Why converting between time zones in Python yields different results?

时间:2018-03-22 23:22:28

标签: python datetime timezone pytz

I have been working with time zones in Python for some time now. One of my challenges was creating an prize which was valid up to 23:59:59 on the proper time zone some days after the current time. I took the current UTC time, added a timedelta, converted to the desired time zone, replaced hour/minutes/seconds and converted back to UTC. That worked and still works perfectly.

Recently I tried to rewrite that code on another project and came to a situation which I cannot explain. Check out the example code below.

from datetime import datetime
import pytz

dt1 = datetime\
.now(pytz.utc)\
.astimezone(pytz.timezone("America/Sao_Paulo"))\
.replace(
    year=2018,
    month=3,
    day=22,
    hour=23,
    minute=59,
    second=59,
    microsecond=0
)\
.astimezone(pytz.utc)

dt2=datetime(
    year=2018,
    month=3,
    day=22,
    hour=23,
    minute=59,
    second=59,
    microsecond=0,
    tzinfo=pytz.timezone("America/Sao_Paulo")
)\
.astimezone(pytz.utc)

print(dt1)
# 2018-03-23 02:59:59+00:00
print(dt2)
# 2018-03-23 03:05:59+00:00

Why dt1 != dt2 ?

I know dt1 is an ugly way to create a datetime object, but that is actually the value I expect. I cannot understand why they differ in 6 minutes.

Thank you very much.

1 个答案:

答案 0 :(得分:1)

Quoting from the pytz documentation :

Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.

Take a look at your dt2 before converting it to UTC and you'll see there's something fishy going on with its UTC offset:

>>> dt2 = datetime(year=2018, month=3, day=22,
...                hour=23, minute=59, second=59,
...                tzinfo=pytz.timezone("America/Sao_Paulo"))
>>> print(dt2)
2018-03-22 23:59:59-03:06

This on the other hand works:

>>> naive_dt = datetime(year=2018, month=3, day=22,
...                     hour=23, minute=59, second=59)
>>> aware_dt = pytz.timezone('America/Sao_Paulo').localize(naive_dt)
>>> print(aware_dt)
2018-03-22 23:59:59-03:00
相关问题