Skip to content

Commit

Permalink
[Fix] Server WFS: Date time with ISO Date time field format
Browse files Browse the repository at this point in the history
If in the field editor widget setup config, the date time field format is ISO format,
do not use the field format stored in the field editor widget setup config but the
`const QgsDateTimeFieldFormatter::DISPLAY_FOR_ISO_FORMAT`.

Funded by Ifremer https://wwz.ifremer.fr/
  • Loading branch information
rldhont authored and nyalldawson committed Nov 19, 2022
1 parent 1569ec8 commit 38cf6ea
Show file tree
Hide file tree
Showing 13 changed files with 2,319 additions and 385 deletions.
15 changes: 10 additions & 5 deletions src/server/services/wfs/qgswfsdescribefeaturetype.cpp
Expand Up @@ -286,13 +286,18 @@ namespace QgsWfs
const QgsEditorWidgetSetup setup = field.editorWidgetSetup();
if ( setup.type() == QStringLiteral( "DateTime" ) )
{
const QgsDateTimeFieldFormatter fieldFormatter;
// Get editor widget setup config
const QVariantMap config = setup.config();
const QString fieldFormat = config.value( QStringLiteral( "field_format" ), fieldFormatter.defaultFormat( field.type() ) ).toString();
if ( fieldFormat == QLatin1String( "yyyy-MM-dd" ) )
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "date" ) );
else if ( fieldFormat == QLatin1String( "HH:mm:ss" ) )
// Get field format from editor widget setup config
const QString fieldFormat = config.value(
QStringLiteral( "field_format" ),
QgsDateTimeFieldFormatter::defaultFormat( field.type() )
).toString();
// Define type from field format
if ( fieldFormat == QgsDateTimeFieldFormatter::TIME_FORMAT ) // const TIME_FORMAT
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "time" ) );
else if ( fieldFormat == QLatin1String( "yyyy-MM-dd" ) ) // QgsDateTimeFieldFormatter provide a local date format
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "date" ) );
else
attElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "dateTime" ) );
}
Expand Down
26 changes: 23 additions & 3 deletions src/server/services/wfs/qgswfsgetfeature.cpp
Expand Up @@ -1580,15 +1580,35 @@ namespace QgsWfs

