在 Python 中向 datetime.time 添加 N 秒的标准方法是什么?

2025-01-09 08:46:00
admin
原创
133
摘要:问题描述:在 Python 中,给定一个datetime.time值,是否有一种标准方法可以向该值添加整数秒数,例如11:34:59+ 3 = 11:35:02?这些显而易见的想法不起作用:>>> datetime.time(11, 34, 59) + 3 TypeError: unsupp...

问题描述:

在 Python 中,给定一个datetime.time值,是否有一种标准方法可以向该值添加整数秒数,例如11:34:59+ 3 = 11:35:02

这些显而易见的想法不起作用:

>>> datetime.time(11, 34, 59) + 3
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'int'
>>> datetime.time(11, 34, 59) + datetime.timedelta(0, 3)
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.timedelta'
>>> datetime.time(11, 34, 59) + datetime.time(0, 0, 3)
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.time'

最后我写了如下函数:

def add_secs_to_time(timeval, secs_to_add):
    secs = timeval.hour * 3600 + timeval.minute * 60 + timeval.second
    secs += secs_to_add
    return datetime.time(secs // 3600, (secs % 3600) // 60, secs % 60)

我禁不住想到我错过了一种更简单的方法来做到这一点。

有关的

  • python 时间 + timedelta 等效项


解决方案 1:

您可以使用完整datetime变量timedelta,并通过提供一个虚拟日期然后使用它time来获取时间值。

例如:

import datetime
a = datetime.datetime(100,1,1,11,34,59)
b = a + datetime.timedelta(0,3) # days, seconds, then other fields.
print(a.time())
print(b.time())

得出两个值,相隔三秒:

11:34:59
11:35:02

你也可以选择更易读的

b = a + datetime.timedelta(seconds=3)

如果你愿意的话。


如果您需要实现此功能,可以研究addSecs以下方法:

import datetime

def addSecs(tm, secs):
    fulldate = datetime.datetime(100, 1, 1, tm.hour, tm.minute, tm.second)
    fulldate = fulldate + datetime.timedelta(seconds=secs)
    return fulldate.time()

a = datetime.datetime.now().time()
b = addSecs(a, 300)
print(a)
print(b)

输出如下:

 09:11:55.775695
 09:16:55

解决方案 2:

正如其他人所说,您可以始终使用完整的日期时间对象:

from datetime import datetime, date, time, timedelta
sometime = time(8,00) # 8am
later = (datetime.combine(date.today(), sometime) + timedelta(seconds=3)).time()

但是,我认为有必要解释一下为什么需要完整的日期时间对象。考虑一下如果我在晚上 11 点加上 2 个小时会发生什么。正确的行为是什么?一个例外,因为你不能有大于晚上 11:59 的时间?它应该绕回来吗?

不同的程序员会有不同的期望,因此无论他们选择哪种结果都会让很多人感到惊讶。更糟糕的是,程序员编写的代码在最初测试时运行良好,然后后来由于做了一些意想不到的事情而导致代码崩溃。这非常糟糕,这就是为什么不允许将 timedelta 对象添加到 time 对象的原因。

解决方案 3:

一件小事可能会增加清晰度以覆盖秒的默认值

>>> b = a + datetime.timedelta(seconds=3000)
>>> b
datetime.datetime(1, 1, 1, 12, 24, 59)

解决方案 4:

您不能简单地添加数字,datetime因为不清楚使用的是什么单位:秒、小时、周......

有一个timedelta用于操作日期和时间的类。datetime减法datetime得到timedeltadatetime加法timedelta得到datetime,两个datetime对象可以相加,但timedelta不能相加。

创建timedelta对象并指定要添加的秒数,然后将其添加到datetime对象中:

>>> from datetime import datetime, timedelta
>>> t = datetime.now() + timedelta(seconds=3000)
>>> print(t)
datetime.datetime(2018, 1, 17, 21, 47, 13, 90244)

C++ 中也有同样的概念:std::chrono::duration

解决方案 5:

感谢@Pax Diablo、@bvmou 和@Arachnid 建议始终使用完整日期时间。如果我必须从外部源接受 datetime.time 对象,那么这似乎是一个替代add_secs_to_time()函数:

def add_secs_to_time(timeval, secs_to_add):
    dummy_date = datetime.date(1, 1, 1)
    full_datetime = datetime.datetime.combine(dummy_date, timeval)
    added_datetime = full_datetime + datetime.timedelta(seconds=secs_to_add)
    return added_datetime.time()

这段详细代码可以压缩为一行:

(datetime.datetime.combine(datetime.date(1, 1, 1), timeval) + datetime.timedelta(seconds=secs_to_add)).time()

但无论如何,我认为为了代码清晰起见,我还是想把它包装在一个函数中。

解决方案 6:

如果有必要向您的项目添加另一个文件/依赖项,我刚刚编写了一个很小的类,它扩展了datetime.time算术能力。当您超过午夜时,它会绕零旋转。现在,“从现在起 24 小时后是几点”有很多极端情况,包括夏令时、闰秒、历史时区变化等等。但有时您确实需要简单的情况,这就是它能做到的。

你的例子可以这样写:

>>> import datetime
>>> import nptime
>>> nptime.nptime(11, 34, 59) + datetime.timedelta(0, 3)
nptime(11, 35, 2)

nptime继承自datetime.time,因此任何这些方法也应该可以使用。

它可以从 PyPi 获得nptime(“非迂腐时间”),也可以在 GitHub 上获得:https ://github.com/tgs/nptime

解决方案 7:

在现实环境中,单独使用从来都不是一个好主意time,总是使用datetime,甚至更好utc,以避免诸如隔夜、夏令时、用户和服务器之间的不同时区等冲突。

因此我推荐这种方法:

import datetime as dt

_now = dt.datetime.now()  # or dt.datetime.now(dt.timezone.utc)
_in_5_sec = _now + dt.timedelta(seconds=5)

# get '14:39:57':
_in_5_sec.strftime('%H:%M:%S')

解决方案 8:

arrow为了完整起见,这里是使用(Python 的更好的日期和时间)的方法:

sometime = arrow.now()
abitlater = sometime.shift(seconds=3)

解决方案 9:

如果您还没有 timedelta 对象,另一种可能性是仅使用旧对象的属性初始化一个新的时间对象并在需要时添加值:

   new_time:time = time(
       hour=curr_time.hour + n_hours,
       minute=curr_time.minute + n_minutes,
       seconds=curr_time.second + n_seconds
    )

诚然,这只有在你对值做出一些假设时才有效,因为这里不处理溢出。但我认为记住这一点是值得的,因为它可以节省一两行

解决方案 10:

尝试将 a 添加datetime.datetime到 a datetime.timedelta。如果您只想要时间部分,可以调用time()结果datetime.datetime对象上的方法来获取它。

解决方案 11:

老问题了,但我想我会加入一个处理时区的函数。关键部分是将datetime.time对象的tzinfo属性传递给组合,然后在生成的虚拟日期时间上使用timetz()而不是。这个答案部分受到此处其他答案的启发。time()

def add_timedelta_to_time(t, td):
    """Add a timedelta object to a time object using a dummy datetime.

    :param t: datetime.time object.
    :param td: datetime.timedelta object.

    :returns: datetime.time object, representing the result of t + td.

    NOTE: Using a gigantic td may result in an overflow. You've been
    warned.
    """
    # Create a dummy date object.
    dummy_date = date(year=100, month=1, day=1)

    # Combine the dummy date with the given time.
    dummy_datetime = datetime.combine(date=dummy_date, time=t, tzinfo=t.tzinfo)

    # Add the timedelta to the dummy datetime.
    new_datetime = dummy_datetime + td

    # Return the resulting time, including timezone information.
    return new_datetime.timetz()

这是一个非常简单的测试用例类(使用内置的unittest):

import unittest
from datetime import datetime, timezone, timedelta, time

class AddTimedeltaToTimeTestCase(unittest.TestCase):
    """Test add_timedelta_to_time."""

    def test_wraps(self):
        t = time(hour=23, minute=59)
        td = timedelta(minutes=2)
        t_expected = time(hour=0, minute=1)
        t_actual = add_timedelta_to_time(t=t, td=td)
        self.assertEqual(t_expected, t_actual)

    def test_tz(self):
        t = time(hour=4, minute=16, tzinfo=timezone.utc)
        td = timedelta(hours=10, minutes=4)
        t_expected = time(hour=14, minute=20, tzinfo=timezone.utc)
        t_actual = add_timedelta_to_time(t=t, td=td)
        self.assertEqual(t_expected, t_actual)


if __name__ == '__main__':
    unittest.main()
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3740  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2617  
  敏捷每日站会作为敏捷项目管理中的关键环节,对于提升产品生命周期管理(PLM)效率有着不可忽视的作用。PLM涵盖了产品从概念产生到最终报废的全过程管理,涉及众多环节与人员,而每日站会能够通过优化沟通机制,让信息在团队中快速、准确地流动,从而推动整个PLM流程更加顺畅、高效。接下来,我们将深入探讨如何通过四步优化沟通机制,...
plm系统   91  
  在企业的发展进程中,产品生命周期管理(PLM)项目管理至关重要,而数据驱动决策则是提升PLM项目管理效能的关键手段。通过运用合适的分析模型,企业能够从海量数据中挖掘有价值的信息,为决策提供有力支撑,进而优化产品全生命周期的各个环节。以下将详细介绍助力PLM项目管理实现数据驱动决策的5大分析模型。需求分析模型需求分析是P...
plm系统功能介绍   94  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与运营中扮演着至关重要的角色。它涵盖了从产品概念设计到退役的全流程管理,确保产品数据的有效整合与协同。然而,在复杂多变的商业环境中,黑天鹅事件随时可能降临,给企业带来难以预估的冲击。这些意外事件具有不可预测性、极大的影响力和事后的可解释性等特点,会对PLM系统的正常运...
plm系统的主要功能模块   92  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用