isoformat中的时区字段

Jos*_*osh 15 python datetime

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

2014-10-06T18:06:40-04:56
Run Code Online (Sandbox Code Playgroud)

我理解这第一部分: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)
Run Code Online (Sandbox Code Playgroud)

然后:

end_time.isoformat()
Run Code Online (Sandbox Code Playgroud)

收益:

2014-10-06T18:06:40-04:56
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 23

问题是pytz:

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

再往下说,它说:

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

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

因此,您需要执行文档建议使用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'
Run Code Online (Sandbox Code Playgroud)

我想这是你想要的最后一次.作为文件localize说:

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

此方法应该用于构造localtimes,而不是将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,夏季是美国东部时间,冬季是美国东部时间,这是你从仰视'US/Eastern'或'America/New_York'.

  • 哇,这让我很难受。 (2认同)

jfs*_*jfs 5

-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())
Run Code Online (Sandbox Code Playgroud)
  • 您应该使用tz.localize()而不是tzinfo直接分配属性
  • is_dst=None 断言输入时间存在且无歧义
  • tz.normalize() 如果日期算术跨越DST边界,则很有必要

输出量

2014-10-06T18:06:40-04:00
2014-10-06T18:13:20-04:00
Run Code Online (Sandbox Code Playgroud)

为什么你需要localize(),normalize()在描述的pytz文档(对部分localize()/ normalize()是文档中的第一个音符)。

为什么在东部时区-04:56UTC偏移量是错误的2014

由于DST转换或其他原因(例如战争或某些政治家认为这是个好主意),同一时间的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>}
Run Code Online (Sandbox Code Playgroud)

注意LMT tzinfo的UTC偏移量:timedelta(-1, 68640)== '-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
Run Code Online (Sandbox Code Playgroud)

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