Convertire le date dal formato Excel a un formato standard con PHP

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.

Torna su