Skip to content

Instantly share code, notes, and snippets.

@zed
Created April 18, 2015 19:47
Show Gist options
  • Select an option

  • Save zed/ff4e35df3887c1f82002 to your computer and use it in GitHub Desktop.

Select an option

Save zed/ff4e35df3887c1f82002 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
"""Test POSIX definition of "seconds since Epoch".
Assert that posix_time(), calendar.timegm(), and timegm() (mktime() in
UTC) behave the same. Check `datetime.timestamp()` and the explicit
formula (d - epoch) too.
"""
import calendar
import itertools
import os
import time
from contextlib import contextmanager
from datetime import datetime, date, time as datetime_time
try:
from datetime import timezone
except ImportError:
timezone = None
def posix_time(utc_time_tuple):
"""seconds since Epoch as defined by POSIX."""
tm_year = utc_time_tuple.tm_year - 1900
tm_yday = utc_time_tuple.tm_yday - 1
tm_hour = utc_time_tuple.tm_hour
tm_min = utc_time_tuple.tm_min
tm_sec = utc_time_tuple.tm_sec
# http://pubs.opengroup.org/stage7tc1/basedefs/V1_chap04.html#tag_04_15
return (tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
(tm_year-70)*31536000 + ((tm_year-69)//4)*86400 -
((tm_year-1)//100)*86400 + ((tm_year+299)//400)*86400)
@contextmanager
def local_timezone(zonename):
#NOTE: it manipulates global state
oldname = os.environ.get('TZ')
try:
os.environ['TZ'] = zonename
time.tzset()
yield
finally:
if oldname is None:
del os.environ['TZ']
else:
os.environ['TZ'] = oldname
time.tzset()
def timegm(utc_time_tuple):
with local_timezone('UTC'):
return time.mktime(utc_time_tuple)
def eq(a, b, err):
return abs(a - b) < err
if __name__ == "__main__":
seconds_since_epoch = time.time() #NOTE: assume POSIX epoch (fail with TZ=right/UTC)
tt = time.gmtime(seconds_since_epoch)
print(posix_time(tt))
assert posix_time(tt) == int(seconds_since_epoch)
assert calendar.timegm(tt) == int(seconds_since_epoch)
assert timegm(tt) == int(seconds_since_epoch)
if timezone:
aware_dt = datetime.fromtimestamp(seconds_since_epoch, timezone.utc)
assert eq(aware_dt.timestamp(), seconds_since_epoch, 1e-6)
for year, month in itertools.product(range(1970, 1970+401), range(1, 13)):
utc_d = date(year, month, 1)
seconds_since_epoch = (utc_d - date(1970, 1, 1)).days*86400
tt = utc_d.timetuple()
assert posix_time(tt) == seconds_since_epoch
assert calendar.timegm(tt) == seconds_since_epoch
assert timegm(tt) == seconds_since_epoch
if timezone:
aware_dt = datetime.combine(utc_d, datetime_time(tzinfo=timezone.utc))
assert aware_dt.timestamp() == seconds_since_epoch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment