Year 2038 Problem

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 archiviazioneVa in overflow a / data maxSicuro dopo il 2038?
time_t con segno 32 bit / SQL INT2038-01-19 03:14:07 UTCNo
MySQL TIMESTAMP2038-01-19 03:14:07 UTCNo — usare DATETIME
32 bit senza segno2106-02-07 06:28:15 UTCGuadagna 68 anni, non una soluzione
time_t con segno 64 bit / SQL BIGINT~292 miliardi di anni
Float a 64 bit (JavaScript, Python)anno 275.760
MySQL DATETIME (campi compattati)anno 9999

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:

RolloverDataCausa
Y2K2000-01-01Memorizzazione dell'anno a due cifre
Rollover della settimana GPS2019-04-06Contatore di settimana GPS a 10 bit
Rollover dell'era NTP2036-02-07Secondi senza segno a 32 bit dal 1900
Anno 2038 (Y2K38)2038-01-19Secondi con segno a 32 bit dal 1970
Anno 21062106-02-07Secondi 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.