← 中文资源

简体中文版本

格式化与解析人类可读时长

把秒数转换为天、小时、分钟和秒的紧凑字符串,并对字符串进行严格反向解析。

阅读英文原文

功能说明

format_duration 把秒数格式化为 1d 2h 3m 4s 这样的可读文本,parse_duration 执行反向解析,把 1d 2h 30m 或 1h30m 转回秒数。两者适合命令行工具的输出、配置文件中的超时时间、任务耗时展示以及用户输入的时间跨度。max_units 控制最多显示几个单位,compact 控制是否省略空格。

格式化先对秒数四舍五入,再依次用天、小时、分钟、秒做整除和取余。解析使用正则逐个匹配数值和单位,允许单位之间没有空格、大小写混用和小数,但要求整个字符串都被消费,遇到 1h 30 这类缺少单位的尾部会抛错。

关键代码

解析循环从当前位置继续匹配,匹配失败立即报告剩余文本:

while position < len(value):
    match = _TOKEN.match(value, position)
    if match is None:
        raise ValueError(
            f"invalid duration at position {position}: "
            f"{value[position:]!r}"
        )
    amount = float(match.group(1))
    unit = match.group(2).lower()
    total += amount * _UNIT_SECONDS[unit]
    position = match.end()

format_duration 用 divmod 同时得到当前单位的值和余数,避免重复计算。

使用注意

格式化默认只保留两个最高单位,例如 3661 秒输出 1h 1m,秒数被截断;需要完整精度时把 max_units 设为 4。四舍五入使用 Python 的银行家舍入,正好处于 .5 的秒数可能向偶数方向取整,若业务要求始终向上应自行调整。负数、NaN 和无穷大会被拒绝。

解析允许小数和重复单位,例如 1h 30m 10m 会把两个分钟相加;单位顺序也不受限制。它不支持 1 hour、1h30 或负数。空字符串和只有空白的字符串会报错。返回值是浮点秒数,可能包含浮点误差;需要整数时可在调用方取整。格式化与解析不保证完全互逆,因为格式化受 max_units 和舍入影响。

验证方式

示例输出 0、45、3661、90061、172800 秒的可读形式,分别为 0s、45s、1h 1m、1d 1h、2d,紧凑模式 1h1m。解析 1d 2h 30m 应得到 95400 秒,1h30m 得到 5400 秒。解析 1h 30 应输出带位置的错误,格式化 -1 应输出非负有限数错误。