【问题标题】:Using datetime.timedelta to add years使用 datetime.timedelta 添加年份
【发布时间】:2019-06-21 00:04:36
【问题描述】:

我正在用 Python 做一些时间计算。

目标:

其中一部分是试图:

给定一个日期,加上时间间隔(X年,X月,X周),返回日期

  • 输入参数:input_time (datetime.date)、interval (datetime.timedelta)
  • 返回:datetime.date

我查看了日期时间和datetime.timedelta docs

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, week=0)¶

如果我想增加一定的小时数或周数,这些似乎很有效。不过,

问题:

  • 我正在尝试实现诸如 date + 1 year 之类的操作,但无法弄清楚

例如

start = datetime.datetime(2000, 1, 1)
# expected output: datetime.datetime(2001, 1, 1)


# with the weeks, etc arguments given in timedelta, this fails unsurprisingly e.g 
start + datetime.timedelta(weeks = 52)

# returns datetime.datetime(2000, 12, 30, 0, 0)

问题

  • 这种基于年份的操作是否可以使用 datetime 的基本工具进行 - 如果可以,我将如何进行?

  • 我意识到对于年份的例子,我可以只做start.replace(year = 2001),但如果我有几个月或几周的输入,这种方法就会失败。

  • 据我了解,dateutil 库具有更高级的功能,但我不清楚它与内置日期时间对象的交互效果如何。

我已经查看过类似的question,但这对我没有帮助。

非常感谢任何帮助!

在 MacO 上运行 Python 3.6.5。

【问题讨论】:

    标签: python datetime timedelta python-dateutil


    【解决方案1】:

    timedelta 不支持年份,因为一年的持续时间取决于哪一年(例如闰年有 2 月 29 日)。

    您可以改用relativedelta,它确实支持years,并考虑了添加的基线日期:

    >>> from dateutil.relativedelta import relativedelta
    >>> now = datetime.now()
    >>> now 
    datetime.datetime(2019, 1, 27, 19, 4, 11, 628081)
    >>> now + relativedelta(years=1)
    datetime.datetime(2020, 1, 27, 19, 4, 11, 628081)
    

    【讨论】:

    • 谢谢,这看起来真的很好,我想出了闰年的部分...查看 docs 的 relativdelta,他们始终使用语法 years=+1 ,您使用 years=1 .测试出来,他们似乎做同样的事情,还是两者之间有区别?
    • @patrick 可能为时已晚,您对语法years=+1 发表评论;这意味着前进或后退,所以如果你必须回到一年,你会做years=-1。来自文档:Relative information, may be negative (argument is plural); adding or subtracting a relativedelta with relative information performs the corresponding aritmetic operation on the original datetime value with the information in the relativedelta.
    【解决方案2】:

    您可以使用替换来硬编码日期时间的新年份值 :) 这样可以避免闰年等​​。

    year_later = current.replace(year=current.year + 1)
    

    【讨论】:

    • 但是如果现在是 2 月 29 日,闰年呢?
    【解决方案3】:

    我的快速而肮脏的方法是使用

    y = [number of years]
    timedelta(days= y * 365)
    

    我发现这个问题正在寻找更优雅的解决方案。对于我的用途,不需要精确的答案。在这种特殊情况下,我不介意每个闰年损失一天。

    【讨论】:

      【解决方案4】:

      我的目标和你的非常相似。我想有相同的日期,就在明年。但我想我不能避免考虑闰年。最后,这一切都归结为需求到底是什么。从理论上讲,我们可以只增加 365 天(如果有 2 月 29 日,则放开一天),或者如果有 2 月 29 日,则检查接下来的 365 天,在这种情况下再增加 1 天。 但是检查会很复杂,最后我使用了一个简单的检查新日期的日期,如果它与原来的不同,然后再增加 1 天。 我理解 dateutil.relativedelta 更容易,但我想在没有额外导入的情况下做到这一点

      演示

      from datetime import datetime, timedelta
      
      dates = [datetime(1999, 1, 1),
               datetime(1999, 12, 31),
               datetime(2000, 1, 1),
               datetime(2019, 3, 1),
               datetime(2019, 1, 1),
               datetime(2020, 1, 1),
               datetime(2020, 3, 1),
               datetime(2020, 2, 29)
               ]
      for date in dates:
          plus1year_date = date + timedelta(days=365)
          print(date, "\t - original date")
          print(plus1year_date, "\t - plus1year_date (+365 days)")
          if date.day != plus1year_date.day:
              plus1year_date = plus1year_date + timedelta(days=1)
              print(plus1year_date, "\t - plus1year_date adjusted for leap year")
          else:
              print("No need to adjust for leap year")
          print('--------------------------------------------------------------')
      
      # Expected output:
      # 1999-01-01 00:00:00    - original date
      # 2000-01-01 00:00:00    - plus1year_date (+365 days)
      # No need to adjust for leap year
      # --------------------------------------------------------------
      # 1999-12-31 00:00:00    - original date
      # 2000-12-30 00:00:00    - plus1year_date (+365 days)
      # 2000-12-31 00:00:00    - plus1year_date adjusted for leap year
      # --------------------------------------------------------------
      # 2000-01-01 00:00:00    - original date
      # 2000-12-31 00:00:00    - plus1year_date (+365 days)
      # 2001-01-01 00:00:00    - plus1year_date adjusted for leap year
      # --------------------------------------------------------------
      # ...
      

      编辑:@MDoe - 我忘了提到,如果是 2 月 29 日,使用 .year + 1 方法可能会导致日期无效(ValueError)。 此外,如果有人想添加一个可能包含多个闰年的时间间隔,那么我的代码将不正确。

      【讨论】:

        猜你喜欢
        • 2021-07-08
        • 2022-12-30
        • 1970-01-01
        • 2023-01-16
        • 2011-05-24
        • 2015-12-24
        • 1970-01-01
        • 1970-01-01
        • 2014-05-10
        相关资源
        最近更新 更多