slashdottir slashdottir - 22 days ago 10
Python Question

How to convert a datetime from one arbitrary timezone to another arbitrary timezone

Let's say I receive an arbitrary datetime object in a request, like this, which could be coming from any possible timezone - I don't know which one.
For the sake of example, pretend it comes from the East Coast

import pytz
from colander import iso8601
...
ests1 = iso8601.parse_date('2016-04-01T00:00:00.0000-04:00')


pretend ests1 is the object that comes in

Using pytz, I can find out a bit about it's timezone

etz = ests1.timetz() # 00:00:00-04:00
etzi = ests1.tzinfo # <FixedOffset '-04:00' datetime.timedelta(-1, 72000)>
etzn = ests1.tzname() # '-04:00' # EST
edst = ests1.dst() # '0:00:00'


Note that no matter what date ests1 is - dst() always seems to return the same value

I would like to do something like this:

psts1 = pytz.timezone(etzn
).localize(dtime.datetime.fromtimestamp(ests1)
).astimezone(pytz.timezone('US/Pacific'))


but that just results in

UnknownTimeZoneError: '-04:00'


I have also tried this:

def convert_dt_to_pstz(dt):
pstoffset = -25200 # -7 * 60 * 60 - but what about DST? how do we tell which offset to use? -8 or -7
return dt.astimezone(tzoffset(None,pstoffset)) # convert to PST


But the problem with that is I don't know how to tell if the date needs to be adjusted for daylight savings time.

I also tried this:

utc_date = ests1.astimezone(pytz.utc) # 2016-04-01T04:00:00+00:00
ptz = pytz.timezone('US/Pacific')
new_date = utc_date.replace(tzinfo=ptz) # 2016-04-01T04:00:00-07:53


But look at the strange result for new_date: -07:53
??

Please note that I cannot use any information corresponding to "now" or the location of the server as it could be anywhere

Answer

To convert a timezone-aware datetime object into a different timezone, use datetime.astimezone() method:

pacific_time = ests1.astimezone(pytz.timezone('US/Pacific'))

In general, pytz docs recommend to call pytz.timezone('US/Pacific').normalize() on the result but you don't need it here because ests1 timezone has a fixed utc offset.