Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[afs] Fix handling of date/datetime field values
(cherry-picked from 2d3d6a8)
  • Loading branch information
nyalldawson committed May 3, 2018
1 parent 8175c4c commit 1e82e07
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/providers/arcgisrest/qgsafsshareddata.cpp
Expand Up @@ -107,7 +107,15 @@ bool QgsAfsSharedData::getFeature( QgsFeatureId id, QgsFeature &f, const QgsRect
// ensure that null values are mapped correctly for PyQGIS
attribute = QVariant( QVariant::Int );
}
mFields.at( idx ).convertCompatible( attribute );

// date/datetime fields must be converted
if ( mFields.at( idx ).type() == QVariant::DateTime || mFields.at( idx ).type() == QVariant::Date )
attribute = QgsArcGisRestUtils::parseDateTime( attribute );

if ( !mFields.at( idx ).convertCompatible( attribute ) )
{
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() ) );
}
attributes[idx] = attribute;
if ( mFields.at( idx ).name() == QStringLiteral( "OBJECTID" ) )
{
Expand Down
15 changes: 15 additions & 0 deletions src/providers/arcgisrest/qgsarcgisrestutils.cpp
Expand Up @@ -506,6 +506,21 @@ QVariantMap QgsArcGisRestUtils::queryServiceJSON( const QUrl &url, QString &erro
return doc.object().toVariantMap();
}

QDateTime QgsArcGisRestUtils::parseDateTime( const QVariant &value )
{
if ( value.isNull() )
return QDateTime();
bool ok = false;
QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
if ( !ok )
{
QgsDebugMsg( QStringLiteral( "Invalid value %1 for datetime" ).arg( value.toString() ) );
return QDateTime();
}
else
return dt;
}

QUrl QgsArcGisRestUtils::parseUrl( const QUrl &url )
{
QUrl modifiedUrl( url );
Expand Down
2 changes: 2 additions & 0 deletions src/providers/arcgisrest/qgsarcgisrestutils.h
Expand Up @@ -46,6 +46,8 @@ class QgsArcGisRestUtils
static QByteArray queryService( const QUrl &url, QString &errorTitle, QString &errorText, QgsFeedback *feedback = nullptr );
static QVariantMap queryServiceJSON( const QUrl &url, QString &errorTitle, QString &errorText, QgsFeedback *feedback = nullptr );

static QDateTime parseDateTime( const QVariant &value );

static QUrl parseUrl( const QUrl &url );
};

Expand Down
85 changes: 85 additions & 0 deletions tests/src/python/test_provider_afs.py
Expand Up @@ -404,6 +404,91 @@ def testObjectIdDifferentName(self):
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
assert vl.isValid()

def testDateTime(self):
""" Test that datetime fields work correctly """

endpoint = self.basetestpath + '/oid_fake_qgis_http_endpoint'
with open(sanitize(endpoint, '?f=json'), 'wb') as f:
f.write("""
{"currentVersion":10.22,"id":1,"name":"QGIS Test","type":"Feature Layer","description":
"QGIS Provider Test Layer.\n","geometryType":"esriGeometryPoint","copyrightText":"","parentLayer":{"id":0,"name":"QGIS Tests"},"subLayers":[],
"minScale":72225,"maxScale":0,
"defaultVisibility":true,
"extent":{"xmin":-71.123,"ymin":66.33,"xmax":-65.32,"ymax":78.3,
"spatialReference":{"wkid":4326,"latestWkid":4326}},
"hasAttachments":false,"htmlPopupType":"esriServerHTMLPopupTypeAsHTMLText",
"displayField":"LABEL","typeIdField":null,
"fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null},
{"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null},
{"name":"dt","type":"esriFieldTypeDate","alias":"dt","length":8,"domain":null}],
"relationships":[],"canModifyLayer":false,"canScaleSymbols":false,"hasLabels":false,
"capabilities":"Map,Query,Data","maxRecordCount":1000,"supportsStatistics":true,
"supportsAdvancedQueries":true,"supportedQueryFormats":"JSON, AMF",
"ownershipBasedAccessControlForFeatures":{"allowOthersToQuery":true},"useStandardizedQueries":true}""".encode(
'UTF-8'))

with open(sanitize(endpoint, '/query?f=json_where=OBJECTID=OBJECTID_returnIdsOnly=true'), 'wb') as f:
f.write("""
{
"objectIdFieldName": "OBJECTID",
"objectIds": [
1,
2
]
}
""".encode('UTF-8'))

# Create test layer
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')

self.assertTrue(vl.isValid())
with open(sanitize(endpoint,
'/query?f=json&objectIds=1,2&inSR=4326&outSR=4326&returnGeometry=true&outFields=OBJECTID,pk,dt&returnM=false&returnZ=false'), 'wb') as f:
f.write("""
{
"displayFieldName": "name",
"fieldAliases": {
"name": "name"
},
"geometryType": "esriGeometryPoint",
"spatialReference": {
"wkid": 4326,
"latestWkid": 4326
},
"fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null},
{"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null},
{"name":"dt","type":"esriFieldTypeDate","alias":"dt","domain":null},
{"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}],
"features": [
{
"attributes": {
"OBJECTID": 1,
"pk": 1,
"dt":1493769600000
},
"geometry": {
"x": -70.332,
"y": 66.33
}
},
{
"attributes": {
"OBJECTID": 2,
"pk": 2,
"dt":null
},
"geometry": {
"x": -68.2,
"y": 70.8
}
}
]
}""".encode('UTF-8'))

features = [f for f in vl.getFeatures()]
self.assertEqual(len(features), 2)
self.assertEqual([f['dt'] for f in features], [QDate(2017, 5, 3), NULL])

def testMetadata(self):
""" Test that metadata is correctly acquired from provider """

Expand Down

0 comments on commit 1e82e07

Please sign in to comment.