isoformat中的时区字段

时间:2014-10-08 19:28:56

标签: python datetime

我有一个应该在EST的时间戳:

2014-10-06T18:06:40-04:56

我理解第一部分:2014-10-06T18:06:40,但不是-04:56

-04:56在这里意味着什么?`

以下是我获得该时间戳的方法:

import datetime
start_time = datetime.datetime(year  = 2014, 
                               month = 10, 
                               day   = 6, 
                               hour  = 18, 
                               tzinfo = pytz.timezone('US/Eastern'))
end_time   = start_time + datetime.timedelta(seconds=400)

然后:

end_time.isoformat()

返回:

2014-10-06T18:06:40-04:56

3 个答案:

答案 0 :(得分:20)

问题在于pytz

  

...与用于tzinfo实现的文档化Python API不同;如果要创建本地挂钟时间,则需要使用本文档中记录的localize()方法...

进一步向下,它说:

  

不幸的是,对于许多时区,使用标准日期时间构造函数的tzinfo参数“对pytz不起作用”。

>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=amsterdam).strftime(fmt)
'2002-10-27 12:00:00 LMT+0020'

因此,您需要执行文档建议的内容 - 使用normalize,构建UTC时间并使用astimezone等。您想要哪一个取决于您正在尝试做什么。例如:

>>> from datetime import datetime
>>> from pytz import timezone
>>> utc = timezone('UTC')
>>> eastern = timezone('US/Eastern')
>>> datetime(2014, 10, 6, 18, tzinfo=eastern).isoformat()
'2014-10-06T18:00:00-04:56'
>>> eastern.normalize(datetime(2014, 10, 6, 18, tzinfo=eastern)).isoformat()
'2014-10-06T18:56:00-04:00'
>>> datetime(2014, 10, 6, 18, tzinfo=utc).astimezone(eastern).isoformat()
'2014-10-06T14:00:00-04:00'
>>> eastern.localize(datetime(2014, 10, 6, 18)).isoformat()
'2014-10-06T18:00:00-04:00'

我认为这是你想要的最后一次。正如localize的文档所说:

  

将天真时间转换为当地时间。

     

此方法应该用于构造本地时间   而不是将tzinfo参数传递给datetime构造函数。

我认为构建当地时间正是你想要的。


如果您想知道为什么 ......好吧,如果您查看Olson数据库中的数据,或打印出eastern._utcoffset,您会看到-1天,+ 68640分钟。这是19.0166+小时,而不是19.为什么?因为每个时区都定义了它的起始偏移量,并从那里进行调整。东部是基于纽约的时区截至1883年11月18日12:03:58,此时格林威治标准时间是-04:56:02。从1920年开始的日期调整减去额外的00:03:58。当然,每年为夏令时来回调整一小时。所以,截至目前,东方是-04:00,但不知道它应该代表什么日期,它是-04:56。并且,因为datetime只是询问一个时区的偏移量,而不是它在特定时间的偏移量,这就是它所得到的。


最后一件事:EST是东部标准时间,即-05:00。这不是2014年10月6日在美国任何地点的时区,因为在2014年,美国的夏令时将持续到11月2日。 (曾经是印第安纳州夏季期间在美国东部时间的县,但不再有。)你要找的是东部日光时间,也就是-04:00。或者,当然,ET,即夏季的EDT和冬季的EST,这是您查找'US/Eastern''America/New_York'时获得的。

答案 1 :(得分:4)

  

-04:56在这里是什么意思?`

这意味着生成输入时间戳的代码被打破,这表明对pytz时区的工作方式缺乏了解。你不应该相信它的结果,如果你认为只有UTC偏移量(-04:56)是错误的但日期本身是东部时区的正确时间然后解析时间,请执行:

#!/usr/bin/env python
from datetime import datetime, timedelta
import pytz

tz = pytz.timezone('America/New_York')

naive = datetime.strptime("2014-10-06T18:06:40-04:56"[:-6],
                          "%Y-%m-%dT%H:%M:%S")
start_time = tz.localize(naive, is_dst=None)
end_time = tz.normalize(start_time + timedelta(seconds=400))
print(start_time.isoformat())
print(end_time.isoformat())
  • 您应该使用tz.localize()而不是直接分配tzinfo属性
  • is_dst=None断言输入时间存在且明确无误
  • 如果日期算术越过DST边界,
  • tz.normalize()是必要的

输出

2014-10-06T18:06:40-04:00
2014-10-06T18:13:20-04:00

localize()中描述了为什么需要normalize()-04:56

为什么2014 UTC偏移在东部时区的>>> import pytz >>> pytz.timezone('US/Eastern') {(datetime.timedelta(-1, 72000), datetime.timedelta(0, 3600), 'EWT'): <DstTzInfo 'US/Eastern' EWT-1 day, 20:00:00 DST>, (datetime.timedelta(-1, 68640), datetime.timedelta(0), 'LMT'): <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>, (datetime.timedelta(-1, 72000), datetime.timedelta(0, 3600), 'EDT'): <DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>, (datetime.timedelta(-1, 68400), datetime.timedelta(0), 'EST'): <DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>, (datetime.timedelta(-1, 72000), datetime.timedelta(0, 3600), 'EPT'): <DstTzInfo 'US/Eastern' EPT-1 day, 20:00:00 DST>} 中错误

由于DST转换或其他原因(例如战争或因为某些政治家认为这是一个好主意),同一地点的UTC偏移可能在不同时间有所不同,例如,这里是US / Eastern的可能值:

timedelta(-1, 68640)

请注意LMT tzinfo的UTC偏移量:'-4:56:00' == #XXX BROKEN, DO NOT DO IT >>> dt = datetime(2014, 10, 6, tzinfo=pytz.timezone('US/Eastern')) >>> dt datetime.datetime(2014, 10, 6, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>) >>> dt.isoformat() 2014-10-06T00:00:00-04:56 。获得它的方法是使用不正确的代码:

tzinfo

直接分配pytz不允许tzinfo在给定时间内选择正确的tzinfo,而是使用可用的随机tz.localize()对象。您应始终使用{{1}}附加正确的时区信息。

答案 2 :(得分:0)

我建议查看arrow。上述答案有效,但使代码真的令人困惑。 Arrow允许您使用以下方式执行此操作:

In [82]: start_time = arrow.get(2014, 10, 6, 18).to('US/Eastern')
In [83]: end_time = start_time.shift(seconds=400)
In [84]: start_time
Out[84]: <Arrow [2014-10-06T14:00:00-04:00]>
In [85]: end_time
Out[85]: <Arrow [2014-10-06T14:06:40-04:00]>

您可以使用

检索datetime个对象
In [86]: start_time.datetime
Out[86]: datetime.datetime(2014, 10, 6, 14, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Eastern'))