如何计算下周五凌晨3点?

11 投票
5 回答
3023 浏览
提问于 2025-04-15 20:22

你怎么能计算出下一个星期五的凌晨3点,作为一个datetime对象呢?

说明:也就是说,计算出来的日期应该总是比现在的日期大于7天,但不超过14天。

5 个回答

4

我一般喜欢用dateutil来处理这类任务,但我不太明白你想要的那些规则是什么。比如说,如果我说“下个星期五”,而今天是星期四,我肯定是指明天(可能是因为我工作太忙,搞混了今天是星期几)。如果你能把你的规则说得清清楚楚,那当然可以编程实现,但如果这些规则比较奇怪或者特别,你可能在现有的工具包里找不到已经写好的代码来满足这些需求;-)。

9

如果你安装了 dateutil 这个库,你就可以做类似下面的事情:

import datetime
import dateutil.relativedelta as reldate

def following_friday(dt):   
    rd=reldate.relativedelta(
        weekday=reldate.FR(+2),
        hours=+21)
    rd2=reldate.relativedelta(
        hour=3,minute=0,second=0,microsecond=0)
    return dt+rd+rd2

上面的 hours=+21 是告诉 relativedelta 在找到下一个星期五之前,把 dt 增加21个小时。所以,如果 dt 是2010年3月12日的凌晨2点,增加21个小时后就变成了同一天的晚上11点。但如果 dt 是在凌晨3点之后,那么增加21个小时就会把 dt 推到星期六。

这里有一些测试代码。

if __name__=='__main__':
    today=datetime.datetime.now()
    for dt in [today+datetime.timedelta(days=i) for i in range(-7,8)]:
        print('%s --> %s'%(dt,following_friday(dt)))

运行后会得到:

2010-03-05 20:42:09.246124 --> 2010-03-19 03:00:00
2010-03-06 20:42:09.246124 --> 2010-03-19 03:00:00
2010-03-07 20:42:09.246124 --> 2010-03-19 03:00:00
2010-03-08 20:42:09.246124 --> 2010-03-19 03:00:00
2010-03-09 20:42:09.246124 --> 2010-03-19 03:00:00
2010-03-10 20:42:09.246124 --> 2010-03-19 03:00:00
2010-03-11 20:42:09.246124 --> 2010-03-19 03:00:00
2010-03-12 20:42:09.246124 --> 2010-03-26 03:00:00 
2010-03-13 20:42:09.246124 --> 2010-03-26 03:00:00
2010-03-14 20:42:09.246124 --> 2010-03-26 03:00:00
2010-03-15 20:42:09.246124 --> 2010-03-26 03:00:00
2010-03-16 20:42:09.246124 --> 2010-03-26 03:00:00
2010-03-17 20:42:09.246124 --> 2010-03-26 03:00:00
2010-03-18 20:42:09.246124 --> 2010-03-26 03:00:00
2010-03-19 20:42:09.246124 --> 2010-04-02 03:00:00

在凌晨3点之前:

two = datetime.datetime(2010, 3, 12, 2, 0)
for date in [two+datetime.timedelta(days=i) for i in range(-7,8)]:
    result = following_friday(date)
    print('{0}-->{1}'.format(date,result))

得到的结果是:

2010-03-05 02:00:00-->2010-03-12 03:00:00
2010-03-06 02:00:00-->2010-03-19 03:00:00
2010-03-07 02:00:00-->2010-03-19 03:00:00
2010-03-08 02:00:00-->2010-03-19 03:00:00
2010-03-09 02:00:00-->2010-03-19 03:00:00
2010-03-10 02:00:00-->2010-03-19 03:00:00
2010-03-11 02:00:00-->2010-03-19 03:00:00
2010-03-12 02:00:00-->2010-03-19 03:00:00
2010-03-13 02:00:00-->2010-03-26 03:00:00
2010-03-14 02:00:00-->2010-03-26 03:00:00
2010-03-15 02:00:00-->2010-03-26 03:00:00
2010-03-16 02:00:00-->2010-03-26 03:00:00
2010-03-17 02:00:00-->2010-03-26 03:00:00
2010-03-18 02:00:00-->2010-03-26 03:00:00
2010-03-19 02:00:00-->2010-03-26 03:00:00
7

这里有一个函数和一个测试,确保它符合提问者的要求:

import datetime

_3AM = datetime.time(hour=3)
_FRI = 4 # Monday=0 for weekday()

def next_friday_3am(now):
    now += datetime.timedelta(days=7)
    if now.time() < _3AM:
        now = now.combine(now.date(),_3AM)
    else:
        now = now.combine(now.date(),_3AM) + datetime.timedelta(days=1)
    return now + datetime.timedelta((_FRI - now.weekday()) % 7)

if __name__ == '__main__':
    start = datetime.datetime.now()
    for i in xrange(7*24*60*60):
        now = start + datetime.timedelta(seconds=i)
        then = next_friday_3am(now)
        assert datetime.timedelta(days=7) < then - now <= datetime.timedelta(days=14)
        assert then.weekday() == _FRI
        assert then.time() == _3AM

撰写回答