How to calculate next Friday at 3am?

穿精又带淫゛_ 提交于 2019-12-05 02:04:00

Here's a function and a test that it meets the OP's requirements:

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

If you install dateutil, then you could do something like this:

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

Above, hours=+21 tells relativedelta to increment the dt by 21 hours before finding the next Friday. So, if dt is March 12, 2010 at 2am, adding 21 hours makes it 11pm of the same day, but if dt is after 3am, then adding 21 hours pushs dt into Saturday.

Here is some test code.

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)))

which yields:

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

while before 3am:

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))

yields:

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

I like dateutil for such tasks in general, but I don't understand the heuristics you want -- as I use the words, if I say "next Friday" and it's Thursday I would mean tomorrow (probably I've been working too hard and lost track of what day of the week it is). If you can specify your heuristics rigorously they can surely be programmed, of course, but if they're weird and quirky enough you're unlikely to find them already pre-programmed for you in existing packages;-).

Based on your clarification... I think you can do something like this:

from datetime import *
>>> today = datetime.today()
>>> todayAtThreeAm = datetime(today.year, today.month, today.day, 3)
>>> todayAtThreeAm
datetime.datetime(2010, 3, 12, 3, 0)
>>> nextFridayAtThreeAm = todayAtThreeAm + timedelta(12 - today.isoweekday())
>>> nextFridayAtThreeAm
datetime.datetime(2010, 3, 19, 3, 0)

Notice isoweekday() returns 1 to 7 for monday to sunday. 12 represents friday of the following week. So 12 - today.isoweekday() gives you the correct time delta you need to add to today.

Hope this helps.

With pendulum, you can do:

In [15]: pendulum.now().next(pendulum.FRIDAY).next(pendulum.FRIDAY).add(hours=3)
Out[15]: DateTime(2019, 5, 3, 3, 0, 0, tzinfo=Timezone('America/Los_Angeles'))

Note that there are two next Friday in this line.

To convert it into string,

In [16]: pendulum.now().next(pendulum.FRIDAY).next(pendulum.FRIDAY).add(hours=3).to_iso8601_string()
Out[16]: '2019-05-03T03:00:00-07:00'
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!