Il problema dell'anno 2038 (Y2K38) spiegato
Il 19 gennaio 2038 alle 03:14:07 UTC, il timestamp Unix 2.147.483.647 — il valore massimo di un intero con segno a 32 bit — andrà in overflow e salterà a una data del 1901. Ecco cosa significa, quali sistemi sono interessati, come funziona la correzione con time_t a 64 bit e come testare il tuo codice.
L'overflow in una riga
Un intero con segno a 32 bit arriva al massimo a 2.147.483.647. Memorizzato come secondi Unix, quel valore è il 19/01/2038 03:14:07 UTC — e un secondo dopo salta a -2.147.483.648, che si legge come 13 dicembre 1901. Qualsiasi sistema che tenga ancora il tempo in un intero con segno a 32 bit farà un balzo di 137 anni nel passato in quell'istante. La correzione sta in una parola: 64 bit. La tabella sotto mostra quali tipi di archiviazione sono interessati e quali sono già al sicuro.
| Tipo di archiviazione | Va in overflow a / data max | Sicuro dopo il 2038? |
|---|---|---|
| time_t con segno 32 bit / SQL INT | 2038-01-19 03:14:07 UTC | No |
| MySQL TIMESTAMP | 2038-01-19 03:14:07 UTC | No — usare DATETIME |
| 32 bit senza segno | 2106-02-07 06:28:15 UTC | Guadagna 68 anni, non una soluzione |
| time_t con segno 64 bit / SQL BIGINT | ~292 miliardi di anni | Sì |
| Float a 64 bit (JavaScript, Python) | anno 275.760 | Sì |
| MySQL DATETIME (campi compattati) | anno 9999 | Sì |
Che cos'è il problema dell'anno 2038?
I timestamp Unix sono tradizionalmente memorizzati in un intero con segno a 32 bit che conta i secondi dal 1° gennaio 1970 00:00:00 UTC. Il valore massimo di un intero con segno a 32 bit è 2.147.483.647 — che corrisponde al 19 gennaio 2038 alle 03:14:07 UTC. Un secondo dopo quel momento, l'intero va in overflow a -2.147.483.648. Interpretato come timestamp Unix, quel valore negativo corrisponde al 13 dicembre 1901 — spedendo i sistemi interessati quasi 137 anni nel passato.
- 2^31 − 1 = 2.147.483.647 (intero con segno a 32 bit massimo)
- 2.147.483.647 come data = 19 gennaio 2038 03:14:07 UTC
- 2.147.483.647 + 1 va in overflow a −2.147.483.648 (il valore a 32 bit più negativo)
- −2.147.483.648 come data = 13 dicembre 1901 20:45:52 UTC
- L'ora locale dell'overflow varia: 22:14:07 EST il 18 gennaio, 14:14:07 JST il 19 gennaio
Quali sistemi sono a rischio?
Il problema interessa i sistemi che memorizzano i timestamp come interi con segno a 32 bit:
- Sistemi embedded e microcontrollori con time_t a 32 bit
- Vecchio codice C e C++ compilato per target a 32 bit che usa time_t o int per i timestamp
- Vecchi kernel Linux (precedenti al 5.6) su hardware a 32 bit ancora in produzione
- Colonne MySQL TIMESTAMP — limitate al 2038-01-19; usare DATETIME al loro posto
- Alcuni protocolli di rete e formati di file che codificano i timestamp come valori a 32 bit
- Firmware in sistemi di controllo industriali e dispositivi IoT con vite di decenni
Quali sistemi sono sicuri?
La maggior parte del codice e dell'infrastruttura moderni non è già interessata:
- Qualsiasi SO a 64 bit — Linux (glibc 2.34+ corregge anche l'hardware a 32 bit), macOS, Windows
- Python — i timestamp usano float a 64 bit, sicuri ben oltre l'anno 292 milioni
- JavaScript — Date usa float IEEE 754 a 64 bit, sicuro fino all'anno 275.760
- Go e Rust — usano int64 per il tempo internamente, sicuri per miliardi di anni
- Java — java.time.Instant usa long (64 bit), sicuro fino all'anno ~292 milioni
- PostgreSQL TIMESTAMP — memorizza correttamente le date oltre il 2038
- MySQL DATETIME — intervallo 1000-01-01 a 9999-12-31, non interessato
MySQL TIMESTAMP e il tetto del 2038
MySQL ha due principali tipi di colonna data-ora che si comportano in modo molto diverso intorno al 2038:
- TIMESTAMP è memorizzato internamente come un intero Unix con segno a 32 bit — va in overflow il 2038-01-19 03:14:07 UTC
- DATETIME è memorizzato come campi A/M/G h/m/s compattati e supporta fino all'anno 9999 — usalo per qualsiasi data che possa essere successiva al 2038
- TIMESTAMP converte anche implicitamente da/verso il fuso di sessione del server; DATETIME memorizza il valore così com'è
- Per colonne epoch grezze, memorizza BIGINT anziché INT così che il valore stesso non possa andare in overflow
- Verifica gli schemi esistenti: SELECT TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS WHERE DATA_TYPE = "timestamp"
Linux embedded e time_t a 32 bit
Il maggior rischio Y2038 rimasto è nei sistemi embedded di lunga durata: router, controllori industriali, centraline automobilistiche, contatori intelligenti e dispositivi IoT spediti con kernel a 32 bit e che possono restare in servizio oltre il 2038. Sia la libreria C sia qualsiasi protocollo binario proprietario devono essere puliti a 64 bit.
- glibc ha ottenuto time_t a 64 bit per le ABI a 32 bit tramite la macro di build -D_TIME_BITS=64 (glibc 2.34+)
- musl libc è a time_t a 64 bit per impostazione predefinita dalla versione 1.2.0 (2020)
- Debian, Ubuntu e OpenWrt hanno migrato tutte le loro port a 32 bit a time_t a 64 bit
- I timestamp del filesystem sono una questione a parte: ext2/ext3 usano tempi a 32 bit; ext4 supporta i 64 bit sugli inode ≥ 256 byte
- Per l'hardware ancora spedito nel 2026+, conferma che sia la libreria C sia qualsiasi formato wire siano a 64 bit
Come correggere e testare per Y2038
La correzione è sempre la stessa — allargare il tempo a 64 bit — ma va applicata a ogni livello che memorizza o trasmette un timestamp: la libreria C, le colonne del database e qualsiasi protocollo binario o formato di file. Il modo più rapido per trovare un problema è spostare un orologio oltre il limite in un ambiente di test e sorvegliare le date che finiscono nel 1901.
- Compila il codice a 32 bit con -D_TIME_BITS=64 (e -D_FILE_OFFSET_BITS=64) su glibc 2.34+
- Usa BIGINT, non INT, per qualsiasi colonna che memorizzi secondi o millisecondi Unix grezzi
- Preferisci DATETIME o TIMESTAMPTZ a MySQL TIMESTAMP per date che possono superare il 2038
- Nei test, imposta l'orologio del sistema o del container a 2038-01-19T03:14:08Z e verifica che le date restino nel 2038
- Controlla i formati wire e gli header dei file — un SO a 64 bit non aiuta se il campo del protocollo è a 32 bit
Rollover correlati: Y2K, GPS, NTP e 2106
L'anno 2038 fa parte di una famiglia di rollover a larghezza fissa. Ciascuno deriva dall'impacchettare un orologio in troppi pochi bit, e conoscere le date aiuta a individuare il successivo prima che venga rilasciato:
| Rollover | Data | Causa |
|---|---|---|
| Y2K | 2000-01-01 | Memorizzazione dell'anno a due cifre |
| Rollover della settimana GPS | 2019-04-06 | Contatore di settimana GPS a 10 bit |
| Rollover dell'era NTP | 2036-02-07 | Secondi senza segno a 32 bit dal 1900 |
| Anno 2038 (Y2K38) | 2038-01-19 | Secondi con segno a 32 bit dal 1970 |
| Anno 2106 | 2106-02-07 | Secondi senza segno a 32 bit dal 1970 |
Riferimenti correlati
FAQ
- Che cos'è il problema dell'anno 2038?
- Il problema dell'anno 2038 (Y2K38) è un bug in cui i sistemi che memorizzano i timestamp Unix in interi con segno a 32 bit andranno in overflow il 19 gennaio 2038 alle 03:14:07 UTC. Il valore massimo di un intero con segno a 32 bit è 2.147.483.647. Un secondo dopo, l'intero salta a -2.147.483.648, che corrisponde al 13 dicembre 1901.
- Qual è il timestamp Unix del 19 gennaio 2038?
- Il timestamp Unix del 19 gennaio 2038 alle 03:14:07 UTC è 2.147.483.647 — il valore massimo di un intero con segno a 32 bit (2^31 - 1). È il momento esatto in cui si verifica l'overflow dell'anno 2038 sui sistemi a 32 bit.
- Come correggo il problema dell'anno 2038?
- Memorizza il tempo in un intero con segno a 64 bit invece che a 32 bit. Usa time_t a 64 bit (compila il codice a 32 bit con -D_TIME_BITS=64 su glibc 2.34+), BIGINT invece di INT per le colonne epoch, e DATETIME invece di MySQL TIMESTAMP. Un valore di tempo con segno a 64 bit non va in overflow per circa 292 miliardi di anni.
- Y2K38 è la stessa cosa di Y2K?
- No. Y2K (problema dell'anno 2000) derivava dai programmi che memorizzavano gli anni a due cifre. Y2K38 deriva dal memorizzare i timestamp Unix come interi con segno a 32 bit che vanno in overflow nel 2038. Cause diverse, sistemi interessati diversi.
- Che cos'è il problema dell'anno 2106?
- L'anno 2106 è lo stesso overflow per i timestamp senza segno a 32 bit, che si esauriscono il 7 febbraio 2106 alle 06:28:15 UTC. Passare da con segno a senza segno a 32 bit guadagna altri 68 anni, ma non è una vera soluzione; il tempo a 64 bit lo è.
- Internet crollerà nel 2038?
- Probabilmente non in modo significativo. La maggior parte dell'infrastruttura internet è già migrata a sistemi a 64 bit. Il rischio si concentra nei sistemi embedded, nei vecchi dispositivi IoT e nel software non aggiornato da decenni. I sistemi operativi, i linguaggi e i database moderni sono già al sicuro.