How can you calculate the following Friday at 3am as a datetime
object?
Clarification: i.e., the calculated date should always be greater than 7 days away, and less than or equal to 14.
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
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
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;-).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With