Skip to content

Commit 1e82e07

Browse files
committed
[afs] Fix handling of date/datetime field values
(cherry-picked from 2d3d6a8)
1 parent 8175c4c commit 1e82e07

File tree

4 files changed

+111
-1
lines changed

4 files changed

+111
-1
lines changed

src/providers/arcgisrest/qgsafsshareddata.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,15 @@ bool QgsAfsSharedData::getFeature( QgsFeatureId id, QgsFeature &f, const QgsRect
107107
// ensure that null values are mapped correctly for PyQGIS
108108
attribute = QVariant( QVariant::Int );
109109
}
110-
mFields.at( idx ).convertCompatible( attribute );
110+
111+
// date/datetime fields must be converted
112+
if ( mFields.at( idx ).type() == QVariant::DateTime || mFields.at( idx ).type() == QVariant::Date )
113+
attribute = QgsArcGisRestUtils::parseDateTime( attribute );
114+
115+
if ( !mFields.at( idx ).convertCompatible( attribute ) )
116+
{
117+
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() ) );
118+
}
111119
attributes[idx] = attribute;
112120
if ( mFields.at( idx ).name() == QStringLiteral( "OBJECTID" ) )
113121
{

src/providers/arcgisrest/qgsarcgisrestutils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,21 @@ QVariantMap QgsArcGisRestUtils::queryServiceJSON( const QUrl &url, QString &erro
506506
return doc.object().toVariantMap();
507507
}
508508

509+
QDateTime QgsArcGisRestUtils::parseDateTime( const QVariant &value )
510+
{
511+
if ( value.isNull() )
512+
return QDateTime();
513+
bool ok = false;
514+
QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
515+
if ( !ok )
516+
{
517+
QgsDebugMsg( QStringLiteral( "Invalid value %1 for datetime" ).arg( value.toString() ) );
518+
return QDateTime();
519+
}
520+
else
521+
return dt;
522+
}
523+
509524
QUrl QgsArcGisRestUtils::parseUrl( const QUrl &url )
510525
{
511526
QUrl modifiedUrl( url );

src/providers/arcgisrest/qgsarcgisrestutils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class QgsArcGisRestUtils
4646
static QByteArray queryService( const QUrl &url, QString &errorTitle, QString &errorText, QgsFeedback *feedback = nullptr );
4747
static QVariantMap queryServiceJSON( const QUrl &url, QString &errorTitle, QString &errorText, QgsFeedback *feedback = nullptr );
4848

49+
static QDateTime parseDateTime( const QVariant &value );
50+
4951
static QUrl parseUrl( const QUrl &url );
5052
};
5153

tests/src/python/test_provider_afs.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,91 @@ def testObjectIdDifferentName(self):
404404
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
405405
assert vl.isValid()
406406

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

0 commit comments

Comments
 (0)