Python中的夏令时

2024-05-20 19:54:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个程序,它处理很多时区和穿越它们。我最常处理的两件事是从“now”创建一个datetime对象,然后本地化一个简单的datetime对象。

为了从现在开始在太平洋时区中创建一个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())

我的问题是为什么?有谁能给我看一个第一个错误,第二个正确的案例吗?

至于我的秒问题,假设我在2012年9月1日上午8:00在加利福尼亚州洛杉矶的某个用户输入中有一个天真的日期和时间,那么将日期时间设置为如下:

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

如果没有,我应该如何建立这些日期时间?


Tags: 对象fromimport程序datetime时间两件事now
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时区进行时间加/减。 转换为本地时间仅用于输出/显示。

pytz documentation

The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.

所以理想情况下,应该使用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而不是本地时间来处理除显示以外的所有事情。

对于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的很多麻烦。

相关问题 更多 >