Skip to content

Commit 2d3d6a8

Browse files
committed
[afs] Fix handling of date/datetime field values
1 parent 1104721 commit 2d3d6a8

File tree

4 files changed

+119
-12
lines changed

4 files changed

+119
-12
lines changed

src/providers/arcgisrest/qgsafsshareddata.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ bool QgsAfsSharedData::getFeature( QgsFeatureId id, QgsFeature &f, const QgsRect
108108
// ensure that null values are mapped correctly for PyQGIS
109109
attribute = QVariant( QVariant::Int );
110110
}
111+
112+
// date/datetime fields must be converted
113+
if ( mFields.at( idx ).type() == QVariant::DateTime || mFields.at( idx ).type() == QVariant::Date )
114+
attribute = QgsArcGisRestUtils::parseDateTime( attribute );
115+
111116
if ( !mFields.at( idx ).convertCompatible( attribute ) )
112117
{
113118
QgsDebugMsg( QStringLiteral( "Invalid value %1 for field %2 of type %3" ).arg( attributesData[mFields.at( idx ).name()].toString(), mFields.at( idx ).name(), mFields.at( idx ).typeName() ) );

src/providers/arcgisrest/qgsarcgisrestutils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,21 @@ Qt::BrushStyle QgsArcGisRestUtils::parseEsriFillStyle( const QString &style )
756756
return Qt::SolidPattern;
757757
}
758758

759+
QDateTime QgsArcGisRestUtils::parseDateTime( const QVariant &value )
760+
{
761+
if ( value.isNull() )
762+
return QDateTime();
763+
bool ok = false;
764+
QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
765+
if ( !ok )
766+
{
767+
QgsDebugMsg( QStringLiteral( "Invalid value %1 for datetime" ).arg( value.toString() ) );
768+
return QDateTime();
769+
}
770+
else
771+
return dt;
772+
}
773+
759774
QUrl QgsArcGisRestUtils::parseUrl( const QUrl &url )
760775
{
761776
QUrl modifiedUrl( url );

src/providers/arcgisrest/qgsarcgisrestutils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class QgsArcGisRestUtils
6161
static Qt::PenStyle parseEsriLineStyle( const QString &style );
6262
static Qt::BrushStyle parseEsriFillStyle( const QString &style );
6363

64+
static QDateTime parseDateTime( const QVariant &value );
65+
6466
static QUrl parseUrl( const QUrl &url );
6567
};
6668

tests/src/python/test_provider_afs.py

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@
1818
import tempfile
1919
import shutil
2020

21-
from qgis.PyQt.QtCore import QCoreApplication, Qt, QObject, QDateTime
22-
23-
from qgis.core import (
24-
QgsVectorLayer,
25-
QgsLayerMetadata,
26-
QgsBox3d,
27-
QgsCoordinateReferenceSystem,
28-
QgsApplication,
29-
QgsSettings,
30-
QgsRectangle,
31-
QgsCategorizedSymbolRenderer
32-
)
21+
from qgis.PyQt.QtCore import QCoreApplication, Qt, QObject, QDate
22+
23+
from qgis.core import (NULL,
24+
QgsVectorLayer,
25+
QgsLayerMetadata,
26+
QgsBox3d,
27+
QgsCoordinateReferenceSystem,
28+
QgsApplication,
29+
QgsSettings,
30+
QgsRectangle,
31+
QgsCategorizedSymbolRenderer
32+
)
3333
from qgis.testing import (start_app,
3434
unittest
3535
)
@@ -405,6 +405,91 @@ def testObjectIdDifferentName(self):
405405
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
406406
assert vl.isValid()
407407

408+
def testDateTime(self):
409+
""" Test that datetime fields work correctly """
410+
411+
endpoint = self.basetestpath + '/oid_fake_qgis_http_endpoint'
412+
with open(sanitize(endpoint, '?f=json'), 'wb') as f:
413+
f.write("""
414+
{"currentVersion":10.22,"id":1,"name":"QGIS Test","type":"Feature Layer","description":
415+
"QGIS Provider Test Layer.\n","geometryType":"esriGeometryPoint","copyrightText":"","parentLayer":{"id":0,"name":"QGIS Tests"},"subLayers":[],
416+
"minScale":72225,"maxScale":0,
417+
"defaultVisibility":true,
418+
"extent":{"xmin":-71.123,"ymin":66.33,"xmax":-65.32,"ymax":78.3,
419+
"spatialReference":{"wkid":4326,"latestWkid":4326}},
420+
"hasAttachments":false,"htmlPopupType":"esriServerHTMLPopupTypeAsHTMLText",
421+
"displayField":"LABEL","typeIdField":null,
422+
"fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null},
423+
{"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null},
424+
{"name":"dt","type":"esriFieldTypeDate","alias":"dt","length":8,"domain":null}],
425+
"relationships":[],"canModifyLayer":false,"canScaleSymbols":false,"hasLabels":false,
426+
"capabilities":"Map,Query,Data","maxRecordCount":1000,"supportsStatistics":true,
427+
"supportsAdvancedQueries":true,"supportedQueryFormats":"JSON, AMF",
428+
"ownershipBasedAccessControlForFeatures":{"allowOthersToQuery":true},"useStandardizedQueries":true}""".encode(
429+
'UTF-8'))
430+
431+
with open(sanitize(endpoint, '/query?f=json_where=OBJECTID=OBJECTID_returnIdsOnly=true'), 'wb') as f:
432+
f.write("""
433+
{
434+
"objectIdFieldName": "OBJECTID",
435+
"objectIds": [
436+
1,
437+
2
438+
]
439+
}
440+
""".encode('UTF-8'))
441+
442+
# Create test layer
443+
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
444+
445+
self.assertTrue(vl.isValid())
446+
with open(sanitize(endpoint,
447+
'/query?f=json&objectIds=1,2&inSR=4326&outSR=4326&returnGeometry=true&outFields=OBJECTID,pk,dt&returnM=false&returnZ=false'), 'wb') as f:
448+
f.write("""
449+
{
450+
"displayFieldName": "name",
451+
"fieldAliases": {
452+
"name": "name"
453+
},
454+
"geometryType": "esriGeometryPoint",
455+
"spatialReference": {
456+
"wkid": 4326,
457+
"latestWkid": 4326
458+
},
459+
"fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null},
460+
{"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null},
461+
{"name":"dt","type":"esriFieldTypeDate","alias":"dt","domain":null},
462+
{"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}],
463+
"features": [
464+
{
465+
"attributes": {
466+
"OBJECTID": 1,
467+
"pk": 1,
468+
"dt":1493769600000
469+
},
470+
"geometry": {
471+
"x": -70.332,
472+
"y": 66.33
473+
}
474+
},
475+
{
476+
"attributes": {
477+
"OBJECTID": 2,
478+
"pk": 2,
479+
"dt":null
480+
},
481+
"geometry": {
482+
"x": -68.2,
483+
"y": 70.8
484+
}
485+
}
486+
]
487+
}""".encode('UTF-8'))
488+
489+
features = [f for f in vl.getFeatures()]
490+
self.assertEqual(len(features), 2)
491+
self.assertEqual([f['dt'] for f in features], [QDate(2017, 5, 3), NULL])
492+
408493
def testMetadata(self):
409494
""" Test that metadata is correctly acquired from provider """
410495

0 commit comments

Comments
 (0)