首页 文章

如何将ISO 8601日期时间字符串转换为Python日期时间对象? [重复]

提问于
浏览
339

这个问题在这里已有答案:

我正在以"2009-05-28T16:15:00"格式获取日期时间字符串(我相信这是ISO 8601) . 一个hackish选项似乎是使用 time.strptime 解析字符串并将元组的前六个元素传递给datetime构造函数,如:

datetime.datetime(*time.strptime("2007-03-04T21:08:12", "%Y-%m-%dT%H:%M:%S")[:6])

我无法找到一种“更清洁”的方式来做到这一点 . 有吗?

11 回答

  • 6

    我更喜欢使用dateutil库进行时区处理和一般的固态日期解析 . 如果您要获得ISO 8601字符串,例如:2010-05-08T23:41:54.000Z,您'd have a fun time parsing that with strptime, especially if you didn' t不知道时区是否包含在内 . pyiso8601有一些问题(检查他们的跟踪器),我在使用过程中遇到过,并且在几年内没有更新 . 相比之下,dateutil一直活跃并为我工作:

    import dateutil.parser
    yourdate = dateutil.parser.parse(datestring)
    
  • 34

    因为ISO 8601允许存在许多可选冒号和破折号的变体,基本上是 CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] . 如果你想使用strptime,你需要先删除这些变化 .

    The goal is to generate a UTC datetime object.


    如果您只想要一个适用于UTC的基本案例,其后缀为Z后缀,如 2016-06-29T19:36:29.3453Z

    datetime.datetime.strptime(timestamp.translate(None, ':-'), "%Y%m%dT%H%M%S.%fZ")
    

    如果要处理 2016-06-29T19:36:29.3453-04002008-09-03T20:56:35.450686+05:00 等时区偏移,请使用以下命令 . 这些将所有变体转换为没有变量分隔符的东西,如 20080903T205635.450686+0500 ,使其更加一致/更容易解析 .

    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" )
    

    如果您的系统不支持 %z strptime指令(您看到 ValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z' 之类的内容),那么您需要手动偏移 Z (UTC)的时间 . 注意 %z 可能无法在您的系统中使用Python版本<3,因为它依赖于C库支持,该支持因系统/ Python构建类型而异(即JythonCython等) .

    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
    
  • 15

    使用Python 2.5:

    datetime.datetime.strptime("2007-03-04T21:08:12", "%Y-%m-%dT%H:%M:%S")
    
  • 3

    Arrow看起来很有希望:

    >>> 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是一个Python库,它提供了一种合理,智能的创建,操作,格式化和转换日期和时间的方法 . Arrow简单,轻巧,受到moment.js和请求的启发 .

  • 41

    您应该密切关注时区信息,因为在将非tz感知日期时间与tz感知日期时间进行比较时可能会遇到麻烦 .

    最好总是使它们具有tz感知能力(即使只是作为UTC),除非你真的知道它为什么没有任何用处 .

    #-----------------------------------------------
    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
    #-----------------------------------------------
    
  • -12

    我还没有尝试过,但pyiso8601承诺支持这一点 .

  • 5
    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',这将转换为纪元时间 .

    >>> 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
    
  • 8

    Isodate似乎拥有最完整的支持 .

  • 565

    双向:

    ISO时代的时代:

    isoTime = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(epochTime))
    

    ISO时间到Epoch:

    epochTime = time.mktime(time.strptime(isoTime, '%Y-%m-%dT%H:%M:%SZ'))
    
  • 5

    aniso8601应该处理这个问题 . 它还可以理解时区,Python 2和Python 3,并且如果您需要,它可以合理地覆盖ISO 8601的其余部分 .

    import aniso8601
    aniso8601.parse_datetime('2007-03-04T21:08:12')
    
  • 40

    这是一种进行这种转换的超级简单方法 . 无需解析或额外的库 . 它干净,简单,快速 .

    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)))
    

相关问题