Specifically, given the timezone of my server (system time perspective) and a timezone input, how do I calculate the system time as if it were in that new timezone (regardless of daylight savings, etc)?
import datetime
current_time = datetime.datetime.now() #system time
server_timezone = "US/Eastern"
new_timezone = "US/Pacific"
current_time_in_new_timezone = ???
If you know your origin timezone and the new timezone you want to convert it to, first use pytz.localize
to handle any localization (e.g. for daylight savings, etc), then use pytz.timezone
to create timezone objects, and finally use datetime.astimezone(timezone)
for an easy calculation. For example:
import datetime
import pytz # new import
my_timestamp = datetime.datetime.now() # some timestamp
old_timezone = pytz.timezone("US/Eastern")
new_timezone = pytz.timezone("US/Pacific")
# returns datetime in the new timezone
my_timestamp_in_new_timezone = old_timezone.localize(my_timestamp).astimezone(new_timezone)
And of course, if all you want is the current time in a specific timezone, you can pass that timezone directly into datetime.now() to get the timestamp. Like this:
datetime.datetime.now(new_timezone)
Now with all that said, I strongly recommend storing all your timestamps in UTC as a system standard, and avoid the whole DST problem. For context on this, see: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/
And to know how difficult it is to deal with time calculations in general: http://yourcalendricalfallacyis.com
How do you convert datetime/timestamp from one timezone to another timezone?
There are two steps:
Create an aware datetime objects from the system time and timezone e.g., to get the current system time in the given timezone:
#!/usr/bin/env python
from datetime import datetime
import pytz
server_timezone = pytz.timezone("US/Eastern")
server_time = datetime.now(server_timezone) # you could pass *tz* directly
Note: datetime.now(server_timezone)
works even during ambiguous times e.g., during DST transitions while server_timezone.localize(datetime.now())
may fail (50% chance).
If you are sure that your input time exists in the server's timezone and it is unique then you could pass is_dst=None
to assert that:
server_time = server_timezone.localize(naive_time, is_dst=None)
It raises an exception for invalid times.
If it is acceptable to ignore upto a day error (though typically an error due to DST is around an hour) then you could drop is_dst
parameter:
server_time = server_timezone.normalize(server_timezone.localize(naive_time))
.normalize()
is called to adjust non-existing times (local time in the gap, during "spring forward" transitions). If the time zone rules haven't changed; your server shouldn't generate non-existing times. See "Can I just always set is_dst=True?"
Convert an aware datetime object to the target timezone tz
:
tz = pytz.timezone("US/Pacific")
server_time_in_new_timezone = server_time.astimezone(tz)