Last active
July 13, 2019 17:19
-
-
Save lernisto/a4c24420429531b362cc8faf3a24f5fb to your computer and use it in GitHub Desktop.
Various ways to get a current timestamp or convert a timestamp to a `datetime`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' | |
I spent way too much time messing with timestamps. | |
A timestamp is the number of seconds elapsed since the epoch. | |
A unix timestamp uses the unix epoch, which is defined as | |
1970-01-01T00:00:00+00:00 | |
Takeaways | |
* the `datetime` module handles two different types of datetimes: | |
1. "naive" times don't know their timezone | |
2. "aware" times do know their timezone | |
* most functions treat a naive time as a local time | |
* `datetime.utcnow()` is evil: it creates a naive time that is not local time | |
* ditto for `datetime.utcfromtimestamp()` | |
* use `datetime.now(UTC)` or `datetime.fromtimestamp(t,UTC)` instead | |
* avoid using naive times | |
''' | |
import time | |
from datetime import datetime as DT | |
from datetime import timezone | |
UTC = timezone.utc | |
EPOCH = DT.fromtimestamp(0,UTC) | |
TEMPLATE ="{:24} {:10d} {:32} {:32} {:32}" | |
print("Unix epoch:",EPOCH.isoformat()) | |
print() | |
def prtime(label,dt,template=TEMPLATE): | |
ts = round(dt.timestamp()) | |
plain = dt.isoformat() | |
local = dt.astimezone().isoformat() | |
utc = dt.astimezone(UTC).isoformat() | |
print(template.format(label,ts,plain,local,utc)) | |
def mktime(label,func,*args,**kw): | |
dt = func(*args,**kw) | |
prtime(label,dt) | |
return dt | |
now = time.time() | |
rnow = round(now) | |
dates = [ mktime(*args) for args in | |
( | |
# naive. wrong unless local time is UTC | |
("DT.utcfromtimestamp(t)",DT.utcfromtimestamp,now), | |
# correct, but naive | |
("DT.fromtimestamp(t)",DT.fromtimestamp,now), | |
# correct and aware | |
("DT.fromtimestamp(t,UTC)",DT.fromtimestamp,now,UTC), | |
# naive. wrong unless local time is UTC | |
("DT.utcnow()",DT.utcnow), | |
# correct, but naive | |
("DT.now()",DT.now), | |
# correct and aware | |
("DT.now(UTC)",DT.now,UTC), | |
) | |
] | |
# these should all represent approximately the same time | |
for d in dates: | |
print(round(d.timestamp())==rnow) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
note that
utcfromtimestamp()
has the same problem asutcnow()