Ho bisogno di trovare tre giorni lavorativi precedenti da una determinata data, omettendo i fine settimana e le vacanze. Questo non è un compito difficile in sé, ma sembra che il modo in cui lo avrei fatto sarebbe stato eccessivamente complicato, quindi ho pensato di chiedere prima la tua opinione.Trova tre giorni lavorativi precedenti da una determinata data
Per rendere le cose più interessanti, facciamo di questo un concorso. Offro 300 come una taglia a chi esce con la soluzione più pulita più breve che aderisce a questa specifica:
- scrivere una funzione che restituisce tre giorni lavorativi precedenti da una certa data
- giorno di lavoro è definito come ogni giorno che non sia sabato o la domenica e non è una vacanza
- la funzione conosce le vacanze per l'anno della data indicata e può tenerne conto
- la funzione accetta un parametro, la data, in
Y-m-d
format - La funzione restituisce un array con tre date nel formato
Y-m-d
, ordinato dal più vecchio al più recente.
Extra:
- La funzione può trovare anche le prossimi tre giorni lavorativi in aggiunta alle precedenti tre
Un esempio di matrice vacanze:
$holidays = array(
'2010-01-01',
'2010-01-06',
'2010-04-02',
'2010-04-04',
'2010-04-05',
'2010-05-01',
'2010-05-13',
'2010-05-23',
'2010-06-26',
'2010-11-06',
'2010-12-06',
'2010-12-25',
'2010-12-26'
);
Si noti che nello scenario reale, le festività non sono hardcode d ma provengono dalla funzione get_holidays($year)
. Puoi includerlo/usarlo nella tua risposta, se lo desideri.
Dato che sto offrendo una taglia, ciò significa che ci saranno almeno tre giorni prima che io possa contrassegnare una risposta come accettata (2 giorni per aggiungere una taglia, 1 giorno fino a quando non posso accettare).
Nota
Se si utilizza una lunghezza giorno fissato come 86400 secondi per passare da un giorno all'altro, si incorrerà in problemi con l'ora legale. Utilizzare invece strtotime('-1 day', $timestamp)
.
Un esempio di questo problema:
soluzione finale
Ecco la soluzione finale ho finito per usare, tratto da un'idea di Keith Minkler di utilizzare 's last weekday
.Rileva la direzione dal conteggio passato, se negativo, ricerca all'indietro, e indietro sul positivo:
function working_days($date, $count) {
$working_days = array();
$direction = $count < 0 ? 'last' : 'next';
$holidays = get_holidays(date("Y", strtotime($date)));
while(count($working_days) < abs($count)) {
$date = date("Y-m-d", strtotime("$direction weekday", strtotime($date)));
if(!in_array($date, $holidays)) {
$working_days[] = $date;
}
}
sort($working_days);
return $working_days;
}
Alcune delle risposte hanno una funzione per ottenere le feste per anno - ma ottengono l'anno dall'ingresso - per quegli anni in cui 1 gennaio è un Sabato, il Venerdì prima è una vacanza nel USA Ma il tavolo della fed per il 2011 conta il 31 dicembre 2010 come una vacanza '2011', quindi si tratta in parte di generare correttamente le tabelle in anticipo: http://www.opm.gov/operating_status_schedules/fedhol/2011.asp – Joe
Punto valido Joe. Idealmente le "get_holidays" dovrebbero accettare una data come argomento. In questo modo è possibile restituire tutte le festività 1 settimana su entrambi i lati di tale data (anche se la settimana si verifica oltre l'anno). – Wireblue