datetime seems to be broken WRT timezones (even when you add them)
Barry Scott
barry at barrys-emacs.org
Tue Feb 11 16:17:44 EST 2020
> On 10 Feb 2020, at 23:01, Python <python at bladeshadow.org> wrote:
>
> As best I can tell, Python has no means to make use of the system's
> timezone info. In order to make datetime "timezone aware", you need
> to manually create a subclass of datetime.tzinfo, whose methods return
> the correct values for the timezone you care about. In the general
> case, this is hard, but since the timezone my dates are in is always
> GMT, it's no problem:
>
> class GMT(datetime.tzinfo):
> def utcoffset(self, dt):
> return datetime.timedelta(hours=0)
> def dst(self, dt):
> return datetime.timedelta(minutes=0)
> def tzname(self, dt):
> return "GMT"
>
> Now, you can instantiate a datetime.datetime object with the times you
> want, and pass an instance of this class as the tzinfo argument to the
> constructor. Also no problem:
>>>> dt = datetime.datetime(2020, 1, 31, 1, 30, 45, 987654, GMT())
>>>> dt
> datetime.datetime(2020, 1, 31, 1, 30, 45, 987654, tzinfo=<__main__.GMT object at 0x7f9084e2add0>)
>>>> print dt
> 2020-01-31 01:30:45.987654+00:00
>
> Note the tzinfo object, and the +00:00 indicating this is indeed in
> GMT. If you create a "naive" datetime object, you don't get that:
>
>>>> xy = datetime.datetime(2020, 1, 31, 1, 30, 45, 987654)
>>>> xy
> datetime.datetime(2020, 1, 31, 1, 30, 45, 987654)
>>>> print xy
> 2020-01-31 01:30:45.987654
>
>
> So far, so good. However, when you go to use this object, the time it
> represents is in fact wrong. For example:
>
>>>> print dt.strftime("%s")
> 1580452245
>
> Using the date command, we can easily see that it is incorrect:
>
> # Ask for UTC, gives the wrong time
> $ date -u -d "@1580452245"
> Fri Jan 31 06:30:45 UTC 2020
>
> # Ask for local time, gives the time I specified... which should have
> # been in GMT, but is in my local timezone
> $ date -d "@1580452245"
> Fri Jan 31 01:30:45 EST 2020
>
> And the correct value should have been:
> $ date -d "2020-01-31 1:30:45 GMT" +%s
> 1580434245
>
> Same results under Python2.7 or Python3.
>
> :( :( :(
>
> I suspect this is because the underlying implementation uses
> strftime() which takes struct tm, which has no field to contain the
> timezone info, and does not do the necessary conversion before handing
> it off. I'm not sure what the date command is doing differently, but
> it clearly is able to get the correct answer.
>
> Does Python have an alternative way to do the above, with correct
> results?
I found that there are two useful PyPi packages to help with time zones.
pytz and tzlocal.
Here is a piece of code that I use to be timezone aware for UTC and the
local time zone. It works for Windows, macOS and unix thanks.
import datetime
import pytz
import tzlocal
def utcDatetime( timestamp ):
return pytz.utc.localize( datetime.datetime.utcfromtimestamp( timestamp ) )
def localDatetime( datetime_or_timestamp ):
if type(datetime_or_timestamp) in (int, float):
dt = utcDatetime( datetime_or_timestamp )
else:
dt = datetime_or_timestamp
local_timezone = tzlocal.get_localzone()
local_dt = dt.astimezone( local_timezone )
return local_dt
Barry
>
> Thanks
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>
More information about the Python-list
mailing list