I’m trying to understand why I’m getting these results when converting time zones to UTC:
In [74]: d1 = datetime(2007, 12, 5, 6, 30,tzinfo=pytz.timezone('US/Pacific'))
In [75]: d1
Out[75]: datetime.datetime(2007, 12, 5, 6, 30, tzinfo=<DstTzInfo 'US/Pacific' LMT-1 day, **16:07:00 STD**>)
In [76]: d1.astimezone(pytz.utc)
Out[76]: datetime.datetime(2007, 12, 5, 14, 23, tzinfo=<UTC>)
Why did 6:30am become 2:23pm?
On the other hand, if I use the following approach, I get the expected result:
In [90]: d2 = datetime(2007, 12, 5, 6, 30)
In [91]: uspac = pytz.timezone('US/Pacific')
In [92]: d2_aware = uspac.localize(d2)
In [94]: d2_aware.astimezone(pytz.utc)
Out[94]: datetime.datetime(2007, 12, 5, 14, 30, tzinfo=<UTC>)
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
What I got is just a workaround, the simple rule is Never create datetime with timezone info by using datetime().
This sample would give you a hint for this. As you see, you could avoid the unexpected difference, once and only you make “naive” datetime (it is, datetime without timezone info) and then localize it (it is not applied when you create datetime on UTC though) :
import pytz
from datetime import datetime
# make Jan 1 on PDT -> UTC
pdt = pytz.timezone("America/Los_Angeles")
pdtnow1 = datetime(2014,1,1, tzinfo=pdt)
pdtnow2 = pdt.localize(datetime(2014,1,1))
pytz.utc.normalize(pdtnow1)
# > datetime.datetime(2014, 1, 1, 7, 53, tzinfo=<UTC>)
pytz.utc.normalize(pdtnow2)
# > datetime.datetime(2014, 1, 1, 8, 0, tzinfo=<UTC>)
# make Jan 1 on UTC -> PDT
utcnow1 = datetime(2014,1,1, tzinfo=pytz.utc)
utcnow2 = pytz.utc.localize(datetime(2014,1,1))
pdt.normalize(utcnow1)
# > datetime.datetime(2013, 12, 31, 16, 0,
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
pdt.normalize(utcnow2)
# > datetime.datetime(2013, 12, 31, 16, 0,
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
Method 2
From the partial documentation:
http://pytz.sourceforge.net/#localized-times-and-date-arithmetic
Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones. […] It is safe for timezones without daylight saving transitions though, such as UTC. […] The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.
Method 3
Unfortunately, creating timezone aware dates using this method doesn’t work.
If you are using Django, they have a utility function, make_aware, that does this correctly.
from django.utils.timezone import make_aware
from pytz import timezone
unaware_datetime = datetime(2007, 12, 5)
local_datetime = make_aware(datetime(2007, 12, 5))
specific_datetime = make_aware(datetime(2007, 12, 5), timezone("Australia/Melbourne"))
If you’re not using Django, then the source code for the make_aware function may give you inspiration.
Method 4
I’m revisiting some questions about date and time to see if some of the newer libraries prove more helpful in situations like this (or not). pendulum is one that stores timezone with date and time, making it particularly valuable in situations such as this.
>>> import pendulum >>> d1 = pendulum.datetime(2007,12,5,6,30, tzinfo='US/Pacific') >>> d1 <Pendulum [2007-12-05T06:30:00-08:00]> >>> d1.timezone <Timezone [US/Pacific]> >>> d1.astimezone(tz='UTC') <Pendulum [2007-12-05T14:30:00+00:00]>
Lots of other sweet features too.
Method 5
Print d2_aware before .astimezone and you see PST-1 (Pacific Standard Time) but in first example you have LMT-1 (Local Mean Time) – and probably it can give 7 minutes difference.
But I don’t know why pytz use different timezones.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0