2012-05-09 56 views
3

我试图比较两次使用Python datetime模块,但似乎无法在UTC中创建时区感知的time对象。使用Python比较UTC时间和东部时间使用Python

>>> import pytz, datetime 
>>> UTC_TZ = pytz.utc 
>>> EASTERN_TZ = pytz.timezone('America/New_York') 
>>> d1 = datetime.time(10, tzinfo = UTC_TZ) 
>>> d1 
datetime.time(10, 0, tzinfo=<UTC>) 
>>> d2 = datetime.time(10, tzinfo = EASTERN_TZ) 
>>> d2 
datetime.time(10, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>) 
>>> d1 < d2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't compare offset-naive and offset-aware times 

这是一个错误?有需要使用的特殊UTC时区吗?这是怎么回事?

回答

4

所有功劳归结于此,但为了简明扼要,我将在这里总结一下。

根据datetime文档,比较两个datetime.time对象时:“如果两个比较值都知道并且具有不同的tzinfo属性,则首先通过减去它们的UTC偏移量(从self.utcoffset()获得)来调整比较值”

在您给出的示例中,比较抛出TypeError,因为EASTERN_TZ.utcoffset()返回None。 utcoffset为None,因为美国东部观察到夏令时,所以与UTC的时间偏差取决于datetime.time中不可用的日期。

您应该使用跨时区比较datetime.datetime对象:

>>> import pytz, datetime 
>>> UTC_TZ = pytz.utc 
>>> EASTERN_TZ = pytz.timezone('America/New_York') 
>>> d1 = datetime.datetime(2012, 1, 1, 10, 0, tzinfo=UTC_TZ) 
>>> d2 = datetime.datetime(2012, 1, 1, 10, 0, tzinfo=EASTERN_TZ) 
>>> d1 < d2 
True 
+1

您不应该在DST中为时区使用'tzinfo'参数。使用'EASTERN_TZ.localize(naive_dt,is_dst = None).astimezone(pytz.utc)'来获取要比较的日期时间对象。 '.astimezone()'不是必需的,但最好始终在内部使用UTC时间,并将其转换为仅在IO上的其他时区 – jfs

+1

请注意,在3.3天赋和感知时间实例之间的相等比较不会引发TypeError。 – kolypto

1

我猜测问题是,UTC被认为是非 - 任何时区,或“偏移天真”,也许?在进行任何比较之前,我建议将所有内容转换为UTC。

显然,您需要知道输入和输出的时区,但您应该尽量保持内部表示全部采用UTC,并且可能仅存储每个用户的时区并在需要时进行转换。从长远来看,这将节省很多头痛。

此外,你不应该这样做。这是更好地使用

timezone.localize(dt) 

为解释在这里:http://pytz.sourceforge.net/#localized-times-and-date-arithmetic

+1

'EASTERN_TZ.localize(datetime.time(10))'给我'类型错误:不支持的操作数类型(S)为+: 'datetime.time'和'datetime.timedelta'' –

+0

@ChrisB .:同一时区在不同日期可能有不同的UTC偏移量,即'tz + datetime.time()'不足以找出正确的UTC偏移量,你需要'tz + datetime.datetime'假设给定的时间存在并且不是不明确的。 – jfs

3

你,因为你正在试图测量可以绑定到特定UTC瞬间一个time对象和另一个time对象之间的差异收到错误是“天真的”,不能绑定到特定的UTC时刻。解决方法是让两个比较都可以抵消意识,或者两者都是天真的。

以下使用datetime对象,但它基本上是相同的想法。

import datetime, time, pytz 

EST = pytz.timezone('America/New_York') 
UTC = pytz.timezone('Etc/UTC') 
dt1 = datetime.datetime.fromtimestamp(time.time(), EST) 
# ... time passes 
dt2 = datetime.datetime.fromtimestamp(time.time(), UTC) 
elapsed = dt2 - dt1 
+0

这是Python中的一个错误吗?文档中提到“时间类型或日期时间类型的对象可能是天真的或意识到的,d知道d.tzinfo不是None,d.tzinfo.utcoffset(d)不返回无。如果d.tzinfo是None,或者如果d.tzinfo不是None,但d.tzinfo.utcoffset(d)返回None,那么d是天真的。“如果这是正确的,那么为什么在我的例子中'd1'说它是偏移天真? –

+0

@ChrisB。,测试'UTC_TZ'并查看它是否为'utcoffset'返回'None'。 –

+0

@Mark Ransom:没有。它返回'datetime.timedelta(0)'。 –