diff options
Diffstat (limited to 'webmap-import')
-rwxr-xr-x | webmap-import | 65 |
1 files changed, 56 insertions, 9 deletions
diff --git a/webmap-import b/webmap-import index 5515dd0..2939ca1 100755 --- a/webmap-import +++ b/webmap-import @@ -22,6 +22,7 @@ import os import logging import argparse import tempfile +import re from fnmatch import fnmatchcase from pathlib import Path @@ -282,6 +283,52 @@ def parseSubFieldType(name): else: raise Exception(f'Unknown field subtype "{name}"') +# Parse timezone (XXX for GDAL ≥3.8 only) +TZ_RE = re.compile(r'(?:UTC\b)?([\+\-]?)([0-9][0-9]):?([0-9][0-9])', flags=re.IGNORECASE) +def parseTimeZone(tz): + if tz is None: + raise Exception('parseTimeZone(None)') + tz2 = tz.lower() + if tz2 == 'none': + return ogr.TZFLAG_UNKNOWN + elif tz2 == 'local': + return ogr.TZFLAG_LOCALTIME + elif tz2 == 'utc' or tz2 == 'gmt': + return ogr.TZFLAG_UTC + + m = TZ_RE.fullmatch(tz) + if m is None: + raise Exception(f'Invalid timezone "{tz}"') + tzSign = m.group(1) + tzHour = int(m.group(2)) + tzMinute = int(m.group(3)) + if tzHour > 14 or tzMinute >= 60 or tzMinute % 15 != 0: + raise Exception(f'Invalid timezone "{tz}"') + tzFlag = tzHour*4 + int(tzMinute/15) + if tzSign == '-': + tzFlag = 100 - tzFlag + else: + tzFlag += 100 + return tzFlag + +# Pretty-print timezone flag, cf. +# ogr/ogrutils.cpp:OGRGetISO8601DateTime() +def formatTZFlag(tzFlag): + if tzFlag is None: + raise Exception('printTimeZone(None)') + if tzFlag == ogr.TZFLAG_UNKNOWN: + return 'none' + elif tzFlag == ogr.TZFLAG_LOCALTIME: + return 'local' + elif tzFlag == ogr.TZFLAG_UTC: + return 'UTC' + + tzOffset = abs(tzFlag - 100) * 15; + tzHour = int(tzOffset / 60); + tzMinute = int(tzOffset % 60); + tzSign = '+' if tzFlag > 100 else '-' + return f'{tzSign}{tzHour:02}{tzMinute:02}' + # Validate layer creation options and schema. The schema is modified in # place with the parsed result. # (We need the driver of the output dataset to determine capability on @@ -339,9 +386,8 @@ def validateSchema(layers, drvo=None, lco_defaults=None): fld_def2['Type'] = parseFieldType(v) elif k2 == 'subtype': fld_def2['SubType'] = parseSubFieldType(v) - elif k2 == 'tzflag': - pass # TODO - #fld_def2['TZFlag'] = v + elif k2 == 'tz': + fld_def2['TZFlag'] = parseTimeZone(v) elif k2 == 'width' and v is not None and isinstance(v, int): fld_def2['Width'] = v elif k2 == 'precision' and v is not None and isinstance(v, int): @@ -471,10 +517,10 @@ def validateOutputLayer(lyr, srs=None, options=None): if 'TZFlag' in fld: v1 = defn.GetTZFlag() - v2, n2 = fld['TZFlag'] + v2 = fld['TZFlag'] if v1 != v2: - logging.warning('Field "%s" has TZFlag=%d, expected %d (%s)', - fldName, v1, v2, n2) + logging.warning('Field "%s" has TZFlag=%d (%s), expected %d (%s)', + fldName, v1, formatTZFlag(v1), v2, formatTZFlag(v2)) ok = False if 'Precision' in fld: @@ -589,8 +635,9 @@ def createOutputLayer(ds, layername, srs=None, options=None): defn.SetSubType(v) if 'TZFlag' in fld: - v, n = fld['TZFlag'] - logging.debug('Set TZFlag=%d (%s) on output field "%s"', v, n, fldName) + v = fld['TZFlag'] + logging.debug('Set TZFlag=%d (%s) on output field "%s"', + v, formatTZFlag(v), fldName) defn.SetTZFlag(v) if 'Precision' in fld: @@ -674,7 +721,7 @@ def clearLayer(ds, lyr): return layername_esc = escapeIdentifier(lyr.GetName()) - # GDAL <3.9 doesn't have lyr.GetDataset() so we pass the DS along with the layer + # XXX GDAL <3.9 doesn't have lyr.GetDataset() so we pass the DS along with the layer drv = ds.GetDriver() if drv.ShortName == 'PostgreSQL': # https://www.postgresql.org/docs/15/sql-truncate.html |