Python 是否有一种简单的方法将ISO 8601持续时间转换为时间增量?

Python 是否有一种简单的方法将ISO 8601持续时间转换为时间增量?,python,datetime,timedelta,python-datetime,Python,Datetime,Timedelta,Python Datetime,给定ISO 8601持续时间字符串,如何将其转换为datetime.timedelta 这不起作用: timedelta("PT1H5M26S", "T%H%M%S") timedelta对象表示持续时间,即两个日期或时间之间的差值()。ISO 8601的持续时间在这里有描述:我发现这个库完全符合我的要求 isodate.parse_duration('PT1H5M26S') 您可以阅读函数的源代码 这里有一个没有新软件包的解决方案,但只有在处理以天

给定ISO 8601持续时间字符串,如何将其转换为
datetime.timedelta

这不起作用:

timedelta("PT1H5M26S", "T%H%M%S")
timedelta对象表示持续时间,即两个日期或时间之间的差值()。ISO 8601的持续时间在这里有描述:

我发现这个库完全符合我的要求

isodate.parse_duration('PT1H5M26S')
  • 您可以阅读函数的源代码

    • 这里有一个没有新软件包的解决方案,但只有在处理以天表示的最大持续时间时才有效。不过,这种限制是有道理的,因为正如其他人所指出的():

      考虑到timedelta有超过“一个月”的天数,如何 您是否可以使用ISO8601持续时间符号来描述它,而不使用 引用特定的时间点?相反,以你为例, “P3Y6M4DT12H30M5S”,您如何将其转换为时间增量 不知道这段时间指的是哪一年哪一个月? Timedelta对象是非常精确的野兽,这几乎可以肯定 为什么他们不在他们的应用程序中支持“年”和“月”参数 构造器

      解析isoduration(“PT1H5M26S”) 3926
      好问题,显然“正确”的解决方案取决于您对输入的期望(更可靠的数据源不需要那么多输入验证)

      我解析ISO8601持续时间时间戳的方法仅检查“PT”前缀是否存在,并且不会假定任何单位的整数值:

      从日期时间导入时间增量
      def parse_isoduration(isostring,as_dict=False):
      """
      将ISO8601持续时间字符串解析为小时、分钟、秒
      """
      分隔符={
      “PT”:无,
      “W”:“周”,
      “D”:“天”,
      “H”:“小时”,
      “M”:“分钟”,
      “S”:“秒”,
      }
      持续时间_vals={}
      对于sep,分离器中的单位。项()
      partitioned=isostring.partition(sep)
      如果已分区[1]==sep:
      #匹配这个单位
      isostring=已分区[2]
      如果sep=“PT”:
      继续#前缀匹配成功
      dur_str=已分区[0]
      dur_val=float(dur_str)if.”在dur_str else int(dur_str)中
      持续时间更新({单位:dur_val})
      其他:
      如果sep=“PT”:
      提升值错误(“缺少PT前缀”)
      其他:
      #这个单位没有对手:它不存在
      持续时间更新({单位:0})
      如有规定:
      返回持续时间
      其他:
      返回元组(持续时间值()
      dur_isostr=“PT3H2M59.989333S”
      dur\u tuple=parse\u isoduration(dur\u isostr)
      dur_dict=parse_isoduration(dur_isostr,as_dict=True)
      td=时间增量(**dur_dict)
      s=td.总秒数()
      

      >>dur\u tuple
      (0, 0, 3, 2, 59.989333)
      >>>杜鲁迪克特
      {'weeks':0,'days':0,'hours':3,'minutes':2,'seconds':59.989333}
      >>>运输署
      datetime.timedelta(秒=10979,微秒=989333)
      >>>
      10979.989333
      
      基于@r3robertson更完整但不完美的版本

      def parse_isoduration(s):
      """ Parse a str ISO-8601 Duration: https://en.wikipedia.org/wiki/ISO_8601#Durations
      Originally copied from:
      https://stackoverflow.com/questions/36976138/is-there-an-easy-way-to-convert-iso-8601-duration-to-timedelta
      :param s:
      :return:
      """
      
      # ToDo [40]: Can't handle legal ISO3106 ""PT1M""
      
      def get_isosplit(s, split):
          if split in s:
              n, s = s.split(split, 1)
          else:
              n = '0'
          return n.replace(',', '.'), s  # to handle like "P0,5Y"
      
      s = s.split('P', 1)[-1]  # Remove prefix
      s_yr, s = get_isosplit(s, 'Y')  # Step through letter dividers
      s_mo, s = get_isosplit(s, 'M')
      s_dy, s = get_isosplit(s, 'D')
      _, s = get_isosplit(s, 'T')
      s_hr, s = get_isosplit(s, 'H')
      s_mi, s = get_isosplit(s, 'M')
      s_sc, s = get_isosplit(s, 'S')
      n_yr = float(s_yr) * 365  # These are approximations that I can live with
      n_mo = float(s_mo) * 30.4  # But they are not correct!
      dt = datetime.timedelta(days=n_yr+n_mo+float(s_dy), hours=float(s_hr), minutes=float(s_mi), seconds=float(s_sc))
      return dt  # int(dt.total_seconds())  # original code wanted to return as seconds, we don't.
      

      “一个datetime.timedelta格式的字符串”没有意义,我假设您指的是
      datetime.timedelta
      对象。标准库没有对delta进行解析,但是PyPI上有一些包供您安装
      pip
      。如果你想知道自己怎么做,我认为这太宽泛了;你应该试一试,看看哪里(如果有!)你太困了,无法继续。是的,你是对的。我想把它转换成timedelta对象。我可以编写我的解析器,但我正在寻找是否有一个简单的解决方案。是的,有:使用第三方软件包来完成。你可以通过搜索找到这些。我不明白为什么这个问题以“太宽泛”结尾。它非常集中。什么是
      datetime.timedelta
      ?它是包裹的一部分吗?你能给出一个具体的例子来说明你想要什么和你得到了什么吗?请注意,这些值不一定是整数(例如,MP4在web上的DASH media streams的MPD清单),这假定它们都是整数并强制为整数。
      def parse_isoduration(s):
      """ Parse a str ISO-8601 Duration: https://en.wikipedia.org/wiki/ISO_8601#Durations
      Originally copied from:
      https://stackoverflow.com/questions/36976138/is-there-an-easy-way-to-convert-iso-8601-duration-to-timedelta
      :param s:
      :return:
      """
      
      # ToDo [40]: Can't handle legal ISO3106 ""PT1M""
      
      def get_isosplit(s, split):
          if split in s:
              n, s = s.split(split, 1)
          else:
              n = '0'
          return n.replace(',', '.'), s  # to handle like "P0,5Y"
      
      s = s.split('P', 1)[-1]  # Remove prefix
      s_yr, s = get_isosplit(s, 'Y')  # Step through letter dividers
      s_mo, s = get_isosplit(s, 'M')
      s_dy, s = get_isosplit(s, 'D')
      _, s = get_isosplit(s, 'T')
      s_hr, s = get_isosplit(s, 'H')
      s_mi, s = get_isosplit(s, 'M')
      s_sc, s = get_isosplit(s, 'S')
      n_yr = float(s_yr) * 365  # These are approximations that I can live with
      n_mo = float(s_mo) * 30.4  # But they are not correct!
      dt = datetime.timedelta(days=n_yr+n_mo+float(s_dy), hours=float(s_hr), minutes=float(s_mi), seconds=float(s_sc))
      return dt  # int(dt.total_seconds())  # original code wanted to return as seconds, we don't.