如何在Python中解析和比较iso8601持续时间?

2024-09-30 18:25:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一个Python(v2)库,它允许我解析和比较iso8601持续时间,这些持续时间可能以不同的单位表示

理想情况下,它可以与标准运算符(a<;b)一起工作,但我对a.compare(b)之类的东西很酷。在

比如说:

duration('P23M') < duration('P2Y') //True
duration('P25M') < duration('P2Y') //False

我已经从PyPi安装了isodate,但是它有自己的类来处理包括月份和年份在内的周期,它们不能与它们自己或与timedelta进行比较


Tags: lttrue标准情况单位运算符v2compare
3条回答

我最终“解决”这个问题的方法是比较结果值,如果将周期加到一个保持当前UTC时间的值上。这当然意味着,在2月份,P30D比P1M长,3月份短,4月份相等。不太理想,但很好地满足了我的需要。在

以下是一些关于持续时间的胡说八道(一个月是30天,一年是平均值,等等):

# parse 8601 duration
from re import findall

def iso8601_duration_as_seconds( d ):
    if d[0] != 'P':
        raise ValueError('Not an ISO 8601 Duration string')
    seconds = 0
    # split by the 'T'
    for i, item in enumerate(d.split('T')):
        for number, unit in findall( '(?P<number>\d+)(?P<period>S|M|H|D|W|Y)', item ):
            # print '%s -> %s %s' % (d, number, unit )
            number = int(number)
            this = 0
            if unit == 'Y':
                this = number * 31557600 # 365.25
            elif unit == 'W': 
                this = number * 604800
            elif unit == 'D':
                this = number * 86400
            elif unit == 'H':
                this = number * 3600
            elif unit == 'M':
                # ambiguity ellivated with index i
                if i == 0:
                    this = number * 2678400 # assume 30 days
                    # print "MONTH!"
                else:
                    this = number * 60
            elif unit == 'S':
                this = number
            seconds = seconds + this
    return seconds

for d in [ 'PT10M', 'PT5H', 'P3D', 'PT45S', 'P8W', 'P7Y', 'PT5H10M', 'P2YT3H10M', 'P3Y6M4DT12H30M5S', 'P23M', 'P2Y' ]:
    seconds = iso8601_duration_as_seconds( d )
    print "%s \t= %s" % (d,seconds)
    print


print '%s' % (iso8601_duration_as_seconds('P23M') < iso8601_duration_as_seconds('P2Y') )
# True
print '%s' % (iso8601_duration_as_seconds('P25M') < iso8601_duration_as_seconds('P2Y') )
# False

面对同样的问题,我求助于正则表达式来解析持续时间并比较得到的秒数:

def duration(duration_str):
    match = re.match(
        r'P(?P<years>\d+)Y)?(?P<months>\d+)M)?(?P<weeks>\d+)W)?(?P<days>\d+)D)?T((?P<hours>\d+)H)?((?P<minutes>\d+)M)?((?P<seconds>\d+)S)?',
        duration_str
    ).groupdict()
    return int(match['years'] or 0)*365*24*3600 + \
        int(match['months'] or 0)*30*24*3600 + \
        int(match['weeks'] or 0)*7*24*3600 + \
        int(match['days'] or 0)*24*3600 + \
        int(match['hours'] or 0)*3600 + \
        int(match['minutes'] or 0)*60 + \
        int(match['seconds'] or 0)

注意,这隐含地假设一年是365天,一个月是30天,等等

相关问题 更多 >