Skip to content

Commit

Permalink
Add support for time zones (#915)
Browse files Browse the repository at this point in the history
* add support for timezones

* mark driver_supports_mode as private

* rename field
  • Loading branch information
rbuffat authored Aug 17, 2020
1 parent a07e6b7 commit 8e982ee
Show file tree
Hide file tree
Showing 22 changed files with 1,388 additions and 518 deletions.
3 changes: 2 additions & 1 deletion fiona/_shim1.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
cdef (int, int, int) get_proj_version()

cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag)
cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField)

from fiona._shim cimport OGR_F_GetFieldAsInteger as OGR_F_GetFieldAsInteger64
from fiona._shim cimport OGR_F_SetFieldInteger as OGR_F_SetFieldInteger64
Expand Down
20 changes: 20 additions & 0 deletions fiona/_shim1.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,23 @@ cdef void set_proj_search_path(object path):

cdef (int, int, int) get_proj_version():
return (-1, -1, -1)


cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag):
cdef int nSecond
nSecond = int(fSecond)
OGR_F_SetFieldDateTime(cogr_feature, iField, nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZFlag)


cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField):
cdef int retval
cdef int nYear = 0
cdef int nMonth = 0
cdef int nDay = 0
cdef int nHour = 0
cdef int nMinute = 0
cdef int nSecond = 0
cdef int nTZFlag = 0

retval = OGR_F_GetFieldAsDateTime(cogr_feature, iField, &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond, &nTZFlag)
return (retval, nYear, nMonth, nDay, nHour, nMinute, float(nSecond), nTZFlag)
2 changes: 2 additions & 0 deletions fiona/_shim2.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
cdef (int, int, int) get_proj_version()
cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag)
cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField)
19 changes: 19 additions & 0 deletions fiona/_shim2.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,22 @@ cdef void set_proj_search_path(object path):

cdef (int, int, int) get_proj_version():
return (-1, -1, -1)


cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag):
OGR_F_SetFieldDateTimeEx(cogr_feature, iField, nYear, nMonth, nDay, nHour, nMinute, fSecond, nTZFlag)


cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField):
cdef int retval
cdef int nYear = 0
cdef int nMonth = 0
cdef int nDay = 0
cdef int nHour = 0
cdef int nMinute = 0
cdef float fSecond = 0.0
cdef int nTZFlag = 0

retval = OGR_F_GetFieldAsDateTimeEx(cogr_feature, iField, &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZFlag)

return (retval, nYear, nMonth, nDay, nHour, nMinute, fSecond, nTZFlag)
2 changes: 2 additions & 0 deletions fiona/_shim22.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
cdef (int, int, int) get_proj_version()
cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag)
cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField)
19 changes: 19 additions & 0 deletions fiona/_shim22.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,22 @@ cdef void set_proj_search_path(object path):

cdef (int, int, int) get_proj_version():
return (-1, -1, -1)


cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag):
OGR_F_SetFieldDateTimeEx(cogr_feature, iField, nYear, nMonth, nDay, nHour, nMinute, fSecond, nTZFlag)


cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField):
cdef int retval
cdef int nYear = 0
cdef int nMonth = 0
cdef int nDay = 0
cdef int nHour = 0
cdef int nMinute = 0
cdef float fSecond = 0.0
cdef int nTZFlag = 0

retval = OGR_F_GetFieldAsDateTimeEx(cogr_feature, iField, &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZFlag)

return (retval, nYear, nMonth, nDay, nHour, nMinute, fSecond, nTZFlag)
2 changes: 2 additions & 0 deletions fiona/_shim3.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ cdef const char* osr_get_name(OGRSpatialReferenceH hSrs)
cdef void osr_set_traditional_axis_mapping_strategy(OGRSpatialReferenceH hSrs)
cdef void set_proj_search_path(object path)
cdef (int, int, int) get_proj_version()
cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag)
cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField)
21 changes: 20 additions & 1 deletion fiona/_shim3.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ cdef extern from "ogr_srs_api.h" nogil:
void OSRSetPROJSearchPaths(const char *const *papszPaths)


