在Python中解析带有timezone缩写名称的日期/时间字符串?

Parsing date/time string with timezone abbreviated name in Python?

我正在尝试在Python中解析像"Sat, 11/01/09 8:00PM EST"这样的时间戳字符串,但我找不到能够处理缩写时区的解决方案。

我正在使用dateutilparse()函数,但它不解析时区。 是否有捷径可寻?


dateutilparser.parse()接受关键字参数tzinfos一种{'EST': -5*3600}的字典(即,将区域名称与GMT偏移量匹配,以秒为单位)。所以假设我们有,我们可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> import dateutil.parser as dp
>>> s = 'Sat, 11/01/09 8:00PM'
>>> for tz_code in ('PST','PDT','MST','MDT','CST','CDT','EST','EDT'):
>>>     dt = s+' '+tz_code
>>>     print dt, '=', dp.parse(dt, tzinfos=tzd)

Sat, 11/01/09 8:00PM PST = 2009-11-01 20:00:00-08:00
Sat, 11/01/09 8:00PM PDT = 2009-11-01 20:00:00-07:00
Sat, 11/01/09 8:00PM MST = 2009-11-01 20:00:00-07:00
Sat, 11/01/09 8:00PM MDT = 2009-11-01 20:00:00-06:00
Sat, 11/01/09 8:00PM CST = 2009-11-01 20:00:00-06:00
Sat, 11/01/09 8:00PM CDT = 2009-11-01 20:00:00-05:00
Sat, 11/01/09 8:00PM EST = 2009-11-01 20:00:00-05:00
Sat, 11/01/09 8:00PM EDT = 2009-11-01 20:00:00-04:00

关于tzinfos的内容,以下是我如何填充我的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
tz_str = '''-12 Y
-11 X NUT SST
-10 W CKT HAST HST TAHT TKT
-9 V AKST GAMT GIT HADT HNY
-8 U AKDT CIST HAY HNP PST PT
-7 T HAP HNR MST PDT
-6 S CST EAST GALT HAR HNC MDT
-5 R CDT COT EASST ECT EST ET HAC HNE PET
-4 Q AST BOT CLT COST EDT FKT GYT HAE HNA PYT
-3 P ADT ART BRT CLST FKST GFT HAA PMST PYST SRT UYT WGT
-2 O BRST FNT PMDT UYST WGST
-1 N AZOT CVT EGT
0 Z EGST GMT UTC WET WT
1 A CET DFT WAT WEDT WEST
2 B CAT CEDT CEST EET SAST WAST
3 C EAT EEDT EEST IDT MSK
4 D AMT AZT GET GST KUYT MSD MUT RET SAMT SCT
5 E AMST AQTT AZST HMT MAWT MVT PKT TFT TJT TMT UZT YEKT
6 F ALMT BIOT BTT IOT KGT NOVT OMST YEKST
7 G CXT DAVT HOVT ICT KRAT NOVST OMSST THA WIB
8 H ACT AWST BDT BNT CAST HKT IRKT KRAST MYT PHT SGT ULAT WITA WST
9 I AWDT IRKST JST KST PWT TLT WDT WIT YAKT
10 K AEST ChST PGT VLAT YAKST YAPT
11 L AEDT LHDT MAGT NCT PONT SBT VLAST VUT
12 M ANAST ANAT FJT GILT MAGST MHT NZST PETST PETT TVT WFT
13 FJST NZDT
11.5 NFT
10.5 ACDT LHST
9.5 ACST
6.5 CCT MMT
5.75 NPT
5.5 SLT
4.5 AFT IRDT
3.5 IRST
-2.5 HAT NDT
-3.5 HNT NST NT
-4.5 HLV VET
-9.5 MART MIT'''


tzd = {}
for tz_descr in map(str.split, tz_str.split('
'
)):
    tz_offset = int(float(tz_descr[0]) * 3600)
    for tz_code in tz_descr[1:]:
        tzd[tz_code] = tz_offset

PS。 @Hank Gay时区命名没有明确定义。为了形成我的表格,我使用了http://www.timeanddate.com/library/abbreviations/timezones/和http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations。我查看了每个冲突,并解决了流行的(更常用的)晦涩和流行的名字之间的冲突。有一个 - IST - 不是那么明确(它可能意味着印度标准时间,伊朗标准时间,爱尔兰标准时间或以色列标准时间),所以我把它排除在表外 - 你可能需要选择添加什么根据您的位置。哦 - 我和他们荒谬的"看着我,我是第一个庆祝新年"GMT + 13和GMT + 14时区,遗漏了基里巴斯共和国。


这可能不会起作用,因为这些缩写并不是唯一的。有关详情,请参阅此页面。如果您正在处理一组已知的输入,您可能需要自己手动处理它。


您可以尝试使用pytz模块:http://pytz.sourceforge.net/

pytz brings the Olson tz database into
Python. This library allows accurate
and cross platform timezone
calculations using Python 2.3 or
higher. It also solves the issue of
ambiguous times at the end of daylight
savings, which you can read more about
in the Python Library Reference
(datetime.tzinfo).

Amost all of the Olson timezones are
supported.


dateutil中的parse()函数无法处理时区。我一直在使用的是%Z格式化程序和time.strptime()函数。我不知道它如何处理时区的模糊性,但它似乎说明了CDT和CST之间的区别,这就是我所需要的。

背景:我使用当地时间将备份图像存储在名称为时间戳的目录中,因为我家里没有GMT时钟。所以我使用time.strptime(d,r"%Y-%m-%dT%H:%M:%S_%Z")将目录名称解析回年龄分析的实际时间。


我使用pytz生成tzinfos映射:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from datetime import datetime as dt

import pytz

from dateutil.tz import gettz
from pytz import utc
from dateutil import parser


def gen_tzinfos():
    for zone in pytz.common_timezones:
        try:
            tzdate = pytz.timezone(zone).localize(dt.utcnow(), is_dst=None)
        except pytz.NonExistentTimeError:
            pass
        else:
            tzinfo = gettz(zone)

            if tzinfo:
                yield tzdate.tzname(), tzinfo

tzinfos用法

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> TZINFOS = dict(gen_tzinfos())
>>> TZINFOS
{'+02': tzfile('/usr/share/zoneinfo/Antarctica/Troll'),
 '+03': tzfile('/usr/share/zoneinfo/Europe/Volgograd'),
 '+04': tzfile('Europe/Ulyanovsk'),
 '+05': tzfile('/usr/share/zoneinfo/Indian/Kerguelen'),              
...
 'WGST': tzfile('/usr/share/zoneinfo/America/Godthab'),
 'WIB': tzfile('/usr/share/zoneinfo/Asia/Pontianak'),
 'WIT': tzfile('/usr/share/zoneinfo/Asia/Jayapura'),
 'WITA': tzfile('/usr/share/zoneinfo/Asia/Makassar'),
 'WSDT': tzfile('/usr/share/zoneinfo/Pacific/Apia'),
 'XJT': tzfile('/usr/share/zoneinfo/Asia/Urumqi')}

parser用法

1
2
3
4
>>> date_str = 'Sat, 11/01/09 8:00PM EST'
>>> tzdate = parser.parse(date_str, tzinfos=TZINFOS)
>>> tzdate.astimezone(utc)
datetime.datetime(2009, 11, 2, 1, 0, tzinfo=<UTC>)

由于每个缩写都有许多时区,因此需要进行UTC转换。由于tzinfosdict,因此每个缩写只有最后一个时区。而且你可能得不到你预期转换的那个。

1
2
>>> tzdate
datetime.datetime(2009, 11, 1, 20, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/Port-au-Prince'))