2010-02-08 84 views
47

Devo sottrarre giorni lavorativi dalla data corrente.Giorni lavorativi in ​​Python

Attualmente ho del codice che deve essere sempre in esecuzione il giorno lavorativo più recente. Quindi potrebbe essere oggi se siamo da lunedì a venerdì, ma se è sabato o domenica, allora devo riportarlo al venerdì prima del fine settimana. Al momento ho alcuni piuttosto codice goffo per fare questo:

lastBusDay = datetime.datetime.today() 
if datetime.date.weekday(lastBusDay) == 5:  #if it's Saturday 
    lastBusDay = lastBusDay - datetime.timedelta(days = 1) #then make it Friday 
elif datetime.date.weekday(lastBusDay) == 6:  #if it's Sunday 
    lastBusDay = lastBusDay - datetime.timedelta(days = 2); #then make it Friday 

C'è un modo migliore?

Posso timedelta dico di lavorare in giorni feriali, piuttosto che giorni di calendario, ad esempio?

+5

Che dire di vacanze? – SLaks

+0

sì, mi sto già occupando di questi: il mio database riempie sempre le festività purché cadano nei giorni feriali. Ma sono d'accordo, anche le vacanze in generale sono un problema. Intendo dire che potrei iniziare a fare i capricci e usare gli sckits.timeseries, ma in realtà voglio qualcosa di più semplice. –

+0

Ecco uno snippet di dzzone che potrebbe aiutarti: http://snippets.dzone.com/posts/show/9173 –

risposta

76

Utilizzare i panda!

import pandas as pd 
# BDay is business day, not birthday... 
from pandas.tseries.offsets import BDay 

# pd.datetime is an alias for datetime.datetime 
today = pd.datetime.today() 
print today - BDay(4) 

Visto che oggi è Giovedi, Sept 26 che vi darà una potenza di:

datetime.datetime(2013, 9, 20, 14, 8, 4, 89761) 
+2

Bello. questa è la risposta giusta, oggi. Quando ho chiesto alla Q, i panda erano ancora un po 'incompleti. –

+3

La versione panda più recente (0.14.0) supporta anche i calendari delle festività – fantabolous

12

Sembra che ci siano diverse opzioni se si è aperti all'installazione di librerie aggiuntive.

Questo post descrive un modo di definire i giorni lavorativi con dateutil.

http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-09/3758.html

BusinessHours consente di custom-definire la lista di vacanze, ecc, per definire quando le ore di lavoro (e per estensione giorni lavorativi) sono.

http://pypi.python.org/pypi/BusinessHours/

+0

nice one Alison. Ancora non molto semplice anche se sfortunatamente. Comunque vado per la tua strada. Grazie per l'aiuto. –

+1

È improbabile che la definizione dei giorni lavorativi in ​​tutte le culture sia un problema abbastanza semplice da essere inclusa nella libreria standard. –

+2

Un punto valido, come del resto la mia domanda è per i mercati finanziari, e l'Egitto e Israele sono aperti la domenica. –

6

Forse questo codice potrebbe aiutare:

lastBusDay = datetime.datetime.today() 
shift = datetime.timedelta(max(1,(lastBusDay.weekday() + 6) % 7 - 3)) 
lastBusDay = lastBusDay - shift 

L'idea è che il lunedì yo deve andare indietro di 3 giorni, la domenica 2, e 1 in qualsiasi altro giorno.

La dichiarazione (lastBusDay.weekday() + 6) % 7 appena ri-basi il lunedì da 0 a 6.

davvero non so se questo sarà meglio in termini di prestazioni.

0

Perché non provare qualcosa di simile:

lastBusDay = datetime.datetime.today() 
if datetime.date.weekday(lastBusDay) not in range(0,5): 
    lastBusDay = 5 
0
def getNthBusinessDay(startDate, businessDaysInBetween): 
    currentDate = startDate 
    daysToAdd = businessDaysInBetween 
    while daysToAdd > 0: 
     currentDate += relativedelta(days=1) 
     day = currentDate.weekday() 
     if day < 5: 
      daysToAdd -= 1 

    return currentDate 
9

DISCLAMER: Sono l'autore ...

I ha scritto un pacchetto che fa esattamente questo, calcoli di date aziendali. Puoi utilizzare le specifiche della settimana e le festività personalizzate.

Ho avuto questo problema esatto mentre si lavora con i dati finanziari e non ha trovato alcuna delle soluzioni disponibili particolarmente facile, così ho scritto uno.

Spero che questo è utile per altre persone.

https://pypi.python.org/pypi/business_calendar/

+1

grazie mille, la tua libreria ha funzionato perfettamente per me. Forse dovresti aggiungere alla tua documentazione che la tua biblioteca supporta i giorni negativi se vuoi sottrarre giorni e che è su pip – guinunez

+0

Hey, so che questo potrebbe non essere il modo migliore per raggiungerti ma volevo solo segnalare un problema Stavo avendo con il tuo modulo business_calendar. Ho impostato un calendario con le festività federali statunitensi: ['2015-01-01', '2015-01-19', '2015-02-16', '2015-05-25', '2015-07- 03 ',' 2015-09-07 ', ' 2015-10-12 ',' 2015-11-11 ', ' 2015-11-26 ',' 2015-12-25 '], quindi provato a calcolare il differenza tra datetime (2015, 1, 16, 15, 28, 40) e datetime (2015, 1, 23, 11, 58, 0) ma restituisce costantemente -1. Staccare h/m/s dai risultati di data/data (correttamente) in 4. –

+1

In realtà, dopo ulteriori test, alcuni confronti di date bloccano, senza una ragione apparente, senza mai dare l'impressione di restituire un risultato. Nel mio esempio precedente il tentativo di confrontare datetime (2015, 1, 16) con datetime (2015, 1, 25) porta a un blocco di questo tipo, con o senza impostare esplicitamente eventuali festività. All'indagine ciò si verifica quando il parametro date2 è una data che non è un giorno lavorativo. Il numero di bus –

2

Questo darà un generatore di giorni lavorativi, ovviamente senza vacanze, fermata è datetime.datetime oggetto. Se avete bisogno di vacanze solo fare ulteriore argomento con la lista delle feste e controllare con 'IFology' ;-)

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

In seguito si possono contare come

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