Recipe 3.9. Converting Time Zones
Credit: Gustavo Niemeyer
Problem
You are in Spain and want to get the
correct local (Spanish) time for an event in China.
Solution
Time zone support for datetime is available in the
third-party dateutil package.
Here's one way to set the local time zone, then
print the current time to check that it worked properly:
from dateutil import tzConversion between different time zones is also possible, and often
import datetime
posixstr = "CET-1CEST-2,M3.5.0/02:00,M10.5.0/03:00"
spaintz = tz.tzstr(posixstr)
print datetime.datetime.now(spaintz).ctime( )
necessary in our expanding world. For instance,
let's find out when the next Olympic Games will
start, according to a Spanish clock:
chinatz = tz.tzoffset("China", 60*60*8)
olympicgames = datetime.datetime(2008, 8, 8, 20, 0, tzinfo=chinatz)
print olympicgames.astimezone(spaintz)Discussion
The cryptic string named posixstr is a POSIX-style
representation for the time zone currently being used in Spain. This
string provides the standard and daylight saving time zone names (CST
and CEST), their offsets (UTC+1 and UTC+2), and the day and hour when
DST starts and ends (the last Sunday of March at 2 a.m., and the last
Sunday of October at 3 a.m., respectively). We may check the DST zone
bounds to ensure they are correct:
assert spaintz.tzname(datetime.datetime(2004, 03, 28, 1, 59)) == "CET"All of these asserts should pass silently,
assert spaintz.tzname(datetime.datetime(2004, 03, 28, 2, 00)) == "CEST"
assert spaintz.tzname(datetime.datetime(2004, 10, 31, 1, 59)) == "CEST"
assert spaintz.tzname(datetime.datetime(2004, 10, 31, 2, 00)) == "CET"
confirming that the time zone name switches between the right strings
at the right times.Observe that even though the return to the standard time zone is
scheduled to 3a.m., the moment of the change is marked as 2 a.m. This
happens because of a one-hour gap, between 2 a.m. and 3 a.m., that is
ambiguous. That hour of time happens twice: once in the time zone
CEST, and then again in the time zone CET. Currently, expressing this
moment in an unambiguous way, using the standard Python date and time
support, is not possible. This is why it is recommended that you
store datetime instances in UTC, which is
unambiguous, and only use time zone conversion for display purposes.To do the conversion from China to Spain, we've used
tzoffset to express the fact that China is eight
hours ahead of UTC time (tzoffset is always compared to
UTC, not to a particular
time zone). Notice how the datetime instance is
created with the time zone information. This is always necessary for
converting between two different time zones, even if the given time
is in the local time zone. If you don't create the
instance with the time zone information, you'll get
a ValueError: astimezone( ) cannot be applied to a naive
datetime. datetime instances are always
created naivethey ignore time zone issues
entirelyunless you explicitly create them with a time zone.
For this purpose, dateutil provides the
tzlocal type, which creates instances representing
the platform's idea of the local time zone.Besides the types we have seen so far, dateutil
also provides tzutc, which creates instances
representing UTC; tzfile, which allows using
standard binary time zone files; tzical, which
creates instances representing iCalendar time zones; and many more
besides.
See Also
Documentation about the dateutil module can be
found at ,
and datetime documentation in the
Library Reference.