18

The code below should return last Friday, 16:00:00. But it returns Friday of previous week. How to fix that?

now = datetime.datetime.now()
test = (now - datetime.timedelta(days=now.weekday()) + timedelta(days=4, weeks=-1))
test = test.replace(hour=16,minute=0,second=0,microsecond=0)

Upd. I use the following approach now - is it the best one?

now = datetime.datetime.now()
if datetime.datetime.now().weekday() > 4:
    test = (now - datetime.timedelta(days=now.weekday()) + timedelta(days=4))
else:
    test = (now - datetime.timedelta(days=now.weekday()) + timedelta(days=4, weeks=-1))
test = test.replace(hour=16,minute=0,second=0,microsecond=0)

Upd2. Just to give an example. Let's assume that today is Oct 5, 2012. In case current time is equal to or less than 16:00 it should return Sep 28, 2012, otherwise - Oct 5, 2012.

Community
  • 1
  • 1
LA_
  • 19,823
  • 58
  • 172
  • 308

6 Answers6

44

The dateutil library is great for things like this:

>>> from datetime import datetime
>>> from dateutil.relativedelta import relativedelta, FR
>>> datetime.now() + relativedelta(weekday=FR(-1))
datetime.datetime(2012, 9, 28, 9, 42, 48, 156867)
jfs
  • 399,953
  • 195
  • 994
  • 1,670
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
17

As in the linked question, you need to use datetime.date objects instead of datetime.datetime. To get a datetime.datetime in the end, you can use datetime.datetime.combine():

import datetime

current_time = datetime.datetime.now()

# get friday, one week ago, at 16 o'clock
last_friday = (current_time.date()
    - datetime.timedelta(days=current_time.weekday())
    + datetime.timedelta(days=4, weeks=-1))
last_friday_at_16 = datetime.datetime.combine(last_friday, datetime.time(16))

# if today is also friday, and after 16 o'clock, change to the current date
one_week = datetime.timedelta(weeks=1)
if current_time - last_friday_at_16 >= one_week:
    last_friday_at_16 += one_week
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • Looks like your code if today is Oct 6, 2012 will return Sep 28, when Oct 5 is expected. – LA_ Oct 02 '12 at 08:47
  • Thanks. I have to clearly explain what I need next time... Your code on Oct 5, 2012 will always return Sep 28, 2012. But in case current time is equal to or less than 16:00 it should return Sep 28, 2012, otherwise - Oct 5, 2012. – LA_ Oct 02 '12 at 10:20
4

This was borrowed from Jon Clements, but is the full solution:

>>> from datetime import datetime
>>> from dateutil.relativedelta import relativedelta, FR
>>> lastFriday = datetime.now() + relativedelta(weekday=FR(-1))
>>> lastFriday.replace(hour=16,minute=0,second=0,microsecond=0)
datetime.datetime(2012, 9, 28, 16, 0, 0, 0)
bohney
  • 1,187
  • 8
  • 12
4

Simplest solution without dependency:

from datetime import datetime, timedelta

def get_last_friday():
    now = datetime.now()
    closest_friday = now + timedelta(days=(4 - now.weekday()))
    return (closest_friday if closest_friday < now
            else closest_friday - timedelta(days=7))
Bertrand Bordage
  • 921
  • 9
  • 16
1

The principle is the same as in your other question.

Get the friday of the current week and, if we are later, subtract one week.

import datetime
from datetime import timedelta
now = datetime.datetime.now()
today = now.replace(hour=16,minute=0,second=0,microsecond=0)
sow = (today - datetime.timedelta(days=now.weekday()))
this_friday = sow + timedelta(days=4)
if now > this_friday:
     test = this_friday
else:
     test = this_friday + timedelta(weeks=-1)
Community
  • 1
  • 1
glglgl
  • 89,107
  • 13
  • 149
  • 217
0

Could be lame but to me simplest. Get the last day of the current month and start checking in a loop (which wouldn't cost anything since max loops before finding last friday is 7) for friday. if last day is not friday decrement and the check the day before.

import calendar
from datetime import datetime, date

def main():
    year = datetime.today().year    
    month = datetime.today().month  
    x = calendar.monthrange(year,month)
    lastday = x[1]
    while True:
        z = calendar.weekday(year, month, lastday)
        if z != 4:
            lastday -= 1
        else:
            print(date(year,month,lastday))
            break

if __name__ == "__main__":
    main()