关于python 3.x:Pytz在没有DST的情况下将时间转换为UTC

Pytz convert time to UTC without DST

在发布这篇文章之前,我做了很多研究,但是我似乎无法正确地进行转换。我有一些数据有时间戳,一些数据应用了DST,而另一些数据没有。我认为正确的方法来指定它没有DST是使用is_dst参数来表示PYTZ。所有3个选项与UTC的偏移量相同,这是不正确的。偏移量应为+1000。进行这种转换的最佳方法是什么?为什么is-dst参数没有任何区别?

1
2
3
4
5
6
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'


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

您试图通过忽略转换规则来转换日期时间。我不认为派兹会支持这一点。相反,您可以在标准时间内选择一个日期,并请求其偏移量,然后使用它。

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

utcoffset方法给出特定日期时间的偏移量(dst方法也只给出DST偏移量)。

1
2
3
4
5
6
7
8
9
>>> 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的tzinfokwarg设置,然后将其交给pytz进行转换。

下面是一个日期时间,它显示在一个没有针对DST进行调整的时钟上:

1
2
3
>>> 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'

这是同样的日期时间回到现实:

1
2
>>> 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的标准偏移量。

1
2
3
4
5
6
7
8
9
10
11
12
13
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