Fix logicalType date conversion
MODIFY
ChangeLog
ChangeLog
+2017-09-16 version 0.14.10
+* Fix logicalType date conversion (@kkirsanov in PR #100, @bitzstein issue #96)
+
2017-09-08 version 0.14.9
* Added time-millis and time-micros logical types (@kkirsanov in PR #98)

MODIFY
fastavro/__init__.py
fastavro/__init__.py
@@ -43,7 +43,7 @@ The only onterface function is iter_avro, example usage::
writer(out, schema, records)
'''
-__version_info__ = (0, 14, 9)
+__version_info__ = (0, 14, 10)
__version__ = '%s.%s.%s' % __version_info__

MODIFY
fastavro/const.py
fastavro/const.py
+import datetime
+
MCS_PER_SECOND = 1000000
MCS_PER_MINUTE = MCS_PER_SECOND * 60
MCS_PER_HOUR = MCS_PER_MINUTE * 60
@@ -5,3 +7,7 @@ MCS_PER_HOUR = MCS_PER_MINUTE * 60
MLS_PER_SECOND = 1000
MLS_PER_MINUTE = MLS_PER_SECOND * 60
MLS_PER_HOUR = MLS_PER_MINUTE * 60
+
+# A date logical type annotates an Avro int, where the int stores the number
+# of days from the unix epoch, 1 January 1970 (ISO calendar).
+DAYS_SHIFT = datetime.date(1970, 1, 1).toordinal()

MODIFY
fastavro/reader.py
fastavro/reader.py
@@ -29,7 +29,7 @@ except ImportError:
)
from fastavro.const import MCS_PER_HOUR, MCS_PER_MINUTE, MCS_PER_SECOND, \
- MLS_PER_HOUR, MLS_PER_MINUTE, MLS_PER_SECOND
+ MLS_PER_HOUR, MLS_PER_MINUTE, MLS_PER_SECOND, DAYS_SHIFT
VERSION = 1
MAGIC = b'Obj' + utob(chr(VERSION))
@@ -157,7 +157,7 @@ def read_timestamp_micros(data, writer_schema=None, reader_schema=None):
def read_date(data, writer_schema=None, reader_schema=None):
- return datetime.date.fromordinal(data)
+ return datetime.date.fromordinal(data + DAYS_SHIFT)
def read_uuid(data, writer_schema=None, reader_schema=None):

MODIFY
fastavro/writer.py
fastavro/writer.py
@@ -18,7 +18,7 @@ except ImportError:
extract_record_type, extract_logical_type
from fastavro.const import MCS_PER_HOUR, MCS_PER_MINUTE, MCS_PER_SECOND,\
- MLS_PER_HOUR, MLS_PER_MINUTE, MLS_PER_SECOND
+ MLS_PER_HOUR, MLS_PER_MINUTE, MLS_PER_SECOND, DAYS_SHIFT
try:
@@ -69,7 +69,7 @@ def prepare_timestamp_micros(data, schema):
def prepare_date(data, schema):
if isinstance(data, datetime.date):
- return data.toordinal()
+ return data.toordinal() - DAYS_SHIFT
else:
return data

MODIFY
tests/test_logical_types.py
tests/test_logical_types.py
@@ -88,7 +88,8 @@ def test_not_logical_ints():
}
binary = serialize(schema, data1)
data2 = deserialize(schema, binary)
- assert (data2['date'] == datetime.date(1, 1, 1))
+ # 1 day since 1970-1-1
+ assert (data2['date'] == datetime.date(1970, 1, 2))
schema_null = {

Fix logicalType date conversion (#100)