How do I translate an ISO 8601 datetime string into a Python datetime object?
我正在以"2009-05-28T16:15:00"的格式获取日期时间字符串(我相信这是ISO 8601)。 一个hackish选项似乎是使用
1 | datetime.datetime(*time.strptime("2007-03-04T21:08:12","%Y-%m-%dT%H:%M:%S")[:6]) |
我无法找到一种"更清洁"的方式来做到这一点。 有吗?
我更喜欢使用dateutil库进行时区处理和一般的固态日期解析。如果您要获得ISO 8601字符串,例如:2010-05-08T23:41:54.000Z,您可以通过strptime解析它,特别是如果您事先不知道时区是否包含在内。 pyiso8601有一些问题(检查他们的跟踪器),我在使用过程中遇到过,并且在几年内没有更新。相比之下,dateutil一直活跃并为我工作:
1 2 | import dateutil.parser yourdate = dateutil.parser.parse(datestring) |
从Python 3.7开始,没有外部库:
1 | datetime.datetime.strptime('2019-01-04T16:41:24+0200',"%Y-%m-%dT%H:%M:%S%z") |
Python 2不支持
1 | datetime.datetime.strptime("2007-03-04T21:08:12Z","%Y-%m-%dT%H:%M:%SZ") |
因为ISO 8601允许存在许多可选冒号和破折号的变体,基本上
目标是生成UTC日期时间对象。
如果您只想要一个适用于UTC的基本案例,其Z后缀如
1 | datetime.datetime.strptime(timestamp.translate(None, ':-'),"%Y%m%dT%H%M%S.%fZ") |
如果要处理
1 2 3 4 5 | import re # This regex removes all colons and all # dashes EXCEPT for the dash indicating + or - utc offset for the timezone conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp) datetime.datetime.strptime(conformed_timestamp,"%Y%m%dT%H%M%S.%f%z" ) |
如果您的系统不支持
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 | import re import datetime # This regex removes all colons and all # dashes EXCEPT for the dash indicating + or - utc offset for the timezone conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp) # Split on the offset to remove it. Use a capture group to keep the delimiter split_timestamp = re.split(r"[+|-]",conformed_timestamp) main_timestamp = split_timestamp[0] if len(split_timestamp) == 3: sign = split_timestamp[1] offset = split_timestamp[2] else: sign = None offset = None # Generate the datetime object without the offset at UTC time output_datetime = datetime.datetime.strptime(main_timestamp +"Z","%Y%m%dT%H%M%S.%fZ" ) if offset: # Create timedelta based on offset offset_delta = datetime.timedelta(hours=int(sign+offset[:-2]), minutes=int(sign+offset[-2:])) # Offset datetime with timedelta output_datetime = output_datetime + offset_delta |
Arrow看起来很有希望:
1 2 3 | >>> import arrow >>> arrow.get('2014-11-13T14:53:18.694072+00:00').datetime datetime.datetime(2014, 11, 13, 14, 53, 18, 694072, tzinfo=tzoffset(None, 0)) |
Arrow is a Python library that provides a sensible, intelligent way of creating, manipulating, formatting and converting dates and times. Arrow is simple, lightweight and heavily inspired by moment.js and requests.
您应该密切关注时区信息,因为在将非tz感知日期时间与tz感知日期时间进行比较时可能会遇到麻烦。
最好总是使它们具有tz感知能力(即使只是作为UTC),除非你真的知道它为什么没有任何用处。
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 | #----------------------------------------------- import datetime import pytz import dateutil.parser #----------------------------------------------- utc = pytz.utc BERLIN = pytz.timezone('Europe/Berlin') #----------------------------------------------- def to_iso8601(when=None, tz=BERLIN): if not when: when = datetime.datetime.now(tz) if not when.tzinfo: when = tz.localize(when) _when = when.strftime("%Y-%m-%dT%H:%M:%S.%f%z") return _when[:-8] + _when[-5:] # Remove microseconds #----------------------------------------------- def from_iso8601(when=None, tz=BERLIN): _when = dateutil.parser.parse(when) if not _when.tzinfo: _when = tz.localize(_when) return _when #----------------------------------------------- |
我还没有尝试过,但pyiso8601承诺支持这一点。
双向:
ISO时代的时代:
1 | isoTime = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(epochTime)) |
ISO时间到Epoch:
1 | epochTime = time.mktime(time.strptime(isoTime, '%Y-%m-%dT%H:%M:%SZ')) |
1 2 3 4 5 6 7 8 | import datetime, time def convert_enddate_to_seconds(self, ts): """Takes ISO 8601 format(string) and converts into epoch time.""" dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+\ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1') seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0 return seconds |
这还包括毫秒和时区。
如果时间是'2012-09-30T15:31:50.262-08:00',这将转换为纪元时间。
1 2 3 4 5 6 | >>> import datetime, time >>> ts = '2012-09-30T15:31:50.262-08:00' >>> dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1') >>> seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0 >>> seconds 1348990310.26 |
Isodate似乎拥有最完整的支持。
aniso8601应该处理这个问题。它还了解时区,Python 2和Python 3,如果您需要,它可以合理地覆盖ISO 8601的其余部分。
1 2 | import aniso8601 aniso8601.parse_datetime('2007-03-04T21:08:12') |
这是一种进行这种转换的超级简单方法。
无需解析或额外的库。
它干净,简单,快速。
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import datetime import time ################################################ # # Takes the time (in seconds), # and returns a string of the time in ISO8601 format. # Note: Timezone is UTC # ################################################ def TimeToISO8601(seconds): strKv = datetime.datetime.fromtimestamp(seconds).strftime('%Y-%m-%d') strKv = strKv +"T" strKv = strKv + datetime.datetime.fromtimestamp(seconds).strftime('%H:%M:%S') strKv = strKv +"Z" return strKv ################################################ # # Takes a string of the time in ISO8601 format, # and returns the time (in seconds). # Note: Timezone is UTC # ################################################ def ISO8601ToTime(strISOTime): K1 = 0 K2 = 9999999999 K3 = 0 counter = 0 while counter < 95: K3 = (K1 + K2) / 2 strK4 = TimeToISO8601(K3) if strK4 < strISOTime: K1 = K3 if strK4 > strISOTime: K2 = K3 counter = counter + 1 return K3 ################################################ # # Takes a string of the time in ISO8601 (UTC) format, # and returns a python DateTime object. # Note: returned value is your local time zone. # ################################################ def ISO8601ToDateTime(strISOTime): return time.gmtime(ISO8601ToTime(strISOTime)) #To test: Test ="2014-09-27T12:05:06.9876" print ("The test value is:" + Test) Ans = ISO8601ToTime(Test) print ("The answer in seconds is:" + str(Ans)) print ("And a Python datetime object is:" + str(ISO8601ToDateTime(Test))) |