| 1 | = RFC 56: OFTTime/OFTDateTime millisecond accuracy = |
| 2 | |
| 3 | Author: Even Rouault[[BR]] |
| 4 | Contact: even dot rouault at spatialys dot com[[BR]] |
| 5 | Status: In development |
| 6 | |
| 7 | == Summary == |
| 8 | |
| 9 | This RFC aims at adding millisecond accuracy to OFTTime and OFTDateTime fields, as |
| 10 | a number of formats support it explicitely or implicitely : MapInfo, |
| 11 | GPX, Atom (GeoRSS driver), GeoPackage, SQLite, PostgreSQL, CSV, GeoJSON, ODS, |
| 12 | XLSX, KML (potentially GML too)... |
| 13 | |
| 14 | == Core changes == |
| 15 | |
| 16 | The OGRField enumeration is modified as such : |
| 17 | |
| 18 | {{{ |
| 19 | typedef union { |
| 20 | [... unchanged ... ] |
| 21 | |
| 22 | struct { |
| 23 | GInt16 Year; |
| 24 | GByte Month; |
| 25 | GByte Day; |
| 26 | GByte Hour; |
| 27 | GByte Minute; |
| 28 | GByte TZFlag; /* 0=unknown, 1=localtime(ambiguous), |
| 29 | 100=GMT, 104=GMT+1, 80=GMT-5, etc */ |
| 30 | GByte Reserved; /* must be set to 0 */ |
| 31 | float Second; /* with millisecond accuracy. at the end of the structure, so as to keep it 12 bytes on 32 bit */ |
| 32 | } Date; |
| 33 | } OGRField; |
| 34 | }}} |
| 35 | |
| 36 | So the "GByte Second" field is removed and replaced by a padding Byte reserved for potential later uses. |
| 37 | A "float Second" field is added. |
| 38 | |
| 39 | On 32 bit builds, the size of OGRField is now 12 bytes instead of 8 bytes. On 64 bit builds, the size of OGRField remains 16 bytes. |
| 40 | |
| 41 | === New/modified methods === |
| 42 | |
| 43 | OGRFeature::SetFieldAsDateTime() methods that took a int nSecond now take a float fSecond parameter. |
| 44 | The GetFieldAsDateTime() method that took a int* pnSecond is kept, and a new GetFieldAsDateTime() method that |
| 45 | takes a float* pfSecond is added. |
| 46 | |
| 47 | * In OGRFeature class : |
| 48 | {{{ |
| 49 | int GetFieldAsDateTime( int i, |
| 50 | int *pnYear, int *pnMonth, int *pnDay, |
| 51 | int *pnHour, int *pnMinute, int *pnSecond, |
| 52 | int *pnTZFlag ); /* unchanged from GDAL 1.X */ |
| 53 | int GetFieldAsDateTime( int i, |
| 54 | int *pnYear, int *pnMonth, int *pnDay, |
| 55 | int *pnHour, int *pnMinute, float *pfSecond, |
| 56 | int *pnTZFlag ); /* new */ |
| 57 | void SetField( int i, int nYear, int nMonth, int nDay, |
| 58 | int nHour=0, int nMinute=0, float fSecond=0.f, |
| 59 | int nTZFlag = 0 ); /* modified */ |
| 60 | void SetField( const char *pszFName, |
| 61 | int nYear, int nMonth, int nDay, |
| 62 | int nHour=0, int nMinute=0, float fSecond=0.f, |
| 63 | int nTZFlag = 0 ); /* modified */ |
| 64 | }}} |
| 65 | |
| 66 | OGRFeature::GetFieldAsString() is modified to output milliseconds if the Second member of OGRField.Date is not integral |
| 67 | |
| 68 | OGRParseDate() is modified to parse second as floating point number. |
| 69 | |
| 70 | The following utility functions have their signature modified to take a OGRField (instead of the full year, month, day, hour, minute, second, TZFlag decomposition) and accept decimal seconds as input/output : |
| 71 | {{{ |
| 72 | int CPL_DLL OGRParseXMLDateTime( const char* pszXMLDateTime, |
| 73 | OGRField* psField ); |
| 74 | int CPL_DLL OGRParseRFC822DateTime( const char* pszRFC822DateTime, |
| 75 | OGRField* psField ); |
| 76 | char CPL_DLL * OGRGetRFC822DateTime(const OGRField* psField); |
| 77 | char CPL_DLL * OGRGetXMLDateTime(const OGRField* psField); |
| 78 | }}} |
| 79 | |
| 80 | === C API changes === |
| 81 | |
| 82 | Only additions : |
| 83 | {{{ |
| 84 | int CPL_DLL OGR_F_GetFieldAsDateTimeEx( OGRFeatureH hFeat, int iField, |
| 85 | int *pnYear, int *pnMonth, int *pnDay, |
| 86 | int *pnHour, int *pnMinute, float *pfSecond, |
| 87 | int *pnTZFlag ); |
| 88 | void CPL_DLL OGR_F_SetFieldDateTimeEx( OGRFeatureH, int, |
| 89 | int, int, int, int, int, float, int ); |
| 90 | }}} |
| 91 | |
| 92 | == Changes in drivers == |
| 93 | |
| 94 | The following drivers now accept milliseconds as input/output : |
| 95 | |
| 96 | * GeoJSON |
| 97 | * CSV |
| 98 | * PG |
| 99 | * PGDump (output only) |
| 100 | * CartoDB |
| 101 | * GeoPackage |
| 102 | * SQLite |
| 103 | * MapInfo .tab and .mif |
| 104 | * LIBKML |
| 105 | * ODS |
| 106 | * XLSX |
| 107 | * GeoRSS (Atom format) |
| 108 | * GPX |
| 109 | |
| 110 | == Changes in SWIG bindings == |
| 111 | |
| 112 | Feature.GetFieldAsDateTime() and Feature.SetFieldAsDateTime() now takes/returns a floating point number for seconds |
| 113 | |
| 114 | == Compatibility == |
| 115 | |
| 116 | This modifies the C/C++ API and ABI. |
| 117 | |
| 118 | Output of above mentionned drivers will now include milliseconds if a DateTime/Time field has such precision. |
| 119 | |
| 120 | == Related ticket == |
| 121 | |
| 122 | The need came from http://trac.osgeo.org/gdal/ticket/2680 for MapInfo driver. |
| 123 | |
| 124 | == Documentation == |
| 125 | |
| 126 | All new/modified methods are documented. MIGRATION_GUIDE.TXT is updated with a new |
| 127 | section for this RFC. |
| 128 | |
| 129 | == Testing == |
| 130 | |
| 131 | The various aspects of this RFC are tested: |
| 132 | * core changes |
| 133 | * driver changes |
| 134 | |
| 135 | == Implementation == |
| 136 | |
| 137 | Implementation will be done by Even Rouault ([http://spatialys.com Spatialys]). |
| 138 | |
| 139 | The proposed implementation lies in the "subsecond_accuracy" branch of the |
| 140 | https://github.com/rouault/gdal2/tree/subsecond_accuracy repository. |
| 141 | |
| 142 | The list of changes : https://github.com/rouault/gdal2/compare/subsecond_accuracy |
| 143 | |
| 144 | == Voting history == |
| 145 | |
| 146 | TBD |