Pytz将时间转换为UTC而不考虑夏令时

3

在发布这个问题之前,我已经做了很多研究,但似乎无法正确进行转换。我有一些带有时间戳的数据,有些应用了DST(夏令时),而其他一些则没有。我认为指定没有DST的正确方法是使用pytz的is_dst参数。但是,三个选项都给出了与UTC相同的偏移量,这是不正确的。偏移量应该是+1000。最好的转换方法是什么,为什么is_dst参数没有任何区别?

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'

大多数时间戳都会忽略is_dst参数。它仅在夏令时转换期间存在歧义的情况下使用,以解决这种歧义。pytz_eastern的转换是什么? - Josh Lee
夏令时从十月的第一个星期日开始,到四月的第一个星期日结束。2017年10月1日至2018年4月1日。 - Matts
1个回答

2

is_dst 参数在大多数时间戳中都被忽略。它仅在 DST 转换期间的模糊时段中使用,以解决该歧义。

您试图通过忽略转换规则来转换日期时间。我认为 pytz 不支持这样做。相反,您可以选择标准时间中的一个日期,并要求其偏移量,然后使用该偏移量。

>>> from datetime import *
>>> import pytz
>>> pytz_eastern = pytz.timezone('Australia/Sydney')
< p > utcoffset 方法为特定日期时间提供偏移量(dst 方法仅提供DST偏移量)。< /p >
>>> 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)

从标准时间的日期中获取utcoffset,并使用datetime的tzinfo关键字参数直接设置它,然后再将其传递给pytz进行转换。
因此,这是一个在未调整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'

这里是同样的日期时间,被带回到现实中:

>>> 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'

标准偏移量似乎也可以使用._utcoffset,但这并没有记录在文档中,因此询问特定日期的utcoffset是有道理的,因为过去的偏移量不太可能发生改变。

实际上,由于pytz提供了计算出的偏移量和当前DST值,您可以将两者相减以忽略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

非常感谢,这是一个好的解决方案,真的帮助我理解了正在发生的事情。 - Matts
该函数运行良好。我还在函数内添加了zoneinfo,因此我只需要传递datetime参数即可。 - Matts
当我运行代码时,我收到了standard_offset = timezone (ro.utcoffset(datetime(2018, 6, 1))) File"/usr/lib/python3/dist-packages/pytz/__init__.py", line 157, in timezone if zone.upper() == 'UTC': AttributeError:'datetime.timedelta' object has no attribute 'upper'错误。为什么会这样? - Daniela

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接