Alferd Nobel
Alferd Nobel

Reputation: 3949

getting the date for next weekday

Im checking if the current date is a weekday, if not I want to get the next weekday. Weekday is from Monday to Friday.

Here is what I have tried:

import time
from datetime import date,timedelta
dmy=time.strftime("%d-%m-%Y")# getting the current date 
if dmy.strftime("%w") in set([6,7]): # checking if its a weekend( Sat/Sun) , if so advancing
    dmy=time.strftime("%d-%m-%Y")+ timedelta(days=dmy.strftime("%w")%5) # this statement is not working, it errors out .  

The statement dmy=time.strftime("%d-%m-%Y")+ timedelta(days=dmy.strftime("%w")%5)) is not working. what is the easiest way to advance to the next date which is a weekday ?

Upvotes: 7

Views: 22007

Answers (5)

Alex
Alex

Reputation: 405

Why not use a polynomial function?

import datetime


def weekday_delta_polynomial(x: int) -> int:
    # This polynomial function behaves like this:
    # f(1)=1,f(2)=1,f(3)=1,f(4)=1,f(5)=3,f(6)=2,f(7)=1
    # which can be used to add the amount of days
    # needed from today to next business day
    if not 1 <= x <= 7:
        raise ValueError("Iso Weekday must be between 1 (Mon) and 7 (Sun)")

    polyday = (
        x**6/30 -
        (31*x**5)/40 +
        (169*x**4)/24 -
        (761*x**3)/24 +
        (2957*x**2)/40 -
        (5011*x)/60 + 36
    )
    weekday = int(round(polyday, 0))
    return weekday


def next_weekday(today: datetime.date) -> datetime.date:
    next_iso_weekday_delta = weekday_delta_polynomial(today.isoweekday())
    the_next_weekday = today + datetime.timedelta(days=next_iso_weekday_delta)
    return the_next_weekday


if __name__ == "__main__":
    # Mon -> Tue 2023-06-06
    print(next_weekday(datetime.date.fromisoformat("2023-06-05")))
    # Tue -> Wed 2023-06-07
    print(next_weekday(datetime.date.fromisoformat("2023-06-06")))
    # Wed -> Thu 2023-06-08
    print(next_weekday(datetime.date.fromisoformat("2023-06-07")))
    # Thu -> Fri 2023-06-09
    print(next_weekday(datetime.date.fromisoformat("2023-06-08")))
    # Fri -> Mon 2023-06-12
    print(next_weekday(datetime.date.fromisoformat("2023-06-09")))
    # Sat -> Mon 2023-06-12
    print(next_weekday(datetime.date.fromisoformat("2023-06-10")))
    # Sun -> Mon 2023-06-12
    print(next_weekday(datetime.date.fromisoformat("2023-06-11")))

Upvotes: 0

Miguel Pinheiro
Miguel Pinheiro

Reputation: 342

Answer:

import datetime
def to_week_day(date):
    if date.isoweekday() in set((6, 7)):
        date += datetime.timedelta(days=-date.isoweekday() + 8)
    return date

Explanation:

I faced this problem today, and @jonrsharpe's answer did not work for me because date.isoweekday() % 5 = 1 when it's saturday date.isoweekday() % 5 = 2 when it's sunday, resulting in the next week day being sunday and tuesday respectively, wich is wrong. I didn't wanted to use if statements in the code, so what I did was to find a function y = f(x) that returned y = 2 when x = 6 and y = 1 when x = 7.

This function is y = -x + 8 and it's used as argument in the timedelta function.

This answer was based on @jonrsharpe's answer so you should upvote him too.

Upvotes: 2

Hafiz Shehbaz Ali
Hafiz Shehbaz Ali

Reputation: 2676

give any day to function get_next_dayofweek_datetime and date_time.

from datetime import datetime as dt
from datetime import timedelta

def get_weekday(day):
    days  = ["mon","tue","wed","thu","fri","sat","sun"]
    return days.index(day) + 1

def get_next_dayofweek_datetime(date_time, dayofweek):
    start_time_w = date_time.isoweekday()
    target_w = get_weekday(dayofweek)
    if start_time_w < target_w:
      day_diff = target_w - start_time_w
    else:
        day_diff = 7 - (start_time_w - target_w)

    return date_time + timedelta(days=day_diff)

start_time = dt.strptime("2020-02-12 20:20:00", "%Y-%m-%d %H:%M:%S") # wednesday


print(get_next_dayofweek_datetime(start_time, "thu"))
print(get_next_dayofweek_datetime(start_time, "fri"))
print(get_next_dayofweek_datetime(start_time, "sat"))
print(get_next_dayofweek_datetime(start_time, "sun"))
print(get_next_dayofweek_datetime(start_time, "mon"))
print(get_next_dayofweek_datetime(start_time, "tue"))
print(get_next_dayofweek_datetime(start_time, "wed"))
print(get_next_dayofweek_datetime(start_time, "thu"))

output:

2020-02-13 20:20:00
2020-02-14 20:20:00
2020-02-15 20:20:00
2020-02-16 20:20:00
2020-02-17 20:20:00
2020-02-18 20:20:00
2020-02-19 20:20:00
2020-02-13 20:20:00

Upvotes: 1

user40780
user40780

Reputation: 1920

def calculate_the_next_week_day(day_now):    
    if day_now.isoweekday()== 5:
        day_now += datetime.timedelta(days=3)
    elif day_now.isoweekday()== 6:
        day_now += datetime.timedelta(days=2)
    else:
        day_now += datetime.timedelta(days=1)
    return day_now

Upvotes: 3

jonrsharpe
jonrsharpe

Reputation: 122067

You should use actual date objects, not strings:

>>> import datetime
>>> today = datetime.date.today()
>>> if today.isoweekday() in set((6, 7)):
    today += datetime.timedelta(days=today.isoweekday() % 5)


>>> today
datetime.date(2014, 9, 30)

Note that isoweekday is 1 (Monday) to 7 (Sunday), whereas weekday is 0 to 6.


Also, note that your logic currently adds one day to Saturday and two days to Sunday, which isn't correct - I think you want:

>>> if today.isoweekday() in set((6, 7)):
    today += datetime.timedelta(days=8 - today.isoweekday())

For example:

>>> day = datetime.date(2014, 10, 4)
>>> day
datetime.date(2014, 10, 4) # Saturday
>>> if day.isoweekday() in set((6, 7)):
    day += datetime.timedelta(days=8 - day.isoweekday())


>>> day
datetime.date(2014, 10, 6) # Monday

Upvotes: 15

Related Questions