if ( setup.type() == QStringLiteral( "DateTime" ) )
{
QgsDateTimeFieldFormatter fieldFormatter;
// For time fields use const TIME_FORMAT
if ( value.type() == QVariant::Time )
{
return value.toTime().toString( QgsDateTimeFieldFormatter::TIME_FORMAT );
}

// Get editor widget setup config
const QVariantMap config = setup.config();
const QString fieldFormat = config.value( QStringLiteral( "field_format" ), fieldFormatter.defaultFormat( value.type() ) ).toString();
// Get field format, for ISO format then use const display format
// else use field format saved in editor widget setup config
const QString fieldFormat =
config.value( QStringLiteral( "field_iso_format" ), false ).toBool() ?
QgsDateTimeFieldFormatter::DISPLAY_FOR_ISO_FORMAT :
config.value( QStringLiteral( "field_format" ), QgsDateTimeFieldFormatter::defaultFormat( value.type() ) ).toString();

// Convert value to date time
QDateTime date = value.toDateTime();

// if not valid try to convert to date with field format
if ( !date.isValid() )
{
date = QDateTime::fromString( value.toString(), fieldFormat );
}
// if the date is valid, convert to string with field format
if ( date.isValid() )
{
return date.toString( fieldFormat );
}
// else provide the value as string
return value.toString();
}
else if ( setup.type() == QStringLiteral( "Range" ) )
{
Expand Down
29 changes: 29 additions & 0 deletions tests/src/python/test_qgsserver_wfs.py
Expand Up @@ -885,6 +885,35 @@ def test_getFeatureFeatureEnvelopeCrs(self):
self.assertEqual([c[:4] for c in e.findall('.//')[0].text.split(' ')], ['7.25', '44.7'])
self.assertEqual([c[:4] for c in e.findall('.//')[1].text.split(' ')], ['7.29', '44.8'])

def test_describeFeatureTypeDateTime(self):
"""Test DescribeFeatureType with dateTime fields"""
project_file = "../qgis_server_accesscontrol/project_with_dimensions.qgs"
self.wfs_request_compare("DescribeFeatureType", '1.0.0', "TYPENAME=Datetime_dim&",
'wfs_describeFeatureType_1_0_0_typename_datetime_dim', project_file=project_file)
self.wfs_request_compare("DescribeFeatureType", '1.1.0', "TYPENAME=Datetime_dim&",
'wfs_describeFeatureType_1_1_0_typename_datetime_dim', project_file=project_file)

self.wfs_request_compare("DescribeFeatureType", '1.1.0', "TYPENAME=datetime_str&",
'wfs_describeFeatureType_1_1_0_typename_datetime_str', project_file=project_file)

def test_GetFeature_with_datetime(self):
""" Test GetFeature with date-time data"""
project_file = "../qgis_server_accesscontrol/project_with_dimensions.qgs"

self.wfs_request_compare(
"GetFeature",
"1.0.0",
"TYPENAME=datetime_str&",
'wfs_getfeature_datetime_str',
project_file=project_file)

self.wfs_request_compare(
"GetFeature",
"1.0.0",
"TYPENAME=Datetime_dim&",
'wfs_getfeature_datetime',
project_file=project_file)


if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,22 @@
Content-Length: 2176
Content-Type: text/xml; charset=utf-8

<schema xmlns:gml="http://www.opengis.net/gml" targetNamespace="http://www.qgis.org/gml" xmlns:qgs="http://www.qgis.org/gml" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ogc="http://www.opengis.net/ogc" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<element type="qgs:Datetime_dimType" name="Datetime_dim" substitutionGroup="gml:_Feature"/>
<complexType name="Datetime_dimType">
<complexContent>
<extension base="gml:AbstractFeatureType">
<sequence>
<element maxOccurs="1" type="gml:PointPropertyType" minOccurs="0" name="geometry"/>
<element type="long" name="fid"/>
<element type="int" nillable="true" name="id"/>
<element type="date" nillable="true" name="date"/>
<element type="time" nillable="true" name="time"/>
<element type="dateTime" nillable="true" name="datetime"/>
<element type="string" nillable="true" name="date_time"/>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
@@ -0,0 +1,22 @@
Content-Length: 2176
Content-Type: text/xml; charset=utf-8

<schema xmlns:gml="http://www.opengis.net/gml" targetNamespace="http://www.qgis.org/gml" xmlns:qgs="http://www.qgis.org/gml" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ogc="http://www.opengis.net/ogc" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd"/>
<element type="qgs:Datetime_dimType" name="Datetime_dim" substitutionGroup="gml:_Feature"/>
<complexType name="Datetime_dimType">
<complexContent>
<extension base="gml:AbstractFeatureType">
<sequence>
<element maxOccurs="1" type="gml:PointPropertyType" minOccurs="0" name="geometry"/>
<element type="long" name="fid"/>
<element type="int" nillable="true" name="id"/>
<element type="date" nillable="true" name="date"/>
<element type="time" nillable="true" name="time"/>
<element type="dateTime" nillable="true" name="datetime"/>
<element type="string" nillable="true" name="date_time"/>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
@@ -0,0 +1,21 @@
Content-Length: 2176
Content-Type: text/xml; charset=utf-8

<schema xmlns:gml="http://www.opengis.net/gml" targetNamespace="http://www.qgis.org/gml" xmlns:qgs="http://www.qgis.org/gml" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ogc="http://www.opengis.net/ogc" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd"/>
<element type="qgs:datetime_strType" name="datetime_str" substitutionGroup="gml:_Feature"/>
<complexType name="datetime_strType">
<complexContent>
<extension base="gml:AbstractFeatureType">
<sequence>
<element maxOccurs="1" type="gml:PointPropertyType" minOccurs="0" name="geometry"/>
<element type="int" nillable="true" name="id"/>
<element type="date" nillable="true" name="date"/>
<element type="time" nillable="true" name="time"/>
<element type="dateTime" nillable="true" name="datetime"/>
<element type="dateTime" nillable="true" name="date_time"/>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
209 changes: 209 additions & 0 deletions tests/testdata/qgis_server/wfs_getfeature_datetime_1_0_0.txt
@@ -0,0 +1,209 @@
Content-Type: text/xml; subtype=gml/2.1.2; charset=utf-8

<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.qgis.org/gml ?">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-7.99492,37.4402 -0.855025,43.0264</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.1">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-7.9293612,43.0263943 -7.9293612,43.0263943</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-7.9293612,43.0263943</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>1</qgs:fid>
<qgs:id>0</qgs:id>
<qgs:date>2021-05-31</qgs:date>
<qgs:time>10:00:00</qgs:time>
<qgs:datetime>2021-05-31 10:00:00</qgs:datetime>
<qgs:date_time>2021-05-31T10:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.2">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-2.63107078,37.98492015 -2.63107078,37.98492015</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-2.63107078,37.98492015</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>2</qgs:fid>
<qgs:id>1</qgs:id>
<qgs:date>2021-06-30</qgs:date>
<qgs:time>07:00:00</qgs:time>
<qgs:datetime>2021-06-30 07:00:00</qgs:datetime>
<qgs:date_time>2021-06-30T07:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.3">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-3.95764769,39.67467133 -3.95764769,39.67467133</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-3.95764769,39.67467133</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>3</qgs:fid>
<qgs:id>2</qgs:id>
<qgs:date>2021-05-31</qgs:date>
<qgs:time>17:00:00</qgs:time>
<qgs:datetime>2021-05-31 17:00:00</qgs:datetime>
<qgs:date_time>2021-05-31T17:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.4">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-0.85502457,37.82787511 -0.85502457,37.82787511</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-0.85502457,37.82787511</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>4</qgs:fid>
<qgs:id>3</qgs:id>
<qgs:date>2021-10-28</qgs:date>
<qgs:time>10:00:00</qgs:time>
<qgs:datetime>2021-10-28 10:00:00</qgs:datetime>
<qgs:date_time>2021-10-28T10:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.5">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-6.16296928,42.57122133 -6.16296928,42.57122133</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-6.16296928,42.57122133</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>5</qgs:fid>
<qgs:id>4</qgs:id>
<qgs:date>2021-07-30</qgs:date>
<qgs:time>01:00:00</qgs:time>
<qgs:datetime>2021-07-30 01:00:00</qgs:datetime>
<qgs:date_time>2021-07-30T01:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.6">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-6.67461865,37.4402079 -6.67461865,37.4402079</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-6.67461865,37.4402079</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>6</qgs:fid>
<qgs:id>5</qgs:id>
<qgs:date>2021-08-29</qgs:date>
<qgs:time>19:00:00</qgs:time>
<qgs:datetime>2021-08-29 19:00:00</qgs:datetime>
<qgs:date_time>2021-08-29T19:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.7">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-3.77557445,40.4568878 -3.77557445,40.4568878</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-3.77557445,40.4568878</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>7</qgs:fid>
<qgs:id>6</qgs:id>
<qgs:date>2021-12-27</qgs:date>
<qgs:time>22:00:00</qgs:time>
<qgs:datetime>2021-12-27 22:00:00</qgs:datetime>
<qgs:date_time>2021-12-27T22:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.8">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-1.98059826,42.02960468 -1.98059826,42.02960468</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-1.98059826,42.02960468</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>8</qgs:fid>
<qgs:id>7</qgs:id>
<qgs:date>2021-09-28</qgs:date>
<qgs:time>09:00:00</qgs:time>
<qgs:datetime>2021-09-28 09:00:00</qgs:datetime>
<qgs:date_time>2021-09-28T09:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.9">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-7.99492105,38.86510435 -7.99492105,38.86510435</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-7.99492105,38.86510435</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>9</qgs:fid>
<qgs:id>8</qgs:id>
<qgs:date>2021-09-28</qgs:date>
<qgs:time>21:00:00</qgs:time>
<qgs:datetime>2021-09-28 21:00:00</qgs:datetime>
<qgs:date_time>2021-09-28T21:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
<gml:featureMember>
<qgs:Datetime_dim fid="Datetime_dim.10">
<gml:boundedBy>
<gml:Box srsName="EPSG:4326">
<gml:coordinates cs="," ts=" ">-6.79827095,37.93340218 -6.79827095,37.93340218</gml:coordinates>
</gml:Box>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
<coordinates xmlns="http://www.opengis.net/gml" cs="," ts=" ">-6.79827095,37.93340218</coordinates>
</Point>
</qgs:geometry>
<qgs:fid>10</qgs:fid>
<qgs:id>9</qgs:id>
<qgs:date>2021-07-30</qgs:date>
<qgs:time>05:00:00</qgs:time>
<qgs:datetime>2021-07-30 05:00:00</qgs:datetime>
<qgs:date_time>2021-07-30T05:00:00</qgs:date_time>
</qgs:Datetime_dim>
</gml:featureMember>
</wfs:FeatureCollection>

0 comments on commit 38cf6ea

Please sign in to comment.