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