Skip to content

Commit 47af0fc

Browse files
authored
Fix for timezones (singer-io#35)
* bump version * timezone or bust * added unit tests
1 parent de24977 commit 47af0fc

4 files changed

Lines changed: 19 additions & 5 deletions

File tree

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
import subprocess
55

66
setup(name="singer-python",
7-
version='2.1.4',
7+
version='3.0.0',
88
description="Singer.io utility library",
99
author="Stitch",
1010
classifiers=['Programming Language :: Python :: 3 :: Only'],
1111
url="http://singer.io",
1212
install_requires=[
1313
'pendulum==1.2.0',
1414
'simplejson==3.11.1',
15+
'python-dateutil==2.6.0',
1516
],
1617
packages=find_packages(),
1718
package_data = {

singer/transform.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ def string_to_datetime(value):
2525

2626

2727
def unix_milliseconds_to_datetime(value):
28-
return strftime(datetime.datetime.utcfromtimestamp(int(value) * 0.001))
28+
return strftime(datetime.datetime.fromtimestamp(int(value) * 0.001, datetime.timezone.utc))
2929

3030

3131
def unix_seconds_to_datetime(value):
32-
return strftime(datetime.datetime.utcfromtimestamp(int(value)))
32+
return strftime(datetime.datetime.fromtimestamp(int(value), datetime.timezone.utc))
3333

3434

3535
class SchemaMismatch(Exception):

singer/utils.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,27 @@
44
import functools
55
import json
66
import time
7+
import dateutil
78

89
from singer.catalog import Catalog
910

1011
DATETIME_PARSE = "%Y-%m-%dT%H:%M:%SZ"
1112
DATETIME_FMT = "%Y-%m-%dT%H:%M:%S.%fZ"
1213

1314

15+
def strptime_with_tz(dtime):
16+
return dateutil.parser.parse(dtime)
17+
1418
def strptime(dtime):
1519
try:
1620
return datetime.datetime.strptime(dtime, DATETIME_FMT)
1721
except Exception:
1822
return datetime.datetime.strptime(dtime, DATETIME_PARSE)
1923

2024
def strftime(dtime):
21-
return dtime.strftime(DATETIME_FMT)
22-
25+
if dtime.utcoffset() != datetime.timedelta(0):
26+
raise Exception("datetime must be pegged at UTC tzoneinfo")
27+
return dtime.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
2328

2429
def ratelimit(limit, every):
2530
def limitdecorator(func):

tests/test_transform.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,11 @@ def test_unexpected_object_properties(self):
206206
self.assertDictEqual({"good_property": "expected data"}, transformed_data)
207207
self.assertSetEqual(set(["bad_property"]), trans.removed)
208208
self.assertListEqual([], trans.errors)
209+
210+
def test_unix_seconds_to_datetime(self):
211+
self.assertEqual(unix_seconds_to_datetime(0), '1970-01-01T00:00:00.000000Z')
212+
self.assertEqual(unix_seconds_to_datetime(1502722441), '2017-08-14T14:54:01.000000Z')
213+
214+
def test_unix_seconds_to_datetime(self):
215+
self.assertEqual(unix_milliseconds_to_datetime(0), '1970-01-01T00:00:00.000000Z')
216+
self.assertEqual(unix_milliseconds_to_datetime(1502722441000), '2017-08-14T14:54:01.000000Z')

0 commit comments

Comments
 (0)