Calcolatore fusi orari
Il calcolatore fusi orari converte una data e un’ora locale tra due zone mantenendo lo stesso istante assoluto.
Una conversione affidabile non consiste nel sommare un numero fisso di ore. Infatti, offset, ora legale, modifiche legislative e transizioni storiche dipendono sia dalla zona sia dalla data scelta. Per questo motivo, il calcolatore deve utilizzare identificatori IANA e dati tz aggiornati.
Date e Intl.DateTimeFormat, la disponibilità non ancora universale di Temporal e le scelte necessarie nei periodi DST ambigui o inesistenti.
Che cos’è il calcolatore fusi orari
Il calcolatore fusi orari dovrebbe accettare data, ora locale, zona IANA di origine, zona di destinazione e una scelta esplicita per gap e overlap DST.
Successivamente può mostrare:
- orario locale di origine;
- offset dell’origine in quell’istante;
- timestamp UTC;
- orario locale di destinazione;
- offset della destinazione;
- differenza tra i due orologi;
- avvisi per valori ambigui o inesistenti.
UTC, offset e fuso orario
| Concetto | Significato |
|---|---|
| UTC | Scala temporale di riferimento usata come base per gli istanti |
| Offset | Differenza locale rispetto a UTC in uno specifico momento |
| Fuso IANA | Insieme di regole geografiche e storiche, per esempio Europe/Rome |
| Wall time | Data e ora mostrate dall’orologio locale, senza univocità garantita |
| Instant | Un singolo punto nella linea temporale, indipendente dal fuso |
Perché UTC+02:00 non equivale a Europe/Rome
L’offset UTC+02:00 descrive una differenza numerica.
Invece, Europe/Rome descrive regole che possono produrre UTC+01:00 oppure UTC+02:00 secondo la data.
Database IANA tz
Il Time Zone Database di IANA contiene dati e codice relativi alla storia del tempo locale in molte località rappresentative.
Viene aggiornato quando autorità politiche cambiano confini, offset o regole dell’ora legale. Alla data di aggiornamento di questa pagina, la versione più recente è 2026b, pubblicata nell’aprile 2026.
Identificatori IANA
Europe/Rome Europe/London America/New_York Asia/Kolkata Asia/Kathmandu Australia/Adelaide
Il sito può mostrare nomi leggibili, ma dovrebbe salvare l’identificatore effettivamente supportato dalla piattaforma.
Alias e nomi principali
Nel database possono esistere alias storici che indicano la stessa zona.
Perciò, il software non dovrebbe presumere che IANA, CLDR, browser e sistemi operativi restituiscano sempre la stessa stringa. È utile normalizzare gli input, conservando il valore originale quando serve audit.
Abbreviazioni ambigue
Sigle come CST, IST o BST non identificano sempre una sola zona.
Inoltre, la stessa abbreviazione può avere significati differenti in paesi diversi. Il calcolatore fusi orari dovrebbe usare il nome IANA e mostrare la sigla soltanto come informazione secondaria.
Procedura corretta di conversione
- Acquisire il wall time locale.
- Associare la zona IANA di origine.
- Controllare quante corrispondenze temporali esistono.
- Risolvere un singolo istante UTC.
- Formattare lo stesso istante nella zona di destinazione.
- Mostrare offset, differenza e avvisi.
Formule concettuali
Istante UTC = tempo locale origine − offset origine a quell’istante
Tempo locale destinazione = istante UTC + offset destinazione a quell’istante
Tuttavia, l’offset di origine non può essere scelto correttamente con una tabella fissa quando il wall time cade vicino a una transizione.
Un wall time non è sempre un istante
La stringa 2025-11-02 01:30 non identifica necessariamente un solo momento.
Serve anche una zona e, durante un overlap, una scelta tra due offset validi.
Orario ambiguo: overlap
Quando gli orologi vengono spostati indietro, una parte della timeline locale si ripete.
Di conseguenza, una stessa ora può corrispondere a due istanti UTC differenti.
Esempio ambiguo a New York
Wall time: 2025-11-02 01:30 America/New_York Prima occorrenza: 01:30 EDT, UTC−04:00 = 2025-11-02 05:30 UTC Seconda occorrenza: 01:30 EST, UTC−05:00 = 2025-11-02 06:30 UTC
Orario inesistente: gap
Quando gli orologi avanzano, una fascia di wall time viene saltata.
Per esempio, 2025-03-09 02:30 America/New_York non si verifica nel calendario locale di quella transizione.
Politica consigliata per i gap
Per un’interfaccia di pianificazione, l’opzione più trasparente è rifiutare il valore e chiedere una nuova scelta.
Alcune API spostano automaticamente l’orario oltre il gap. Tuttavia, farlo senza messaggio può programmare un evento in un momento diverso da quello immaginato.
Disambiguazione con Temporal
Temporal supporta compatible, earlier, later e reject.
In un overlap, earlier sceglie la prima occorrenza e later la seconda. Con reject, un valore ambiguo o inesistente genera un errore.
Esempio JavaScript con Temporal
const origine = Temporal.ZonedDateTime.from(
{
timeZone: "America/New_York",
year: 2025,
month: 11,
day: 2,
hour: 1,
minute: 30
},
{ disambiguation: "reject" }
);
const roma = origine.withTimeZone("Europe/Rome");
Disponibilità di Temporal
Temporal.ZonedDateTime non è ancora classificato da MDN come Baseline ampiamente disponibile.
Perciò, un’applicazione production deve eseguire feature detection, fornire un polyfill oppure delegare la risoluzione a un backend affidabile.
Che cosa fa Intl.DateTimeFormat
Intl.DateTimeFormat formatta un istante in base a lingua, stile e zona selezionata.
È adatto quando l’applicazione possiede già un timestamp UTC univoco.
Che cosa non fa Intl.DateTimeFormat
Intl.DateTimeFormat non è un parser completo di wall time zoned.
Inoltre, non offre da solo una scelta tra due occorrenze durante un overlap. L’articolo originale attribuiva quindi a Intl una responsabilità troppo ampia.
Esempio di sola formattazione con Intl
const instant = new Date("2025-07-10T08:00:00Z");
const formatter = new Intl.DateTimeFormat("it-IT", {
timeZone: "America/New_York",
dateStyle: "full",
timeStyle: "long"
});
console.log(formatter.format(instant));
Problemi di JavaScript Date
Date rappresenta un istante, ma le stringhe senza offset possono essere interpretate nella zona locale del dispositivo.
Di conseguenza, new Date("2025-07-10T09:00") può produrre un istante diverso su computer configurati in zone differenti.
Input datetime-local
Un controllo HTML datetime-local contiene data e ora, ma non contiene la zona.
Perciò, il form deve aggiungere un selettore separato per l’identificatore IANA.
Rilevare la zona del browser
const zone =
Intl.DateTimeFormat()
.resolvedOptions()
.timeZone;
Il valore è un buon default, ma l’utente deve poterlo modificare.
Esempio Londra → New York
Europe/London: 2025-07-10 09:00 offset UTC+01:00 Istante: 2025-07-10 08:00 UTC America/New_York: 2025-07-10 04:00 offset UTC−04:00
La differenza tra gli orologi è di cinque ore in quella data.
La differenza tra città può cambiare
Londra e New York non cambiano sempre l’ora legale nello stesso giorno.
Durante alcune settimane, la differenza può essere di quattro ore invece di cinque. Il sito non deve salvare una differenza fissa tra le città.
Esempio con offset di mezz’ora
Il 15 luglio 2025 alle 10:00 a New Delhi:
Asia/Kolkata: 10:00, UTC+05:30 Istante UTC: 04:30 Australia/Adelaide: 14:00, UTC+09:30
Correzione dell’esempio Adelaide
L’articolo originale associava 14:00 a Adelaide durante DST.
Tuttavia, con offset estivo UTC+10:30, le 04:30 UTC corrispondono alle 15:00. Le 14:00 corrispondono all’offset standard UTC+09:30.
Esempio Adelaide durante DST
Data: 2025-01-15 New Delhi: 10:00, UTC+05:30 UTC: 04:30 Adelaide: 15:00, UTC+10:30
Offset di 45 minuti
Non tutti gli offset sono multipli di 30 minuti.
Per esempio, Asia/Kathmandu usa UTC+05:45. Il calcolatore deve lavorare in minuti o secondi, non in ore intere.
Cambio di data
Una conversione può cambiare anche il giorno.
Perciò, il risultato deve mostrare data completa, giorno della settimana e indicatore “giorno precedente” o “giorno successivo”.
Formato ISO con UTC
2025-07-10T08:00:00Z
La lettera Z indica offset zero rispetto a UTC.
Timestamp con offset
2025-07-10T10:00:00+02:00
Il timestamp contiene un offset, ma non conserva automaticamente le regole di Europe/Rome.
Timestamp esteso con zona
RFC 9557 definisce un’estensione di RFC 3339 che può allegare informazioni aggiuntive:
2025-07-10T10:00:00+02:00[Europe/Rome]
Prima di usare questo formato, verifica che tutti i componenti del sistema lo supportino.
Che cosa salvare per un appuntamento singolo
- istante UTC;
- zona IANA originale;
- wall time inserito;
- offset scelto durante un overlap;
- versione tzdata, quando serve riproducibilità.
Che cosa salvare per un evento ricorrente
Per “ogni lunedì alle 09:00 a Roma”, salvare soltanto un UTC fisso è insufficiente.
- regola di ricorrenza;
- ora locale;
- zona
Europe/Rome; - politica per gap e overlap;
- eccezioni del calendario.
Ricorrenza locale e durata assoluta
“Ogni giorno alle 09:00” è una regola di calendario locale.
Invece, “ogni 24 ore” è una durata assoluta. Nei giorni di cambio DST, le due interpretazioni possono produrre orari locali differenti.
Viaggi e itinerari
Partenza e arrivo devono essere interpretati nella zona dell’aeroporto indicato.
Inoltre, la durata del viaggio si calcola tra istanti, non sottraendo direttamente due orari locali.
Log e sistemi distribuiti
Per ordinamento tecnico, usa timestamp UTC o epoch.
Tuttavia, conserva zona e contesto quando servono interpretazione umana, ricorrenza o ricostruzione dell’input originale.
Client e server
| Approccio | Vantaggio | Limite |
|---|---|---|
| Client con Intl | Formattazione immediata | Tzdata dipende dalla piattaforma |
| Client con Temporal/polyfill | Disambiguazione esplicita | Supporto nativo non universale |
| Server con zoneinfo/java.time | Versione tzdata controllabile | Richiede aggiornamenti regolari |
| API esterna | Gestione centralizzata | Dipendenza, privacy e costo |
Python zoneinfo
Da Python 3.9, zoneinfo fornisce supporto IANA nella libreria standard.
Usa i dati del sistema oppure il pacchetto first-party tzdata quando disponibile.
Ambiguità in Python
dt_prima = datetime(
2025, 11, 2, 1, 30,
tzinfo=ZoneInfo("America/New_York"),
fold=0
)
dt_seconda = dt_prima.replace(fold=1)
L’attributo fold distingue le due occorrenze dell’ora ripetuta.
Attenzione ai gap in Python
Assegnare direttamente ZoneInfo a un datetime non garantisce che il wall time esista.
Un’applicazione deve validare il round-trip oppure usare una procedura che rilevi esplicitamente i gap.
Java ZonedDateTime
java.time.ZonedDateTime gestisce zone, gap e overlap.
Nei gap alcune costruzioni spostano il wall time in avanti; perciò, una UI deve rendere visibile questa politica.
Caching sicuro
È utile riutilizzare formatter e liste di zone.
Tuttavia, non memorizzare un solo offset per Europe/Rome. Una cache di offset deve includere zona, istante o intervallo e versione tzdata.
Aggiornamento della tzdata
- monitorare le release IANA;
- aggiornare runtime e container;
- eseguire test di regressione;
- registrare la versione usata;
- ricalcolare eventi futuri quando una legge cambia.
Testing delle transizioni
- istante prima della transizione;
- primo istante dopo;
- wall time nel gap;
- entrambe le occorrenze dell’overlap;
- data senza DST;
- data futura dopo un aggiornamento normativo.
Testing degli offset frazionari
Asia/Kolkatacon 30 minuti;Australia/Adelaidecon 30 minuti e DST;Asia/Kathmanducon 45 minuti;- una zona che cambia data rispetto all’origine.
Leap second
Un normale calcolatore web non dovrebbe fingere di supportare 23:59:60 se runtime e modello temporale non lo rappresentano.
Inoltre, l’applicazione deve documentare il modello temporale usato.
Formattazione localizzata
- ordine giorno-mese-anno;
- formato 12 o 24 ore;
- nomi tradotti di giorni e mesi;
- zona IANA;
- offset esplicito;
- indicatore del cambio di data.
Accessibilità
- associa ogni input a un’etichetta;
- permetti navigazione da tastiera;
- annuncia errori DST con una live region;
- non comunicare il cambio di giorno soltanto tramite colore;
- offri una copia testuale completa del risultato.
Privacy
Una conversione isolata può essere eseguita interamente nel browser.
Tuttavia, calendari, partecipanti, itinerari e luoghi possono essere dati personali. Se vengono inviati a un server, il sito deve spiegare finalità e conservazione.
Validazione degli input
Un buon calcolatore fusi orari dovrebbe verificare:
- data e ora valide;
- zona IANA supportata;
- presenza di zero, una o due corrispondenze;
- scelta esplicita durante overlap;
- rifiuto o politica documentata durante gap;
- assenza di parsing dipendente dal dispositivo.
Messaggi di errore utili
- “Seleziona un fuso IANA, non soltanto un offset”.
- “Questa ora locale si verifica due volte”.
- “Questa ora locale non esiste a causa del cambio dell’ora”.
- “Scegli la prima o la seconda occorrenza”.
- “Il campo datetime-local non contiene una zona”.
Errori frequenti
- aggiungere manualmente ore fisse;
- salvare soltanto l’offset;
- affidarsi a abbreviazioni ambigue;
- usare
Date.parsesu stringhe senza offset; - attribuire a
Intlla risoluzione del wall time; - correggere un gap senza avviso;
- scegliere un overlap in silenzio;
- ignorare offset di 30 o 45 minuti;
- salvare ricorrenze come intervalli fissi di 24 ore;
- mettere in cache un offset senza data.
Procedura consigliata
- Acquisisci wall time e zona separatamente.
- Valida l’identificatore IANA.
- Rileva gap e overlap.
- Chiedi una scelta quando esistono due istanti.
- Rifiuta o documenta lo spostamento dei gap.
- Converti in un singolo instant.
- Formatta l’instant nella destinazione.
- Mostra UTC, offset e differenza.
- Conserva zona e regola per le ricorrenze.
- Mantieni tzdata aggiornata.
Come usare il calcolatore fusi orari
Nel calcolatore fusi orari, inserisci data e ora locali, quindi seleziona zona di origine e destinazione.
Successivamente, controlla eventuali avvisi DST e scegli l’occorrenza corretta. Infine, verifica timestamp UTC, offset, data locale di destinazione e indicatore del giorno precedente o successivo.
Domande frequenti
Come si converte correttamente un orario tra due città?
Inserisci data e ora locali, seleziona il fuso di origine con un identificatore IANA e risolvi quel wall time in un istante UTC. Successivamente formatta lo stesso istante nel fuso di destinazione.
Perché un offset UTC non sostituisce un fuso orario?
Un offset come UTC+01:00 descrive soltanto una differenza in un momento specifico. Un identificatore IANA, come Europe/Rome, contiene anche regole storiche e future su ora legale e cambi normativi.
Che cosa significa orario ambiguo durante il cambio dell’ora?
Quando gli orologi tornano indietro, una stessa ora locale può verificarsi due volte con offset differenti. Il calcolatore deve mostrare entrambe le possibilità oppure chiedere quale occorrenza usare.
Che cosa succede a un orario locale inesistente?
Quando gli orologi avanzano, alcune ore locali vengono saltate. Un’applicazione affidabile deve rifiutare il valore o spiegare chiaramente come lo sposta; non dovrebbe correggerlo in silenzio.
Intl.DateTimeFormat è sufficiente per costruire il calcolatore?
È adatto a formattare un istante in un fuso specifico, ma non risolve da solo un wall time locale ambiguo o inesistente. Per questa parte servono Temporal, una libreria affidabile o logica server-side.
Come si devono salvare gli eventi ricorrenti?
Per un evento che deve restare alle 09:00 locali, salva regola di ricorrenza, ora locale e identificatore IANA. Salvare soltanto un UTC fisso può spostare l’evento locale dopo un cambio DST.
Fonti autorevoli
- IANA: Time Zone Database
- TC39: specifica Temporal
- TC39: time zone e disambiguazione
- MDN: Intl.DateTimeFormat
- MDN: Temporal.ZonedDateTime
- MDN: input datetime-local
- Python: zoneinfo e fold
- Oracle Java: ZonedDateTime
- RFC 3339
- RFC 9557
Contenuto aggiornato il 25 giugno 2026. Le regole dei fusi orari possono cambiare; per applicazioni critiche verifica la versione tzdata e le fonti ufficiali della località.