Lately I’ve been getting sick of working with datetimes and timezones in Python. The standard library offers many different conversion routines, but does not prescribe a best practice way to deal with them. Luckily, Armin Ronacher did in his article Dealing with Timezones in Python.
The summary is to never ever work with local datetimes. When a local datetime is input, immediately convert it to universal time and only ever store or calculate with those. Only when presenting datetimes to the end user, convert them to local time again.
This seems simple enough, alright. But to actually do it in Python, you still
have to think about how to implement it correctly. Every. Single. Time.
pytz
does help a bit here, but it still isn’t trivial. It should be.
Meet Times
, a very small Python library to
deal with conversions from universal to local timezones and vice versa. It’s
focused on simplicity and opinionated about what is good practice.
Example use ¶
Imagine you’re building a web app that allows your users to set an alarm. Say
that someone in the Netherlands sets an alarm to 9:30 am. You can use times
to simplify this:
>>> import times >>> import datetime >>> >>> local_time = datetime.datetime(2012, 2, 3, 9, 30, 0) >>> universal_time = times.to_universal(local_time, 'Europe/Amsterdam') >>> universal_time datetime.datetime(2012, 2, 3, 8, 30)
Now, this universal_time
variable is safe to store or calculate with.
Once you want to show this date to the user again, simply format it for the given timezone:
>>> times.format(universal_time, 'Europe/Amsterdam') '2012-02-03 09:30:00+0100'
If your app allows users to share alerts, it is just as easy to present the alert date to an end user in New Zealand as well:
>>> times.format(universal_time, 'Pacific/Auckland') '2012-02-03 21:30:00+1300'
Current time ¶
If you ever need to record the current time, you can use
>>> times.now() datetime.datetime(2012, 2, 2, 16, 4, 40, 283090)
Which is actually just an alias to datetime.datetime.utcnow()
.
Converting from other sources ¶
I’ve added the ability to create universal times from two other sources: UNIX
timestamps and date strings. To use any of these, simply pass them to the
to_universal
function, like so:
>>> time.time() 1328729274.982 >>> times.to_universal(1328729274.982) datetime.datetime(2012, 2, 8, 19, 27, 54, 982000)
Note that UNIX timestamps must be in UTC (which the output of time.time()
is). Local UNIX timestamps are not accepted.
To create universal times from string representations, Times
uses the
advanced parser from the python-dateutil
library. Time zones are
automatically recognized if such info is encoded in the string representation.
In any other case, you are required to provide it explicitly. Two examples to
illustrate both variants:
>>> # Timezone-aware date formats don't require a source timezone >>> date_str = '2012-02-08 19:27:54+0100' >>> times.to_universal(date_str) datetime.datetime(2012, 2, 8, 18, 27, 54) >>> # Timezone-less date formats require an explicit source timezone >>> date_str = '2012-02-08 19:27:54' >>> times.to_universal(date_str, 'Asia/Singapore') datetime.datetime(2012, 2, 8, 11, 27, 54)
Installing ¶
Times
is on PyPI (link), so just pip
install times
to use it.
Of course, you can fork me on GitHub.
As usual, Times
is licensed under the liberal terms of the BSD license.