Skip to content

Commit

Permalink
Implement packing of time zone aware native types
Browse files Browse the repository at this point in the history
Partially implements #4.
  • Loading branch information
wbolster committed Oct 24, 2014
1 parent 4cc55cc commit 17001a1
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
40 changes: 40 additions & 0 deletions temporenc/temporenc.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,35 @@ def _detect_type(first):
return 'DTSZ', precision, DTSZ_LENGTHS[precision]


class _FixedOffset(datetime.tzinfo):
"""Time zone information for a fixed offset from UTC."""

# Python 2 does not have any concrete tzinfo implementations in its
# standard library, hence this implementation. This implementation
# is based on the examples in the Python docs, in particular:
# https://docs.python.org/3.4/library/datetime.html#tzinfo-objects

ZERO = datetime.timedelta(0)

def __init__(self, minutes):
self._offset = datetime.timedelta(minutes=minutes)
sign = '+' if minutes >= 0 else '-'
hours, minutes = divmod(minutes, 60)
self._name = 'UTC{0}{1:02d}:{2:02d}'.format(sign, hours, minutes)

def utcoffset(self, dt):
return self._offset

def tzname(self, dt):
return self._name

def dst(self, dt):
return self.ZERO

def __repr__(self):
return '<{}>'.format(self._name)


#
# Public API
#
Expand Down Expand Up @@ -432,6 +461,17 @@ def packb(

if isinstance(value, (datetime.datetime, datetime.time)):
handled = True

if tz_offset is None:
# Extract time zone information for tz aware values.
delta = value.utcoffset()
if delta is not None:
# This is a tz aware value. Convert to UTC and
# obtain the offset from UTC. The tzinfo attribute
# is not used, so don't bother setting it.
value = value - delta
tz_offset = int(delta.total_seconds()) // 60

if hour is None:
hour = value.hour
if minute is None:
Expand Down
23 changes: 23 additions & 0 deletions tests/test_temporenc.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,29 @@ def test_native_packing():
assert actual == expected


def test_native_packing_time_zone():

# Python < 3.2 doesn't have concrete tzinfo implementations, so
# use the internal helper class instead to avoid depending on newer
# Python versions (or on pytz).
from temporenc.temporenc import _FixedOffset
tz = _FixedOffset(60) # UTC +01:00

# DTZ
actual = temporenc.packb(
datetime.datetime(1983, 1, 15, 18, 25, 12, 0, tzinfo=tz),
type='DTZ')
expected = from_hex('cf 7e 0e 8b 26 44')
assert actual == expected

# DTSZ (microsecond, since native types have that precision)
actual = temporenc.packb(
datetime.datetime(1983, 1, 15, 18, 25, 12, 123456, tzinfo=tz),
type='DTSZ')
dtsz_us = from_hex('eb df 83 a2 c9 83 c4 81 10')
assert actual == dtsz_us


def test_native_packing_with_overrides():
actual = temporenc.packb(
datetime.datetime(1984, 1, 16, 18, 26, 12, 123456),
Expand Down

0 comments on commit 17001a1

Please sign in to comment.