缺少 datetime.timedelta.to_seconds() -> Python 中的浮动?

发布于 2024-07-26 15:25:10 字数 1090 浏览 6 评论 0原文

我知道出于效率原因,秒和微秒可能会在 datetime.timedelta 中单独表示,但我只是编写了这个简单的函数:

def to_seconds_float(timedelta):
    """Calculate floating point representation of combined
    seconds/microseconds attributes in :param:`timedelta`.

    :raise ValueError: If :param:`timedelta.days` is truthy.

        >>> to_seconds_float(datetime.timedelta(seconds=1, milliseconds=500))
        1.5
        >>> too_big = datetime.timedelta(days=1, seconds=12)
        >>> to_seconds_float(too_big) # doctest: +ELLIPSIS
        Traceback (most recent call last):
        ...
        ValueError: ('Must not have days', datetime.timedelta(1, 12))
    """
    if timedelta.days:
        raise ValueError('Must not have days', timedelta)
    return timedelta.seconds + timedelta.microseconds / 1E6

这​​对于向 time.sleep< 传递值之类的事情很有用/code> 或 select.select为什么datetime.timedelta接口中没有类似的东西?我可能会遗漏一些极端情况。 时间表示似乎有很多不明显的极端情况......

我拒绝了几天以在一定精度上进行合理的尝试(我懒得实际计算出数学ATM,所以这似乎是一个合理的妥协; -)。

I understand that seconds and microseconds are probably represented separately in datetime.timedelta for efficiency reasons, but I just wrote this simple function:

def to_seconds_float(timedelta):
    """Calculate floating point representation of combined
    seconds/microseconds attributes in :param:`timedelta`.

    :raise ValueError: If :param:`timedelta.days` is truthy.

        >>> to_seconds_float(datetime.timedelta(seconds=1, milliseconds=500))
        1.5
        >>> too_big = datetime.timedelta(days=1, seconds=12)
        >>> to_seconds_float(too_big) # doctest: +ELLIPSIS
        Traceback (most recent call last):
        ...
        ValueError: ('Must not have days', datetime.timedelta(1, 12))
    """
    if timedelta.days:
        raise ValueError('Must not have days', timedelta)
    return timedelta.seconds + timedelta.microseconds / 1E6

This is useful for things like passing a value to time.sleep or select.select. Why isn't something like this part of the datetime.timedelta interface? I may be missing some corner case. Time representation seems to have so many non-obvious corner cases...

I rejected days right out to have a reasonable shot at some precision (I'm too lazy to actually work out the math ATM, so this seems like a reasonable compromise ;-).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅暮の光 2024-08-02 15:25:10

Python 浮点数大约有 15 位有效数字,因此秒数最多为 86400(小数点左边 5 位数字),微秒需要 6 位数字,您可以很好地包括天数(最多几年的价值)而不会丢失精确。

一个好的口头禅是“pi 秒是一个纳世纪”——大约每 100 年 3.14E9 秒,即每年 3E7,因此每年 3E13 微秒。 这个咒语很好,因为它很容易记住,尽管它确实需要你事后做一些心算(但是,就像菠菜一样,它对你有好处——让你保持敏捷和警觉!-)。

datetime 的设计理念有些简约,因此它省略了许多可能归结为简单算术表达式的辅助方法也就不足为奇了。

A Python float has about 15 significant digits, so with seconds being up to 86400 (5 digits to the left of the decimal point) and microseconds needing 6 digits, you could well include the days (up to several years' worth) without loss of precision.

A good mantra is "pi seconds is a nanocentury" -- about 3.14E9 seconds per 100 years, i.e. 3E7 per year, so 3E13 microseconds per year. The mantra is good because it's memorable, even though it does require you to do a little mental arithmetic afterwards (but, like spinach, it's GOOD for you -- keeps you nimble and alert!-).

The design philosophy of datetime is somewhat minimalist, so it's not surprising it omits many possible helper methods that boil down to simple arithmetic expressions.

七颜 2024-08-02 15:25:10

您对精度的关注是错误的。 这是一个简单的两行代码,用于粗略计算您可以将 IEEE754 64 位浮点数中 53 位精度的剩余部分压缩为多少年:

>>> import math
>>> 10 ** (math.log10(2 ** 53) - math.log10(60 * 60 * 24) - 6) / 365.25
285.42092094268787
>>>

注意四舍五入; 首先添加最小的非零数:

return timedelta.seconds + timedelta.microseconds / 1E6 + timedelta.days * 86400

Your concern for precision is misplaced. Here's a simple two-liner to calculate roughly how many YEARS you can squeeze into what's left of the 53 bits of precsion in an IEEE754 64-bit float:

>>> import math
>>> 10 ** (math.log10(2 ** 53) - math.log10(60 * 60 * 24) - 6) / 365.25
285.42092094268787
>>>

Watch out for round-off; add the smallest non-zero numbers first:

return timedelta.seconds + timedelta.microseconds / 1E6 + timedelta.days * 86400
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文