【发布时间】:2010-12-14 18:48:12
【问题描述】:
我正在尝试在 Python 中解析像 "Sat, 11/01/09 8:00PM EST" 这样的时间戳字符串,但我无法找到可以处理缩写时区的解决方案。
我正在使用dateutil 的parse() 函数,但它不解析时区。有没有简单的方法可以做到这一点?
【问题讨论】:
-
python bug tracker 出现问题:bugs.python.org/issue22377
我正在尝试在 Python 中解析像 "Sat, 11/01/09 8:00PM EST" 这样的时间戳字符串,但我无法找到可以处理缩写时区的解决方案。
我正在使用dateutil 的parse() 函数,但它不解析时区。有没有简单的方法可以做到这一点?
【问题讨论】:
dateutil 的parser.parse() 接受tzinfos 类型的字典作为关键字参数{'EST': -5*3600}(即,以秒为单位将区域名称与GMT 偏移量匹配)。所以假设我们有这个,我们可以这样做:
>>> 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 的内容,这是我的填充方式:
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('\n')):
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 时区忽略了基里巴斯共和国。
【讨论】:
dp.parse(dt, tzinfos=tzd)
MSK 将在 2014 年 10 月 26 日再次距 UTC 3 小时,即,鉴于'MSK',如果您不知道日期,则无法返回正确的 UTC 偏移量。 'EST' is worse, it may correspond to several UTC offsets at the same time
这可能行不通,因为这些缩写不是唯一的。有关详细信息,请参阅this page。如果您使用一组已知的输入,您可能最终只需要自己手动处理它。
【讨论】:
你可以试试 pytz 模块:http://pytz.sourceforge.net/
pytz 将 Olson tz 数据库引入 Python。该库允许准确 和跨平台时区 使用 Python 2.3 或 更高。也解决了问题 白天结束时的模棱两可的时间 节省,您可以阅读更多信息 在 Python 库参考中 (datetime.tzinfo)。
几乎所有的奥尔森时区都是 支持。
【讨论】:
dateutil 中的 parse() 函数无法处理时区。我一直在使用的是 %Z 格式化程序和 time.strptime() 函数。我不知道它如何处理时区的歧义,但它似乎可以区分 CDT 和 CST,这正是我所需要的。
背景:我将备份图像存储在名称为使用当地时间的时间戳的目录中,因为我家里没有 GMT 时钟。所以我使用 time.strptime(d, r"%Y-%m-%dT%H:%M:%S_%Z") 将目录名称解析回实际时间进行年龄分析。
【讨论】:
我使用pytz 生成了一个TZINFOS 映射:
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 用法
>>> 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 用法
>>> 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 转换,因为每个缩写都有许多可用的时区。由于TZINFOS 是dict,因此每个缩写只有最后一个时区。而且您可能无法获得您所期望的预转换。
>>> tzdate
datetime.datetime(2009, 11, 1, 20, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/Port-au-Prince'))
【讨论】:
我意识到dateparser 可以解决这个问题。 https://pypi.org/project/dateparser/
用法:
import dateparser
def time_gmt_format(str_datetime):
# from string like "29/05/2020, 08:18 WIB" to GMT yyyymmddhhmmss
date_time_obj = dateparser.parse(str_datetime, date_formats=['%d/%m/%Y, %H:%M %Z'],
settings={'TO_TIMEZONE': 'GMT'}) # convert to GMT datetime object
return date_time_obj.strftime('%Y%m%d%H%M%S') # Output: 20200529011800
【讨论】: