Как пройти в прошлую пятницу?

Код ниже должен вернуться в прошлую пятницу, 16:00:00. Но он возвращается в пятницу предыдущей недели. Как это исправить?

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. Сейчас я использую следующий подход - это лучший?

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. Просто чтобы привести пример. Предположим, что сегодня 5 октября 2012 года. Если текущее время равно или меньше 16:00, оно должно вернуться 28 сентября 2012 года, в противном случае - 5 октября 2012 года.

6 ответов

Решение

Как и в связанном вопросе, вам нужно использовать datetime.date объекты вместо datetime.datetime, Чтобы получить datetime.datetime в конце концов, вы можете использовать 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

dateutil библиотека отлично подходит для таких вещей:

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

Самое простое решение без зависимости:

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

Это было заимствовано у Джона Клемента, но это полное решение:

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

Принцип тот же, что и в вашем другом вопросе.

Получить пятницу текущей недели и, если мы позже, вычтите одну неделю.

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)

Может быть хромым, но для меня самое простое. Получите последний день текущего месяца и начните проверку в цикле (который не будет стоить ничего, так как максимальное количество циклов до того, как будет найдена последняя пятница - 7) для пятницы. если последний день не является пятницей декремента и чека накануне.

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()
Другие вопросы по тегам