夏令时在Python(Daylight savings time in Python)

2019-06-27 14:19发布

我写一个程序,它涉及了很多与时区和对着干。 两件事情我处理大多是从“现在”创建日期时间对象,然后定位一个天真的DateTime对象。

从现在开始在太平洋时区创建DateTime对象,我目前做这个(蟒蛇2.7.2+)

from datetime import datetime
import pytz
la = pytz.timezone("America/Los_Angeles")
now = datetime.now(la)

这是正确的有关于DST? 如果不是这样,我想我应该做的:

now2 = la.localize(datetime.now())

我的问题是为什么呢? 谁能告诉我的情况下,首先是错误的,而秒数是正确的?

至于我秒的问题,假设我有从9/1/2012一些用户输入一个天真的日期和时间上午8:00在洛杉矶,CA. 就是让这样的日期时间的正确方法:

la.localize(datetime(2012, 9, 1, 8, 0))

如果不是这样,我应该如何构建这些日期时间?

Answer 1:

从pytz文档 :

处理时间的最佳方式是始终UTC工作,转换才产生的localtime输出时,由人来阅读。

所以,最好你应该使用utcnow ,而不是now

假如由于某种原因,你的双手被缚,你需要与本地时间工作,你仍然可以与尝试,如果你夏令转变窗口期间做本地化当前时间遇到了问题。 同样的datetime可能会出现两次,在白天的时间一次又一次在标准时间和localize方法不知道如何解决冲突,除非你用告诉它明确is_dst参数。

因此,要获得当前UTC时间:

utc = pytz.timezone('UTC')
now = utc.localize(datetime.datetime.utcnow())

并把它转换为本地时间(但只有当你必须):

la = pytz.timezone('America/Los_Angeles')
local_time = now.astimezone(la)

编辑:作为被评论中指出@JF塞巴斯蒂安 ,使用您的第一个例子datetime.now(tz)将适用于所有情况。 正如我上面列出的秋天过渡期间,你的第二个例子失败。 我还是主张使用UTC而不是本地时间,除了显示一切。



Answer 2:

第一种方案是关于DST正确的,第二个解决方案是坏的。

我举一个例子。 在这里,在欧洲,这段代码运行时:

from datetime import datetime
import pytz # $ pip install pytz

la = pytz.timezone("America/Los_Angeles")
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
now = datetime.now(la)
now2 = la.localize(datetime.now())
now3 = datetime.now()
print(now.strftime(fmt))
print(now2.strftime(fmt))
print(now3.strftime(fmt))

我得到如下:

2012-08-30 12:34:06 PDT-0700
2012-08-30 21:34:06 PDT-0700
2012-08-30 21:34:06 

datetime.now(la)创建与LA当前时间的日期时间,加上LA时区信息。

la.localize(datetime.now())增加了时区信息到幼稚日期时间,但不执行时区转换; 它只是假定的时间已经在这个时区。

datetime.now()创建了一个天真的日期时间(无时区信息)和本地时间。

只要你是在洛杉矶,你会看不出来区别,但如果你的代码运行在其他地方,它可能不会做你想要的。

除此之外,如果你需要与时区认真对待,最好是在UTC你所有的时间,为自己节省了大量的与DST麻烦。



Answer 3:

这工作:

# naive datetime
d = datetime.datetime(2016, 11, 5, 16, 43, 45) 
utc = pytz.UTC # UTC timezone
pst = pytz.timezone('America/Los_Angeles') # LA timezone

# Convert to UTC timezone aware datetime
d = utc.localize(d) 
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>)

# show as in LA time zone (not converting here)
d.astimezone(pst) 
>>> datetime.datetime(2016, 11, 5, 9, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
# we get Pacific Daylight Time: PDT

# add 1 day to UTC date
d = d + datetime.timedelta(days=1) 
>>> datetime.datetime(2016, 11, 6, 16, 43, 45, tzinfo=<UTC>)

d.astimezone(pst) # now cast to LA time zone 
>>> datetime.datetime(2016, 11, 6, 8, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>) 
# Daylight saving is applied -> we get Pacific Standard Time PST

这不起作用:

# naive datetime
d = datetime.datetime(2016, 11, 5, 16, 43, 45) 
utc = pytz.UTC # UTC timezone
pst = pytz.timezone('America/Los_Angeles') # LA timezone

# convert to UTC timezone aware datetime
d = utc.localize(d) 
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>)

# convert to 'America/Los_Angeles' timezone: DON'T DO THIS
d = d.astimezone(pst) 
>>> datetime.datetime(2016, 11, 5, 9, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>) 
# we are in Pacific Daylight Time PDT

# add 1 day to LA local date: DON'T DO THAT
d = d + datetime.timedelta(days=1)
>>> datetime.datetime(2016, 11, 6, 9, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>) 
# Daylight Saving is NOT respected, we are still in PDT time, not PST

结论:

datetime.timedelta() 考虑夏令时。

难道你的时间添加/ UTC时区减去ALWAYS。 投射到当地时间仅输出/显示。



Answer 4:

该pytz网站说:

不幸的是使用标准的datetime建设者“”不起作用'与pytz许多时区的tzinfo说法。

所以,你不应该使用datetime.now(la) 我不知道具体情况,但有些时区上更奇特的规则,那么我们习惯进行操作,和Python的日期时间代码无法处理它们。 通过使用pytz的代码,它们应该被正确地处理,因为这是pytz的目的。 它也可能有对发生两次由于在夏令跳跃次数的时间问题。

至于第二个问题,这也正是该文档显示,所以你应该不错。



文章来源: Daylight savings time in Python