【问题标题】:Python: Given a Date and Weekday find the date of the next occurrence of a given weekdayPython:给定日期和工作日找到给定工作日的下一次出现的日期
【发布时间】:2012-01-03 04:52:13
【问题描述】:

这有点难以解释,所以如果这没有多大意义,我深表歉意。

我有一个程序,我正在做一些调度。它的一项设置是在某些日子每周运行一项任务。例如,每周一、周三和周五。

考虑当前任务计划在 2012 年 1 月 2 日(星期一)的示例,我已经有一堆代码工作到我知道下一个任务应该在 1 之后的星期三运行的地步2/2012。我需要做的就是计算那个星期三(2012 年 1 月 4 日)的实际日期。

我实际上将星期几作为 date.weekday() 中的相应整数,所以在这种情况下,我有 2 代表星期三。

处理此类事情的最佳方法是什么?我觉得应该有一个相当简单的解决方案,但没有想到。我正在考虑使用日历对象来搜索我想要的星期几,但这似乎有点过头了。

【问题讨论】:

    标签: python datetime timedelta


    【解决方案1】:

    使用dateutil.relativedelta:

    from dateutil import relativedelta
    import datetime
    
    today = datetime.date.today()
    # datetime.date(2012, 1, 3)
    
    today + relativedelta.relativedelta(weekday=2) # 2 is Wednesday
    # datetime.date(2012, 1, 4)
    
    today + relativedelta.relativedelta(weekday=6) # 6 is Sunday
    # datetime.date(2012, 1, 8)
    
    today + relativedelta.relativedelta(weekday=1) # 1 is Tuesday
    # datetime.date(2012, 1, 3)
    # returns today
    
    today + relativedelta.relativedelta(weeks=1, weekday=1)
    # datetime.date(2012, 1, 10)
    # returns Tuesday at least one week ahead
    

    【讨论】:

      【解决方案2】:

      使用timedelta 添加日期。例如,使用某个日期 d 作为当前任务的计划日期,某天 next_day(您希望运行该任务的下一个)。

      from datetime import date, timedelta
      ...
      n = (next_day - d.weekday()) % 7 # mod-7 ensures we don't go backward in time
      next_run_date = d + timedelta(days=n)
      

      【讨论】:

      • 这似乎对我不起作用。当我对更改进行单元测试时,它已经关闭了几天。我认为在 Python 中,星期一是 0 和星期日是 6 可能会让事情变得糟糕。我认为星期一是 0 会抛出这个问题,但我不确定。
      • 我想你想要next_day - d.weekday()
      • 谢谢@MarkRansom,我认为你是对的,我修正了我的答案。 @Jon,你能再试一次吗?只要 next_day 使用相同的约定,我认为 Monday=0 应该不是问题。
      • 现在可以了,感谢您的帮助。我最初正在尝试一些非常相似的东西,但它并不完全正确。我所有的单元测试现在都通过了。
      【解决方案3】:

      我们知道:

      • 星期一星期三有 2 天的差异。
      • 星期三星期五有 2 天的差异。
      • 星期五星期一相差 3 天。

      所以,这就像添加计划任务之间的差异天数一样简单:

      from datetime import datetime, timedelta
      first_scheduled_task = datetime(year=2012, month=1, day=2)
      second_scheduled_task = first_scheduled_task + timedelta(2)
      third_scheduled_task = second_scheduled_task + timedelta(2)
      fourth_scheduled_task = third_scheduled_task + timedelta(3)
      

      这会给我们一个结果:

      >>> first_scheduled_task
      datetime.datetime(2012, 1, 2, 0, 0) # Monday 1/2/2012
      >>> second_scheduled_task
      datetime.datetime(2012, 1, 4, 0, 0) # Wednesday 1/4/2012
      >>> third_scheduled_task
      datetime.datetime(2012, 1, 6, 0, 0) # Friday 1/6/2012
      >>> fourth_scheduled_task
      datetime.datetime(2012, 1, 9, 0, 0) # Monday 1/9/2012
      

      【讨论】:

      • 我应该澄清我使用星期一和星期三作为一个通用示例。重复可以是天数的任意组合。例如,星期一、星期四、星期六。所以这行不通。
      【解决方案4】:

      使用dateutil 处理计划和重复。

      【讨论】:

        猜你喜欢
        • 2011-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-23
        相关资源
        最近更新 更多