Pytz convert time to UTC without DST

假装没事ソ 提交于 2019-12-11 16:48:59

问题


I've done a quite a bit of research before posting this, but I can't seem to get the conversion right. I have some data which has timestamps, and some have DST applied, and others don't. I thought the correct way to specify that it's without DST is using the is_dst parameter for pytz. All 3 options give the same offset from UTC, which is incorrect. The offset should be +1000. What's the best way to do this conversion, and why does the is_dst parameter not make any difference?

pytz_eastern.localize(datetime(2018, 1, 18, 18, 50), is_dst=None).strftime('%Y-%m-%d %H:%M %z')
'2018-01-18 18:50 +1100'
pytz_eastern.localize(datetime(2018, 1, 18, 18, 50), is_dst=False).strftime('%Y-%m-%d %H:%M %z')
'2018-01-18 18:50 +1100'
pytz_eastern.localize(datetime(2018, 1, 18, 18, 50), is_dst=True).strftime('%Y-%m-%d %H:%M %z')
'2018-01-18 18:50 +1100'

回答1:


The is_dst parameter is ignored for most timestamps. It is only used during DST transition ambiguous periods to resolve that ambiguity.

You're trying to convert a datetime by ignoring the transition rules. I don't think pytz will support that. Instead you can pick a date in standard time and ask for its offset, then use that.

>>> from datetime import *
>>> import pytz
>>> pytz_eastern = pytz.timezone('Australia/Sydney')

The utcoffset method gives the offset for a particular datetime (and the dst method will also give just the DST offset).

>>> pytz_eastern.dst(datetime(2018, 6, 1))
datetime.timedelta(0)
>>> pytz_eastern.utcoffset(datetime(2018, 6, 1))
datetime.timedelta(0, 36000)

>>> pytz_eastern.dst(datetime(2018, 1, 1))
datetime.timedelta(0, 3600)
>>> pytz_eastern.utcoffset(datetime(2018, 1, 1))
datetime.timedelta(0, 39600)

Take the utcoffset from a date in standard time and set it directly with the tzinfo kwarg of datetime, and only then give it to pytz for conversion.

So here's a datetime that was shown on a clock which was not adjusted for DST:

>>> standard_offset = timezone(pytz_eastern.utcoffset(datetime(2018, 6, 1)))
>>> datetime(2018, 1, 18, 18, 50, tzinfo=standard_offset).strftime('%Y-%m-%d %H:%M %z')
'2018-01-18 18:50 +1000'

And here's that same datetime brought back into reality:

>>> datetime(2018, 1, 18, 18, 50, tzinfo=standard_offset).astimezone(pytz_eastern).strftime('%Y-%m-%d %H:%M %z')
'2018-01-18 19:50 +1100'

(The standard offset also seems to be available as ._utcoffset, but that's not documented, so that's a reason to ask for the utcoffset of a specific date, as it's less likely for offsets in the past to ever change.)

In fact, since pytz gives you the computed offset and the current DST value, you could subtract the two to get the standard offset ignoring DST.

def add_forgotten_dst(dt, zoneinfo):
    '''Like pytz.localize, but ignores dst.'''
    utcoffset = zoneinfo.utcoffset(dt)
    dst = zoneinfo.dst(dt)
    standard_offset = utcoffset - dst
    dt = dt.replace(tzinfo=timezone(standard_offset))
    return dt.astimezone(zoneinfo)

>>> naive_time = datetime(2018, 1, 18, 18, 50)
>>> print(pytz_eastern.localize(naive_time))
2018-01-18 18:50:00+11:00
>>> print(add_forgotten_dst(naive_time, pytz_eastern))
2018-01-18 19:50:00+11:00


来源:https://stackoverflow.com/questions/48321362/pytz-convert-time-to-utc-without-dst

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!