timeutils: avoid passing leap second to datetime

Python datetime module does not support leap seconds [1]. The best thing
we can do without switching API to using another time module is to
avoid passing leap seconds to underlying python module.

Note: next leap second is scheduled for June 30 [2].

[1]: http://bugs.python.org/issue23574
[2]: http://www.usatoday.com/story/tech/2015/01/08/computer-chaos-feares/21433363/

Closes-Bug: #1427212
Change-Id: I7ffd8121cb20f3742e8e9cd7d4b8f0f15fa6ca9a
This commit is contained in:
Ihar Hrachyshka 2015-03-02 13:24:58 +01:00
parent cb88d17a36
commit c50d8161ac
2 changed files with 20 additions and 1 deletions

View File

@ -191,6 +191,18 @@ class TimeUtilsTest(test_base.BaseTestCase):
backagain = timeutils.unmarshall_time(binary)
self.assertEqual(now, backagain)
def test_unmarshall_time_leap_second(self):
leap_dict = dict(day=30, month=6, year=2015,
hour=23, minute=59,
second=timeutils._MAX_DATETIME_SEC + 1,
microsecond=0)
leap_time = timeutils.unmarshall_time(leap_dict)
leap_dict.update(second=timeutils._MAX_DATETIME_SEC)
expected = timeutils.unmarshall_time(leap_dict)
self.assertEqual(expected, leap_time)
def test_delta_seconds(self):
before = timeutils.utcnow()
after = before + datetime.timedelta(days=7, seconds=59,

View File

@ -31,6 +31,8 @@ _ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f'
_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND
_MAX_DATETIME_SEC = 59
# Use monotonic time in stopwatches if we can get at it...
#
# PEP @ https://www.python.org/dev/peps/pep-0418/
@ -211,12 +213,17 @@ def marshall_now(now=None):
def unmarshall_time(tyme):
"""Unmarshall a datetime dict."""
# NOTE(ihrachys): datetime does not support leap seconds,
# so the best thing we can do for now is dropping them
# http://bugs.python.org/issue23574
second = min(tyme['second'], _MAX_DATETIME_SEC)
return datetime.datetime(day=tyme['day'],
month=tyme['month'],
year=tyme['year'],
hour=tyme['hour'],
minute=tyme['minute'],
second=tyme['second'],
second=second,
microsecond=tyme['microsecond'])