Python datetime conversions
Recently for my work I had to do some date/time-wrangling in Python. We have a database containing unix timestamp values, and the front-end application needs to talk local time. The necessary conversions aren’t so complicated, but Python makes life a bit harder by having three relevant modules, three relevant data types (not matching the modules), and a complicated web of conversion possibilities between them.
For instance:
- the
datetime
class lives in thedatetime
module; careful with your imports, you will want both! - the
datetime
module has atime
class, but there’s also atime
module - the documentation talks at different places about “time tuples” and also about “
time.struct_time
” objects; they’re the same thing - to convert a unix timestamp to a time tuple representing UTC time, you use
time.gmtime()
; for the reverse conversion, you usecalendar.timegm()
(this is the only place you’ll use thecalendar
module) - to get now you use:
time.localtime()
if you want a timetupletime.time()
if you want a unix timestampdatetime.now()
if you want a datetime objecttime.gmtime()
if you want a timetuple representing UTC timedatetime.utcnow()
if you want a datetime object representing UTC time- a crowbar if necessary
- to build a
datetime
object from a time-tuple, you can set the fields one-by-one… or you can slice the time-tuple and unpack the list:datetime(*a_time_tuple[:6])
In other words, there’s a lot of fiddly detail to remember. So I made a chart.
It’s formatted for a4 paper and prints nicely. I used the incredible LaTeX drawing system TikZ. (On my screen the arrows have a little glitch at start and finish, but it doesn’t appear in my printout. Possibly a TikZ bug? Not sure.)
Note that it doesn’t show everything you can do; apart from the more egregious omissions (like timezone handling on datetime
objects, which actually seems quite straight-forward but didn’t fit nicely into the design), I didn’t include arrows for nonsensical operations. For example you could feed a UTC time-tuple into time.mktime()
(which takes a localtime time-tuple to a unix timestamp), but the result would be nonsense: the number of seconds since a date similar to, but probably not quite the same as, the unix epoch.
Comments
Glad you like it! (Of course let me know if anything is wrong or missing...)
Using UTC: the tricky thing is, the people using the app speak localtime. So at least at the UI layer you need to translate back and forth. (And under certain circumstances, the dates you get out of a database might be automagically localtimed as well, gr.)
I assume you handle double summer time by putting in a tzinfo
object (and writing that baby must be a nightmare); I steered entirely clear of that, the naive objects were enough headache...
apt-get source tzdata and poke through the files there, there's all sorts of bits of history of time changes. There's actually something similar I think that goes into more detail, but I'm failing to find it at the moment.
This looks suspiciously like a PHP library.
Wow, man, we are printing it and putting on the wall in our office. Thanks! Of course, you DO know that you really want to use UTC everywhere, unless the circumstances really force you to use local time, for the sake of your sanity, right?
The
datetime
library is rather complex, but the domain itself is really complicated, and Python's implementation is pretty complete. For example, did you know that it allows you to (easilishly) handle stuff like the double summer time the British fancied during WW2?