将表示为<number> [m | h | d | s | w]的时间字符串转换为Python中的秒数</number>

时间:2010-06-22 20:26:12

标签: python datetime

是否有一种很好的方法来转换表示时间的字符串,格式为[m | h | d | s | w](m =分钟,h =小时,d =天,s =秒w =周)秒数?即。

def convert_to_seconds(timeduration):
    ...

convert_to_seconds("1h")
-> 3600

convert_to_seconds("1d")
-> 86400

等?

谢谢!

5 个答案:

答案 0 :(得分:17)

是的,有一个很好的简单方法,您可以在大多数语言中使用,而无需阅读日期时间库的手册。这种方法也可以外推到盎司/磅/吨等等:

seconds_per_unit = {"s": 1, "m": 60, "h": 3600, "d": 86400, "w": 604800}

def convert_to_seconds(s):
    return int(s[:-1]) * seconds_per_unit[s[-1]]

答案 1 :(得分:8)

我建议使用datetime模块中的the timedelta class

from datetime import timedelta

UNITS = {"s":"seconds", "m":"minutes", "h":"hours", "d":"days", "w":"weeks"}

def convert_to_seconds(s):
    count = int(s[:-1])
    unit = UNITS[ s[-1] ]
    td = timedelta(**{unit: count})
    return td.seconds + 60 * 60 * 24 * td.days

在内部,timedelta个对象将所有内容存储为微秒,秒和天。因此,虽然您可以以毫秒或数月或数年为单位给出参数,但最终您必须使用您创建的timedelta并转换回秒。

如果**语法让您感到困惑,那就是Python apply语法。基本上,这些函数调用都是等效的:

def f(x, y): pass

f(5, 6)
f(x=5, y=6)
f(y=6, x=5)

d = {"x": 5, "y": 6}
f(**d)

答案 2 :(得分:0)

我在java(而不是php)中写了一个开源库MgntUtils,部分回答了这个要求。它包含一个静态方法parsingStringToTimeInterval(String value)此方法解析一个预期保存一些时间间隔值的字符串 - 一个带有可选时间单位后缀的数值。例如,字符串“38s”将被解析为38秒,“24m” - 24分钟“4h” - 4小时,“3d” - 3天和“45”将被解析为45毫秒。支持的后缀为秒数“s”,分钟为“m”,小时为“h”,日期为“d”。不带后缀的字符串被认为是以毫秒为单位保存的值。后缀不区分大小写。如果提供String包含不受支持的后缀或保留负数值或零或保存非数字值 - 则抛出IllegalArgumentException。此方法返回TimeInterval类 - 也是在此库中定义的类。本质上,它包含两个具有相关getter和setter的属性:long“value”和java.util.concurrent.TimeUnit。但除了getter和setter之外,这个类还有方法toMillis(),toSeconds(),toMinutes(),toHours()toDays()。这些方法在指定的时间范围内返回长值(与java.util.concurrent.TimeUnit类中的对应方法相同)

此方法对于解析时间间隔属性(如超时或配置文件中的等待时间)非常有用。它消除了从不同时间尺度到来回毫秒的不必要计算。请考虑您有一个需要设置5天的methodInvokingInterval属性。因此,为了设置毫秒值,您需要计算5天是432000000毫秒(显然不是一个不可能的任务,但烦人且容易出错)然后看到值432000000的任何其他人将不得不计算回到5天令人沮丧。但是使用此方法,您将具有设置为“5d”的属性值并调用代码

long seconds = TextUtils.parsingStringToTimeInterval("5d").toSeconds();

将解决您的转化问题。显然,这不是一个过于复杂的功能,但它可以在配置文件中增加简单性和清晰度,并将一些挫败感和“愚蠢”错误计算保存到几毫秒的错误中。以下是描述MgntUtils库的文章的链接以及获取它的位置:MgntUtils

答案 3 :(得分:0)

我通常需要支持原始数字,以[m | h | d | s | w]结尾的字符串

此版本将处理:10,“ 10”,“ 10s”,“ 10m”,“ 10h”,“ 10d”,“ 10w”。

关于字符串转换的@Eli Courtwright answer的提示。

UNITS = {"s":"seconds", "m":"minutes", "h":"hours", "d":"days", "w":"weeks"}

def convert_to_seconds(s):
    if isinstance(s, int):
        # We are dealing with a raw number
        return s

    try:
        seconds = int(s)
        # We are dealing with an integer string
        return seconds
    except ValueError:
        # We are dealing with some other string or type
        pass

    # Expecting a string ending in [m|h|d|s|w]
    count = int(s[:-1])
    unit = UNITS[ s[-1] ]
    td = timedelta(**{unit: count})
    return td.seconds + 60 * 60 * 24 * td.days

答案 4 :(得分:0)

另一个要添加到组合中。 此解决方案很简短,但相当宽容,并且可以使用倍数,例如10m 30s

from datetime import timedelta
import re

UNITS = {'s':'seconds', 'm':'minutes', 'h':'hours', 'd':'days', 'w':'weeks'}

def convert_to_seconds(s):
    return int(timedelta(**{
        UNITS.get(m.group('unit').lower(), 'seconds'): int(m.group('val'))
        for m in re.finditer(r'(?P<val>\d+)(?P<unit>[smhdw]?)', s, flags=re.I)
    }).total_seconds())

测试结果:

>>> convert_to_seconds('10s')
10
>>> convert_to_seconds('1')  # defaults to seconds
1
>>> convert_to_seconds('1m 10s')  # chaining
70
>>> convert_to_seconds('1M10S')  # case insensitive
70
>>> convert_to_seconds('1week 3days')  # ignores 'eek' and 'ays'
864000

不完美

>>> convert_to_seconds('1month 3days')  # actually 1minute + 3 days
259260
>>> convert_to_seconds('40s 10s')  # 1st value clobbered by 2nd
10