Introduzione
Quando si gestiscono date e orari in PHP, spesso il problema non è solo calcolare una data, ma farlo rispettando regole reali di business. Un caso molto comune è il calcolo dei giorni lavorativi: ad esempio, sapere quando scade un ordine dopo 5 giorni lavorativi, oppure programmare una consegna evitando weekend e festività.
Questo sotto-argomento è molto utile perché si incontra spesso in applicazioni gestionali, e-commerce, CRM e software per uffici. PHP offre ottimi strumenti per lavorare con le date, ma per gestire i giorni lavorativi bisogna aggiungere una logica personalizzata. In questo tutorial vedremo come costruire una soluzione chiara, riutilizzabile e abbastanza robusta da usare in un progetto reale.
Usheremo DateTimeImmutable per evitare modifiche accidentali agli oggetti data, e implementeremo una funzione che calcola una data futura aggiungendo un certo numero di giorni lavorativi, escludendo sabati, domeniche e un elenco di festività.
Codice completo
<?php
declare(strict_types=1);
/**
* Aggiunge un numero di giorni lavorativi a una data di partenza.
*
* - Esclude sabati e domeniche
* - Esclude una lista di festività passate come array di stringhe ´Y-m-d´
*
* @param DateTimeImmutable $startDate Data di partenza
* @param int $workingDays Numero di giorni lavorativi da aggiungere
* @param array $holidays Elenco festività in formato ´Y-m-d´
* @return DateTimeImmutable
*/
function addWorkingDays(DateTimeImmutable $startDate, int $workingDays, array $holidays = []): DateTimeImmutable
{
$date = $startDate;
$added = 0;
while ($added < $workingDays) {
$date = $date->modify(´+1 day´);
$dayOfWeek = (int) $date->format(´N´); // 1 = lunedì, 7 = domenica
$formattedDate = $date->format(´Y-m-d´);
$isWeekend = $dayOfWeek >= 6;
$isHoliday = in_array($formattedDate, $holidays, true);
if (!$isWeekend && !$isHoliday) {
$added++;
}
}
return $date;
}
/**
* Verifica se una data è un giorno lavorativo.
*
* @param DateTimeImmutable $date
* @param array $holidays
* @return bool
*/
function isWorkingDay(DateTimeImmutable $date, array $holidays = []): bool
{
$dayOfWeek = (int) $date->format(´N´);
$formattedDate = $date->format(´Y-m-d´);
return $dayOfWeek < 6 && !in_array($formattedDate, $holidays, true);
}
// --------------------
// ESEMPIO D´USO
// --------------------
$startDate = new DateTimeImmutable(´2026-12-22´);
$holidays = [
´2026-12-25´, // Natale
´2026-12-26´, // Santo Stefano
´2027-01-01´, // Capodanno
];
$deliveryDate = addWorkingDays($startDate, 5, $holidays);
echo "Data di partenza: " . $startDate->format(´d/m/Y´) . PHP_EOL;
echo "Data consegna: " . $deliveryDate->format(´d/m/Y´) . PHP_EOL;
// Controllo singola data
$checkDate = new DateTimeImmutable(´2026-12-25´);
if (isWorkingDay($checkDate, $holidays)) {
echo $checkDate->format(´d/m/Y´) . " è un giorno lavorativo" . PHP_EOL;
} else {
echo $checkDate->format(´d/m/Y´) . " non è un giorno lavorativo" . PHP_EOL;
} Spiegazione
La funzione addWorkingDays() parte da una data iniziale e avanza di un giorno alla volta finché non raggiunge il numero richiesto di giorni lavorativi. Ogni iterazione controlla due condizioni:
- se il giorno corrente è sabato o domenica;
- se la data corrisponde a una festività presente nell’array $holidays.
Il controllo del giorno della settimana avviene con format(´N´), che restituisce un numero da 1 a 7: lunedì vale 1, domenica vale 7. Questa scelta è comoda perché permette di identificare il weekend con una semplice condizione:
$isWeekend = $dayOfWeek >= 6; Le festività vengono gestite come stringhe nel formato Y-m-d. Questo formato è molto pratico perché è stabile, facile da confrontare e non dipende dalla rappresentazione locale della data.
L’uso di DateTimeImmutable è importante: ogni chiamata a modify() restituisce un nuovo oggetto, quindi la data originale non viene modificata. Questo riduce il rischio di bug, soprattutto quando la stessa data viene riutilizzata in più punti del codice.
La funzione isWorkingDay() è un piccolo aiuto aggiuntivo. Serve quando vuoi verificare rapidamente se una singola data è lavorativa oppure no. In un progetto reale, questa funzione può essere utile per validazioni, filtri o controlli su interfacce utente.
Vediamo un esempio concreto. Se la data di partenza è il 22 dicembre 2026 e aggiungiamo 5 giorni lavorativi, il risultato non sarà semplicemente il 27 dicembre. Il calcolo salterà il weekend e anche le festività indicate nell’array. Questo comportamento è molto più vicino alle esigenze di un sistema gestionale o di una logica di consegna reale.
Best practice
Quando lavori con giorni lavorativi in PHP, ci sono alcune buone pratiche da seguire per mantenere il codice affidabile e facile da mantenere.
- Usa DateTimeImmutable invece di DateTime quando vuoi evitare modifiche involontarie.
- Separare la logica di calcolo in funzioni dedicate rende il codice riutilizzabile e testabile.
- Conserva le festività in un formato uniforme, ad esempio
Y-m-d, per evitare confronti ambigui. - Non hardcodare le regole di business nel codice principale se possono cambiare spesso: meglio passare festività, calendario e configurazioni come parametri.
- Scrivi test automatici per verificare casi limite: fine mese, cambio anno, weekend consecutivi, festività vicine al sabato o alla domenica.
Un aspetto spesso sottovalutato è la gestione delle festività variabili. In alcuni contesti, infatti, i giorni non lavorativi non sono solo quelli nazionali, ma dipendono anche da regione, sede aziendale o calendario del cliente. Per questo motivo, conviene progettare la funzione in modo che l’elenco delle festività sia esterno e facilmente aggiornabile.
Se il progetto cresce, puoi anche evolvere questa soluzione in una classe dedicata, ad esempio WorkingDayCalculator, con metodi per:
- aggiungere giorni lavorativi;
- trovare il prossimo giorno lavorativo;
- verificare se una data è lavorativa;
- gestire calendari diversi per paese o reparto.
Infine, presta attenzione al fuso orario. Anche se in questo esempio lavoriamo solo con date senza orario, in applicazioni reali può essere importante inizializzare correttamente il timezone per evitare risultati inattesi quando si passa da una data a un timestamp o quando si integra il calcolo con sistemi esterni.
Riepilogo
In questo tutorial abbiamo visto come gestire i giorni lavorativi in PHP con un approccio pratico e riutilizzabile. Il punto chiave è che i calcoli sulle date non devono limitarsi a sommare giorni: nella realtà bisogna considerare weekend e festività.
- DateTimeImmutable è ideale per calcoli sicuri e prevedibili.
- Con format(´N´) puoi riconoscere facilmente sabato e domenica.
- Un array di festività in formato Y-m-d rende i confronti semplici e affidabili.
- Separare la logica in funzioni dedicate migliora manutenzione e testabilità.
Questa tecnica è molto utile in sistemi di prenotazione, gestione ordini, assistenza clienti e qualunque applicazione che debba ragionare su scadenze “reali” e non solo su giorni consecutivi.
