我正在编写一个程序,它可以处理很多时区并将它们交叉。我最常处理的两件事是从“now”创建一个datetime对象,然后本地化一个天真的日期时间对象。
要在太平洋时区创建一个日期时间对象,我现在正在这样做(python 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())
我的问题是为什么?任何人都可以告诉我第一个错误的情况,秒是对的吗?
关于我的秒问题,假设我在加利福尼亚州洛杉矶上午8:00的某个用户输入中有一个天真的日期和时间。是这样制作日期时间的正确方法:
la.localize(datetime(2012, 9, 1, 8, 0))
如果没有,我应该如何构建这些日期时间?
答案 0 :(得分:15)
处理时间的首选方法是始终使用UTC,仅在生成输出以供人类阅读时转换为本地时间。
理想情况下,您应该使用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)
修改:正如@J.F. Sebastian在评论中指出的那样,您使用datetime.now(tz)
的第一个示例将适用于所有情况。如上所述,您的第二个示例在秋季过渡期间失败。我仍然主张使用UTC而不是本地时间来处理除显示之外的所有内容。
答案 1 :(得分:6)
关于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.localize(datetime.now())
将时区信息添加到天真的日期时间,但没有时区转换;它只是假设时间已经在这个时区。
datetime.now()
使用当地时间创建一个天真的日期时间(没有时区信息)。
只要你在洛杉矶,你就不会看到差异,但如果你的代码在其他地方运行,那么它可能无法达到你想要的效果。
除此之外,如果您需要认真对待时区,最好将所有时间都用在UTC中,这样可以为DST省去很多麻烦。
答案 2 :(得分:2)
这有效:
journalctl -S-10h
这不起作用:
# 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
不说明夏令时。
以UTC时区为单位加/减时间总是如此。 仅转换为当地时间输出/显示。
答案 3 :(得分:1)
不幸的是使用标准日期时间的tzinfo参数 对于许多时区,构造函数''与pytz不起作用'。
所以你不应该使用datetime.now(la)
。我不知道具体细节,但有些时区按照我们习惯的更奇特的规则运行,而python的日期时间代码无法处理它们。通过使用pytz的代码,它们应该被正确处理,因为这是pytz的目的。由于夏令时的跳跃时间,它可能也会出现两次发生的问题。
关于第二个问题,这正是文档所显示的内容,所以你应该做得很好。