Python datetime和tzinfo对象(更改分钟而不是小时)

8

我正在尝试将时区信息应用于一个日期时间对象。

In [1]: from datetime import datetime
In [2]: import pytz

In [3]: london = pytz.timezone("Europe/London")
In [4]: london
Out[5]: <DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>

In [6]: localized_date_object = datetime(2016, 1, 1, 11, 30, 0, 5000, london)
In [7]: localized_date_object
Out[8]: datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>)

In [9]: utc_date_object = localized_date_object.astimezone(pytz.utc)
In [10]: utc_date_object
Out[11]: datetime.datetime(2016, 1, 1, 11, 31, 0, 5000, tzinfo=<UTC>)

In [16]: paris = pytz.timezone("Europe/Paris")
In [17]: localized_date_object = datetime(2016, 1, 1, 11, 30, 0, 5000, paris)
In [18]: utc_date_object = localized_date_object.astimezone(pytz.utc)
In [19]: utc_date_object
Out[19]: datetime.datetime(2016, 1, 1, 11, 21, 0, 5000, tzinfo=<UTC>)

正如你所看到的,它应用了分钟而非小时的增量。
有人能解释一下我在这里做错了什么吗。

5个回答

11

根据pytz文档:

这个库只支持两种本地时间构建方法。第一种是使用pytz库提供的localize()方法,它用于本地化一个无时区信息的naive datetime:

第二种构建本地化时间的方法是使用标准的astimezone()方法将现有本地化时间进行转换:

不幸的是,对于许多时区,使用标准datetime构造函数的tzinfo参数"不起作用"。

在提供的代码示例中,您正在尝试使用tzinfo参数而不是localize()方法。

>>> london = pytz.timezone("Europe/London")

>>> datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, london) # This is incorrect
datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>)

>>> london.localize(datetime.datetime(2016, 1, 1, 11, 30, 0, 5000)) # This is correct
datetime.datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=<DstTzInfo 'Europe/London' GMT0:00:00 STD>)

1
是的。被采纳的答案没有解决问题,但这个答案解决了。 - Cfreak

2

我认为巴黎时间应该使用CET,伦敦时间应该使用UTC。我采用了略微不同的方法,但对我来说它很有效:

from datetime import datetime
from pytz import timezone

ldo = datetime(2016, 1, 1, 11, 30, 0, 5000)
ldo = ldo.replace(tzinfo=timezone('Europe/London'))

udo = ldo.astimezone(timezone('UTC'))
print ldo
print udo

ldo = datetime(2016, 1, 1, 11, 30, 0, 5000)
ldo = ldo.replace(tzinfo=timezone('CET'))

udo = ldo.astimezone(timezone('UTC'))
print ldo
print udo

更新:

当您存储时间值时,应该同时存储相关的时区信息。在我看来,最佳实践是将所有内容存储为协调世界时(UTC),并在查看时转换为“用户”时区。顺便说一下,从UTC转换为欧洲/巴黎时区可以无缝进行,请尝试以下操作:

winter = datetime(2016, 1, 1, 11, 30, 0, 5000, tzinfo=timezone("UTC"))
paris =  winter.astimezone(timezone("Europe/Paris"))
print paris
# 2016-01-01 12:30:00.005000+01:00

summer = datetime(2016, 6, 1, 11, 30, 0, 5000, tzinfo=timezone("UTC"))
paris = summer.astimezone(timezone("Europe/Paris"))
print paris
# 2016-06-01 13:30:00.005000+02:00

谢谢您,Jiri。因此,在伦敦冬季是协调世界时(UTC),夏季是英国夏令时(BST)。 - Sifnos
法国夏季使用中欧夏令时(CEST);) - Sifnos
1
@Sebabouche 这不是为了确定您城市的正确时区的问题;-) 当您在某个地方存储时间时,应该同时存储相关的时区信息(CET或CEST)。在我看来,最佳实践是将所有内容存储为UTC,并将其转换为“用户”时区进行查看。顺便说一句,从UTC转换为Europe/Paris可以无缝运行,详见答案的更新。 - Jiri

0

根据当时的协定标准,UTC 偏移量通常有多个定义。

使用带有时区的 datetime 函数构造 datetime 时,它不会很聪明地选择要使用的转换,并且往往会默认选择一个旧的历史偏移量,在您的示例中是一个一分钟的偏移量。这是因为它在考虑要转换的日期之前选择时区差。

这种替代方法解决了这个问题,可以得到更可靠(现代标准)的结果:

dt = mytz.localize(datetime(2020, 4, 7, 16, 30))


0
在第5行,它显示了一个奇怪的输出 - <DstTzInfo 'Europe/London' LMT-1 day, 23:59:00 STD>,似乎是一分钟的偏移(减去1天+23:59:00小时)。
我建议您尝试在pytz中使用其他几个时区定义来查看它们的声明。

0

时区Europe/London比UTC晚1分钟。时区Europe/Paris比UTC早9分钟。伦敦和巴黎在地理上靠近格林威治,因此时区偏移较小。

如果您尝试

pytz.timezone("Asia/Shanghai")

你会看到小时数的变化。


好的,我找错地方了,我在寻找传统的时区转换,+1小时,-1小时,就像英国夏令时(BST)一样。但是我会把你的答案标记为正确的 ;) - Sifnos

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