Quando si importano dati da un file Excel in PHP, può capitare che le date vengano rappresentate come numeri seriali. Questi numeri indicano il numero di giorni trascorsi dal 1° gennaio 1900. Per convertirli in un formato leggibile (come YYYY-MM-DD
), è necessario effettuare una conversione esplicita.
Come Funziona il Formato Data di Excel
Excel memorizza le date come numeri interi a partire dal 1° gennaio 1900, che ha il valore 1
. Ad esempio, il numero 44927
corrisponde al 1° gennaio 2023. Va notato che Excel considera erroneamente il 1900 come anno bisestile, includendo il 29 febbraio 1900 (che in realtà non esiste), quindi bisogna tenere conto di questo errore nel calcolo.
Codice PHP per la Conversione
Qui sotto un semplice esempio per convertire un numero seriale Excel in una data nel formato standard:
function excelDateToDateTime($excelDate, $format = 'Y-m-d') {
// Excel considera il 1900 come anno bisestile, quindi si parte da 1899-12-30
$baseDate = DateTime::createFromFormat('Y-m-d', '1899-12-30');
if (!$baseDate) {
throw new Exception('Errore nella creazione della data base');
}
// Aggiunge i giorni all'origine
$interval = new DateInterval("P{$excelDate}D");
$baseDate->add($interval);
return $baseDate->format($format);
}
// Esempio di utilizzo
$excelSerial = 44927;
echo excelDateToDateTime($excelSerial); // Output: 2023-01-01
Considerazioni
- La funzione sopra restituisce la data in formato
Y-m-d
, ma può essere personalizzata. - Se il valore seriale è decimale (ad esempio, include ore e minuti), bisogna usare un approccio diverso con i secondi o frazioni di giorno.
- Per valori provenienti da LibreOffice o Google Sheets, il comportamento è identico nella maggior parte dei casi.
Gestione delle Date e Orari
Se si vuole ottenere anche l'orario (quando il seriale Excel include una parte decimale), si può usare questo metodo:
function excelDateTimeToDateTime($excelDate, $format = 'Y-m-d H:i:s') {
$days = (int)$excelDate;
$fraction = $excelDate - $days;
$baseDate = DateTime::createFromFormat('Y-m-d H:i:s', '1899-12-30 00:00:00');
if (!$baseDate) {
throw new Exception('Errore nella creazione della data base');
}
$secondsInDay = 86400;
$interval = new DateInterval("P{$days}D");
$baseDate->add($interval);
$baseDate->modify("+".round($fraction * $secondsInDay)." seconds");
return $baseDate->format($format);
}
// Esempio con ora
$excelSerial = 44927.5; // 2023-01-01 12:00:00
echo excelDateTimeToDateTime($excelSerial);
Con questa funzione puoi gestire anche le date e ore esatte, utile per timestamp dettagliati.