from fiona.ogrext2 cimport *
from fiona.ogrext3 cimport *
from fiona._err cimport exc_wrap_pointer
from fiona._err import cpl_errs, CPLE_BaseError, FionaNullPointerError
from fiona.errors import DriverError
Expand Down Expand Up @@ -167,3 +167,22 @@ cdef (int, int, int) get_proj_version():
cdef int patch
OSRGetPROJVersion(&major, &minor, &patch)
return (major, minor, patch)


cdef void set_field_datetime(void *cogr_feature, int iField, int nYear, int nMonth, int nDay, int nHour, int nMinute, float fSecond, int nTZFlag):
OGR_F_SetFieldDateTimeEx(cogr_feature, iField, nYear, nMonth, nDay, nHour, nMinute, fSecond, nTZFlag)


cdef (int, int, int, int, int, int, float, int) get_field_as_datetime(void *cogr_feature, int iField):
cdef int retval
cdef int nYear = 0
cdef int nMonth = 0
cdef int nDay = 0
cdef int nHour = 0
cdef int nMinute = 0
cdef float fSecond = 0.0
cdef int nTZFlag = 0

retval = OGR_F_GetFieldAsDateTimeEx(cogr_feature, iField, &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZFlag)

return (retval, nYear, nMonth, nDay, nHour, nMinute, fSecond, nTZFlag)
39 changes: 19 additions & 20 deletions fiona/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from fiona._env import get_gdal_release_name, get_gdal_version_tuple
from fiona.env import env_ctx_if_needed
from fiona.errors import FionaDeprecationWarning
from fiona.drvsupport import supported_drivers, driver_mode_mingdal
from fiona.drvsupport import (supported_drivers, driver_mode_mingdal, _driver_converts_field_type_silently_to_str,
_driver_supports_field)
from fiona.path import Path, vsi_path, parse_path
from six import string_types, binary_type

Expand Down Expand Up @@ -412,25 +413,23 @@ def _check_schema_driver_support(self):

for field in self._schema["properties"].values():
field_type = field.split(":")[0]
if self._driver == "ESRI Shapefile":
if field_type == "datetime":
raise DriverSupportError("ESRI Shapefile does not support datetime fields")
elif field_type == "time":
raise DriverSupportError("ESRI Shapefile does not support time fields")
elif self._driver == "GPKG":
if field_type == "time":
raise DriverSupportError("GPKG does not support time fields")
elif gdal_version_major == 1:
if field_type == "datetime":
raise DriverSupportError("GDAL 1.x GPKG driver does not support datetime fields")
elif self._driver == "GeoJSON":
if gdal_version_major == 1:
if field_type == "date":
warnings.warn("GeoJSON driver in GDAL 1.x silently converts date to string in non-standard format")
elif field_type == "datetime":
warnings.warn("GeoJSON driver in GDAL 1.x silently converts datetime to string in non-standard format")
elif field_type == "time":
warnings.warn("GeoJSON driver in GDAL 1.x silently converts time to string")

if not _driver_supports_field(self.driver, field_type):
if self.driver == 'GPKG' and gdal_version_major < 2 and field_type == "datetime":
raise DriverSupportError("GDAL 1.x GPKG driver does not support datetime fields")
else:
raise DriverSupportError("{driver} does not support {field_type} "
"fields".format(driver=self.driver,
field_type=field_type))
elif field_type in {'time', 'datetime', 'date'} and _driver_converts_field_type_silently_to_str(self.driver,
field_type):
if self._driver == "GeoJSON" and gdal_version_major < 2 and field_type in {'datetime', 'date'}:
warnings.warn("GeoJSON driver in GDAL 1.x silently converts {} to string"
" in non-standard format".format(field_type))
else:
warnings.warn("{driver} driver silently converts {field_type} "
"to string".format(driver=self.driver,
field_type=field_type))

def flush(self):
"""Flush the buffer."""
Expand Down
Loading

0 comments on commit 8e982ee

Please sign in to comment.