【问题标题】:Python splitting time string of "4d12h33m59s" format into piecesPython将“4d12h33m59s”格式的时间字符串分割成碎片
【发布时间】:2018-03-04 10:17:43
【问题描述】:

我想知道是否有人可以帮助提出一个优雅的解决方案,如何将从路由器的 API 接收到的时间字符串拆分为 "4d12h33m59s" 格式。

问题是字符串可能是动态大小。例如,它可以是"4d12h33m59s""12h33m59s""12y14w4d12h33m59s""12m23s""33s"

有没有什么优雅的方法可以分割字符串并得到一个类似的列表:

received_string = "12y14w4d12h33m59s"
time_list = convert_string(received_string)

print(time_list) 
["12y","14w","4d","12h","33m","59s"]

【问题讨论】:

    标签: python string time split


    【解决方案1】:

    你可以使用regular expression:

    import re
    
    time_list = re.findall('\d+[a-z]', received_string)
    

    re.findall() function 生成输入字符串中给定模式的所有匹配项的列表。此处的模式查找 1 个或多个数字,后跟一个小写 ASCII 字母。

    您可以使用[ywdhms] 对允许的字母更加挑剔,但如果您的输入格式合理,我不会担心。

    演示:

    >>> import re
    >>> received_string = "12y14w4d12h33m59s"
    >>> re.findall('\d+[a-z]', received_string)
    ['12y', '14w', '4d', '12h', '33m', '59s']
    

    但是,您可能希望进一步拆分数字和字母,以便更轻松地将信息转换为更易于使用的格式,例如 datetime.timedelta() 对象,可能转换为字典:

    {type_: int(count) for count, type_ in re.findall('(\d+)([a-z])', received_string)}
    

    添加的(..) 分组会改变re.findall() 输出,为每个匹配项生成一个元组,其中包含单独的组值(如('12', 'y')('14', 'w') 等)。

    这会产生

    {'y': 12, 'w': 14, 'd': 4, 'h': 12, 'm': 33, 's': 59}
    

    供您参考。

    【讨论】:

    • 哇哦?伙计,我没想到这么快就得到了完美的答案!谢谢你,你是我的英雄!完美运行!
    【解决方案2】:

    Martijn 的回答和往常一样出色。我只是想扩展一下在此转换中使用 timedelta 的方法:

    import datetime, re, operator, functools
    times = {'s': datetime.timedelta(seconds=1),
             'm': datetime.timedelta(minutes=1),
             'h': datetime.timedelta(hours=1),
             'd': datetime.timedelta(days=1),
             'w': datetime.timedelta(weeks=1),
             'y': datetime.timedelta(days=365)}
    fieldre = re.compile(r'(\d+)([{}])'.format(''.join(times.keys())))
    
    samplevalue = "12y14w4d12h33m59s"
    
    duration = functools.reduce(operator.add, 
         (times[unit]*int(value) for (value,unit) in 
          fieldre.findall(samplevalue)))
    
    remains = fieldre.subn("", samplevalue)
    if remains:
        raise ValueError("Unexpected time fields in {!r}: {!r}".format(
            samplevalue, remains))
    

    诚然,最后一个有点乱。请注意,年份单位是一个粗略的近似值(365 天)。我使用dict.keys 来提取这些单位并允许它们出现在正则表达式中,正则表达式中的括号将值和单位作为一对生成,并使用functools.reduce(operator.add, iterable) 作为sum 的替代品,因为后者不起作用timedelta。最后,我们有一个 timedelta,我们可以从中读取标准化时间,例如duration.total_seconds().

    可能更有用的是,我添加了一种方法来检测我们是否使用subn 遗漏了某些内容。错误的数据可能比检测无效转化更有害。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-26
      • 2011-06-20
      • 2016-12-14
      相关资源
      最近更新 更多