102 votes

Jour ouvré précédent le plus récent en Python

Je dois soustraire des jours ouvrés de la date actuelle.

J'ai actuellement du code qui doit toujours être en cours d'exécution le jour ouvré le plus récent. Ainsi, ce peut être aujourd'hui si nous sommes du lundi au vendredi, mais si c'est samedi ou dimanche alors je dois le ramener au vendredi précédent le week-end. J'ai actuellement un code assez lourd pour faire cela :

 lastBusDay = datetime.datetime.today()
 if datetime.date.weekday(lastBusDay) == 5:      #si c'est samedi
     lastBusDay = lastBusDay - datetime.timedelta(days = 1) #alors faire de vendredi
 elif datetime.date.weekday(lastBusDay) == 6:      #si c'est dimanche
     lastBusDay = lastBusDay - datetime.timedelta(days = 2); #alors faire de vendredi

Est-ce qu'il y a une meilleure façon?

Puis-je dire à timedelta de travailler en jours ouvrés plutôt qu'en jours calendaires par exemple?

9voto

ZdPo Ster Points 158

Si quelqu'un cherche une solution respectant les jours fériés (sans utiliser de bibliothèque énorme comme pandas), essayez cette fonction :

import holidays
import datetime

def previous_working_day(check_day_, holidays=holidays.US()):
    offset = max(1, (check_day_.weekday() + 6) % 7 - 3)
    most_recent = check_day_ - datetime.timedelta(offset)
    if most_recent not in holidays:
        return most_recent
    else:
        return previous_working_day(most_recent, holidays)

check_day = datetime.date(2020, 12, 28)
previous_working_day(check_day)

qui produit :

datetime.date(2020, 12, 24)

7voto

Maxim Mamaev Points 96

timeboard package fait cela.

Suppose your date is 04 Sep 2017. In spite of being a Monday, it was a holiday in the US (the Labor Day). So, the most recent business day was Friday, Sep 1.

>>> import timeboard.calendars.US as US
>>> clnd = US.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 1)

In UK, 04 Sep 2017 was the regular business day, so the most recent business day was itself.

>>> import timeboard.calendars.UK as UK
>>> clnd = UK.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 4)

DISCLAIMER: I am the author of timeboard.

4voto

yco Points 189

Pour le cas d'utilisation des pandas, j'ai trouvé ce qui suit assez utile et compact, bien que pas complètement lisible :

Obtenir le jour ouvré précédent le plus récent :

In [2]: datetime.datetime(2019, 11, 30) + BDay(1) - BDay(1)  # Samedi
Out[2]: Timestamp('2019-11-29 00:00:00')

In [3]: datetime.datetime(2019, 11, 29) + BDay(1) - BDay(1)  # Vendredi
Out[3]: Timestamp('2019-11-29 00:00:00')

Dans l'autre sens, il suffit d'utiliser :

In [4]: datetime.datetime(2019, 11, 30) + BDay(0)  # Samedi
Out[4]: Timestamp('2019-12-02 00:00:00')

In [5]: datetime.datetime(2019, 11, 29) + BDay(0)  # Vendredi
Out[5]: Timestamp('2019-11-29 00:00:00')

2voto

mastier Points 814

Cela donnera un générateur de jours ouvrés, bien sûr sans jours fériés, stop est un objet datetime.datetime. Si vous avez besoin de jours fériés, ajoutez simplement un argument supplémentaire avec une liste de jours fériés et vérifiez avec 'IFologie' ;-)

def workingdays(stop, start=datetime.date.today()):
    while start != stop:
        if start.weekday() < 5:
            yield start
        start += datetime.timedelta(1)

Plus tard, vous pourrez les compter comme suit

workdays = workingdays(datetime.datetime(2015, 8, 8))
len(list(workdays))

1voto

ValentinS Points 1

Pourquoi ne pas essayer quelque chose comme :

lastBusDay = datetime.datetime.today()
if datetime.date.weekday(lastBusDay) not in range(0,5):
    lastBusDay = 5

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X