RFC 3339 - Date and Time on the Internet: Timestamps (Data e ora su Internet: timestamp)
- Stato: Proposed Standard
- Pubblicato: July 2002
- Stream: IETF
- Errata: Nessun errata
Status of this Memo (Stato di questo memorandum)
Questo documento specifica un protocollo di tracciamento standard Internet per la comunità Internet e richiede discussioni e suggerimenti per il miglioramento. Per lo stato di standardizzazione di questo protocollo, fare riferimento alla versione corrente degli "Internet Official Protocol Standards" (STD 1). La distribuzione di questo memorandum non è limitata.
Copyright Notice (Avviso sul copyright)
Copyright (C) The Internet Society (2002). All Rights Reserved.
Abstract (Riassunto)
Questo documento definisce un formato di data e ora da utilizzare nei protocolli Internet, che rappresenta un profilo (Profile) dello standard ISO 8601 per la rappresentazione di date e ore utilizzando il calendario gregoriano (Gregorian Calendar).
Indice
- 1. Introduction (Introduzione)
- 2. Definitions (Definizioni)
- 3. Two Digit Years (Anni a due cifre)
- 4. Local Time (Ora locale)
- 4.1 Coordinated Universal Time (UTC)
- 4.2 Local Offsets
- 4.3 Unknown Local Offset Convention
- 4.4 Unqualified Local Time
- 5. Date and Time format (Formato data e ora)
- 5.1 Ordering
- 5.2 Human Readability
- 5.3 Rarely Used Options
- 5.4 Redundant Information
- 5.5 Simplicity
- 5.6 Internet Date/Time Format
- 5.7 Restrictions
- 5.8 Examples
- 6. References (Riferimenti)
- 7. Security Considerations (Considerazioni sulla sicurezza)
Appendici
- Appendix A. ISO 8601 Collected ABNF
- Appendix B. Day of the Week
- Appendix C. Leap Years
- Appendix D. Leap Seconds
Risorse correlate
- Testo originale ufficiale: RFC 3339 (TXT)
- Pagina ufficiale: RFC 3339 DataTracker
- Errata: RFC Editor Errata
Riferimento rapido
Formato standard
YYYY-MM-DDTHH:MM:SS.sssZ
YYYY-MM-DDTHH:MM:SS.sss±HH:MM
Esempi
1985-04-12T23:20:50.52Z
1996-12-19T16:39:57-08:00
1990-12-31T23:59:60Z (secondo intercalare)
1937-01-01T12:00:27.87+00:20
Nota importante: Questo è il formato standard per rappresentare i timestamp nei protocolli Internet, ampiamente utilizzato in protocolli e formati di dati come HTTP, JSON, XML, ecc.
1. Introduzione
I formati di data e ora causano molta confusione e problemi di interoperabilità su Internet. Questo documento affronta molti dei problemi riscontrati e fornisce raccomandazioni per migliorare la coerenza e l'interoperabilità quando si rappresentano e utilizzano date e ore nei protocolli Internet.
Questo documento include un profilo Internet dello standard ISO 8601 [ISO8601] per la rappresentazione di date e ore utilizzando il calendario gregoriano (Gregorian Calendar).
Esistono molti modi in cui i valori di data e ora possono apparire nei protocolli Internet: questo documento si concentra su un solo uso comune, vale a dire i timestamp per gli eventi dei protocolli Internet. Questa considerazione limitata ha le seguenti conseguenze:
Limitazioni e ipotesi per i timestamp
o Era corrente
Si presume che tutte le date e gli orari si trovino nell'« era corrente », da qualche parte tra lo 0000 d.C. e il 9999 d.C.
o Relazione con UTC
Tutti gli orari espressi hanno una relazione dichiarata (offset) con il Tempo Coordinato Universale (Coordinated Universal Time, UTC). (Questo è distinto da alcuni usi nelle applicazioni di pianificazione in cui un orario locale e una posizione possono essere noti, ma la relazione effettiva con UTC può dipendere dalle azioni sconosciute o inconoscibili di politici o amministratori. L'ora UTC corrispondente alle 17:00 del 23 marzo 2005 a New York può dipendere da decisioni amministrative sull'ora legale. Questa specifica evita deliberatamente tali considerazioni.)
o Timestamp storici
I timestamp possono rappresentare momenti verificatisi prima dell'introduzione dell'UTC. Tali timestamp sono relativi al Tempo Universale (Universal Time), utilizzando la migliore pratica disponibile nel momento indicato.
o Rappresentazione dei punti nel tempo
Le espressioni di data e ora rappresentano un istante nel tempo (Instant in Time). Le descrizioni di periodi di tempo (Time Periods) o intervalli (Intervals) non sono trattate qui.
Punti chiave:
- Questa specifica si concentra sui timestamp, non sui periodi di tempo o sulla pianificazione
- Tutti gli orari devono avere una relazione definita con UTC
- Supporta l'intervallo di date dallo 0000 d.C. al 9999 d.C.
- Evita la dipendenza da decisioni politiche riguardanti i fusi orari locali (come gli aggiustamenti dell'ora legale)
2. Definizioni
Le parole chiave "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" e "OPTIONAL" in questo documento devono essere interpretate come descritto nella RFC 2119 [RFC2119].
Definizioni dei termini
UTC (Coordinated Universal Time, Tempo Coordinato Universale)
Tempo Coordinato Universale come mantenuto dal Bureau International des Poids et Mesures (BIPM).
second (secondo)
Un'unità di base di misurazione del tempo nel Sistema Internazionale di Unità. È definito come la durata di 9.192.631.770 cicli di luce a microonde assorbita o emessa dalla transizione iperfine degli atomi di cesio-133 (cesium-133) nel loro stato fondamentale non disturbato da campi esterni.
minute (minuto)
Un periodo di tempo di 60 secondi. Tuttavia, vedere anche la Sezione 5.7 e l'Appendice D per come i secondi intercalari (Leap Seconds) sono denotati all'interno dei minuti.
hour (ora)
Un periodo di tempo di 60 minuti.
day (giorno)
Un periodo di tempo di 24 ore.
leap year (anno bisestile)
Nel calendario gregoriano, un anno che ha 366 giorni. Un anno bisestile è un anno il cui numero è divisibile per 4, ma non per 100, a meno che non sia anche divisibile per 400.
Regole dell'anno bisestile:
if (anno % 400 == 0) → anno bisestile
else if (anno % 100 == 0) → anno comune
else if (anno % 4 == 0) → anno bisestile
else → anno comune
Esempi:
- 2000: anno bisestile (divisibile per 400)
- 1900: anno comune (divisibile per 100 ma non per 400)
- 2004: anno bisestile (divisibile per 4)
- 2001: anno comune
ABNF (Augmented Backus-Naur Form, Forma di Backus-Naur Aumentata)
Un formato per rappresentare le stringhe consentite in un protocollo o linguaggio, come definito in [ABNF].
Email Date/Time Format (Formato data/ora e-mail)
Il formato di data/ora utilizzato dalla posta Internet come definito dalla RFC 2822 [IMAIL-UPDATE].
Internet Date/Time Format (Formato data/ora Internet)
Il formato della data definito nella sezione 5 di questo documento.
Timestamp
Questo termine è utilizzato in questo documento per riferirsi a una rappresentazione inequivocabile (Unambiguous Representation) di un istante nel tempo.
Z
Un suffisso che, quando applicato a un orario, denota un offset UTC di 00:00; spesso pronunciato "Zulu" dalla rappresentazione dell'alfabeto fonetico ICAO della lettera "Z".
Esempio:
2002-07-15T10:30:00Z
Rappresenta: 15 luglio 2002 alle 10:30:00 UTC
Ulteriori informazioni
Per ulteriori informazioni riguardanti le scale temporali, vedere:
- Appendice E di [NTP]
- Sezione 3 di [ISO8601]
- I documenti ITU appropriati [ITU-R-TF]
Nota: Comprendere questi termini fondamentali è fondamentale per implementare e utilizzare correttamente questa specifica, in particolare le definizioni di anni bisestili e secondi intercalari.
3. Anni a due cifre
I seguenti requisiti affrontano i problemi di ambiguità causati dagli anni a due cifre:
Requisiti
o Gli anni a quattro cifre sono obbligatori
I protocolli Internet devono (MUST) generare anni a quattro cifre nelle date.
Esempi corretti:
✅ 2002-07-15
✅ 1999-12-31
Esempi errati:
❌ 02-07-15
❌ 99-12-31
o Gli anni a due cifre sono deprecati
L'uso di anni a due cifre è deprecato (Deprecated). Se viene ricevuto un anno a due cifre, dovrebbe (SHOULD) essere accettato solo se un'interpretazione errata non causerà un fallimento del protocollo o dell'elaborazione (ad esempio, se utilizzato solo per scopi di registrazione o tracciamento).
o Gestione degli anni a tre cifre
I programmi che utilizzano anni a due cifre possono rappresentare gli anni dopo il 1999 come tre cifre. Ciò si verificherà se il programma sottrae semplicemente 1900 dall'anno senza controllare il numero di cifre. I programmi che desiderano gestire in modo robusto le date generate da tale software difettoso possono (MAY) aggiungere 1900 agli anni a tre cifre.
Esempio:
Output del programma difettoso: 102 (che rappresenta l'anno 2002)
Analisi robusta: 102 + 1900 = 2002
o Gestione delle cifre di decennio non numeriche
I programmi che utilizzano anni a due cifre possono rappresentare gli anni dopo il 1999 come ":0", ":1", ... ":9", ";0", .... Ciò si verificherà se il programma sottrae semplicemente 1900 dall'anno e aggiunge la cifra del decennio al carattere zero US-ASCII. I programmi che desiderano gestire in modo robusto le date generate da tale software difettoso dovrebbero (SHOULD) rilevare le cifre di decennio non numeriche e interpretarle in modo appropriato.
Esempio:
Output del programma difettoso:
- '0' + 10 = ':' (che rappresenta gli anni 2000, codice ASCII 58)
- '0' + 11 = ';' (che rappresenta gli anni 2010, codice ASCII 59)
L'analisi robusta dovrebbe riconoscere questi pattern e convertirli correttamente
Lezioni dal problema Y2K
I problemi con gli anni a due cifre dimostrano ampiamente perché tutte le date e gli orari utilizzati nei protocolli Internet devono (MUST) essere completamente qualificati (Fully Qualified).
Raccomandazioni per l'implementazione
Quando si generano date
✅ Utilizzare sempre anni a quattro cifre: 2024-12-21
❌ Non utilizzare mai due cifre: 24-12-21
Quando si analizzano date
# Esempio di analisi robusta
def parse_year(year_str):
if len(year_str) == 4:
return int(year_str) # Quattro cifre corrette
elif len(year_str) == 2:
# Deprecato, solo per compatibilità con le versioni precedenti
year = int(year_str)
if year < 70:
return 2000 + year
else:
return 1900 + year
elif len(year_str) == 3:
# Gestire software difettoso
return 1900 + int(year_str)
else:
raise ValueError("Formato anno non valido")
Avvertenza: Sebbene questa sezione descriva come gestire gli anni a due cifre, ciò è solo per compatibilità con le versioni precedenti. Le nuove implementazioni non devono assolutamente (MUST NOT) generare anni a due cifre.
4. Ora locale
4.1. Tempo Coordinato Universale (UTC)
Poiché le regole dell'ora legale per i fusi orari locali sono così complicate e possono cambiare in base alla legge locale in momenti imprevedibili, la vera interoperabilità si ottiene meglio utilizzando il Tempo Coordinato Universale (UTC). Questa specifica non tiene conto delle regole dei fusi orari locali.
Perché usare l'UTC?
- ✅ Standard temporale unificato globalmente
- ✅ Non influenzato dall'ora legale
- ✅ Non influenzato da decisioni politiche
- ✅ Garantisce l'interoperabilità
4.2. Offset locali
L'offset tra l'ora locale e l'UTC è spesso un'informazione utile. Ad esempio, nella posta elettronica (RFC2822, [IMAIL-UPDATE]), l'offset locale fornisce un'euristica utile per determinare la probabilità di una risposta tempestiva. I tentativi di etichettare gli offset locali con stringhe alfabetiche hanno portato a una scarsa interoperabilità in passato [IMAIL], [HOST-REQ]. Di conseguenza, RFC2822 [IMAIL-UPDATE] ha reso obbligatori gli offset numerici.
Calcolo dell'offset numerico
Gli offset numerici sono calcolati come «ora locale meno UTC». Quindi l'ora equivalente in UTC può essere determinata sottraendo l'offset dall'ora locale.
Esempio 1:
Ora locale: 18:50:00-04:00
Ora UTC: 18:50:00 - (-04:00) = 18:50:00 + 04:00 = 22:50:00Z
Verifica: Eastern Daylight Time (EDT) è UTC-4
Esempio 2:
Ora locale: 15:30:00+08:00
Ora UTC: 15:30:00 - (+08:00) = 15:30:00 - 08:00 = 07:30:00Z
Verifica: China Standard Time (CST) è UTC+8
Note importanti
Nota: Seguendo ISO 8601, gli offset numerici rappresentano solo fusi orari che differiscono dall'UTC per un numero intero di minuti. Tuttavia, molti fusi orari storici differiscono dall'UTC per un numero non intero di minuti. Per rappresentare esattamente tali timestamp storici, le applicazioni devono (MUST) convertirli in un fuso orario rappresentabile.
Esempi di fusi orari storici:
Alcuni orari locali alla fine del XIX secolo:
- Amsterdam: UTC+00:19:32
- Parigi: UTC+00:09:21
Questi non possono essere rappresentati con precisione in RFC 3339 e devono essere arrotondati al minuto più vicino
4.3. Convenzione per offset locale sconosciuto
Se l'ora in UTC è nota, ma l'offset rispetto all'ora locale è sconosciuto, questo può essere rappresentato con un offset di "-00:00". Questo differisce semanticamente da un offset di "Z" o "+00:00", che implica che l'UTC è il punto di riferimento preferito per l'ora specificata. RFC2822 [IMAIL-UPDATE] descrive una convenzione simile per la posta elettronica.
Distinzione tra tre rappresentazioni
Z o +00:00:
2002-07-15T10:30:00Z
2002-07-15T10:30:00+00:00
Significato: Questo orario È l'ora UTC, l'UTC è il punto di riferimento preferito
-00:00:
2002-07-15T10:30:00-00:00
Significato: L'ora UTC è 10:30:00, ma l'offset del fuso orario locale è sconosciuto
(possibilmente da un sistema che non conosce l'impostazione del fuso orario)
Scenari di utilizzo:
Scenario 1: Log del server, noto per essere UTC → usare Z
Scenario 2: Timestamp generato da dispositivo, il dispositivo è in UTC ma non conosce il fuso locale → usare -00:00
Scenario 3: Esplicitamente a Londra (GMT) → usare +00:00
4.4. Ora locale non qualificata
Un certo numero di dispositivi attualmente connessi a Internet eseguono i loro orologi interni in ora locale e non sono a conoscenza dell'UTC. Sebbene Internet abbia una tradizione di accettare la realtà nella progettazione delle specifiche, questo non dovrebbe essere fatto a scapito dell'interoperabilità. Poiché l'interpretazione di un fuso orario locale non qualificato fallirà in circa 23/24 del globo,
Requisiti obbligatori
I protocolli Internet devono (MUST) generare timestamp completamente qualificati.
Ciò significa che i protocolli Internet non devono (MUST NOT) utilizzare l'ora locale senza informazioni sul fuso orario.
Esempi errati:
❌ 2002-07-15T10:30:00 (nessuna informazione sul fuso orario)
Esempi corretti:
✅ 2002-07-15T10:30:00Z (UTC)
✅ 2002-07-15T10:30:00+08:00 (fuso orario esplicito)
✅ 2002-07-15T10:30:00-00:00 (UTC ma zona sconosciuta)
Problemi di interoperabilità
Se viene utilizzata un'ora locale non qualificata:
Mittente: 2002-07-15T10:30:00 (ora locale di New York, in realtà UTC-4)
Destinatario a Tokyo: Interpreta come ora di Tokyo (UTC+9)
Errore di differenza oraria: 13 ore!
Raccomandazioni per l'implementazione
Progettazione del sistema
# Raccomandato: Memorizzare sempre l'ora in UTC
def store_timestamp():
utc_time = datetime.now(timezone.utc)
return utc_time.isoformat() # 2024-12-21T10:30:00+00:00
# Quando si visualizza: Convertire nel fuso orario locale dell'utente
def display_timestamp(utc_time, user_timezone):
local_time = utc_time.astimezone(user_timezone)
return local_time.isoformat()
Archiviazione nel database
-- Raccomandato: Utilizzare TIMESTAMP WITH TIME ZONE
CREATE TABLE events (
id SERIAL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Evitare: TIMESTAMP WITHOUT TIME ZONE (causa ambiguità)
Principio chiave: Memorizzare internamente in UTC, convertire nel fuso orario locale quando si visualizza. Non utilizzare mai timestamp senza informazioni sul fuso orario per lo scambio di dati.
5. Formato data e ora
Questa sezione discute le qualità desiderabili dei formati di data e ora e definisce un profilo di ISO 8601 per l'uso su Internet.
5.1. Ordering (Ordinamento)
Se i componenti di data e ora sono ordinati dal meno preciso al più preciso, si ottiene una proprietà utile. Supponendo che i fusi orari delle date e degli orari siano gli stessi (ad esempio, tutti in UTC), espressi usando la stessa stringa (ad esempio, tutti "Z" o tutti "+00:00"), e che tutti gli orari abbiano lo stesso numero di cifre di secondi frazionari, allora le stringhe di data e ora possono essere ordinate come stringhe (ad esempio, utilizzando la funzione strcmp() in C) e produrranno una sequenza ordinata temporalmente. La presenza di punteggiatura opzionale violerebbe questa caratteristica.
Esempio:
Ordinamento corretto (anno-mese-giorno ora:minuto:secondo):
2002-01-15T10:00:00Z
2002-07-20T15:30:00Z
2002-12-31T23:59:59Z
Formato errato (mese/giorno/anno) non può essere ordinato correttamente:
01/15/2002 10:00:00
12/31/2002 23:59:59 ← L'ordinamento di stringa pone questo prima di luglio
07/20/2002 15:30:00
5.2. Human Readability (Leggibilità umana)
La leggibilità umana si è dimostrata una caratteristica preziosa dei protocolli Internet. I protocolli leggibili dall'uomo riducono notevolmente i costi di debug poiché telnet è spesso sufficiente come client di test e gli analizzatori di rete non devono essere modificati con la conoscenza del protocollo. D'altra parte, la leggibilità umana a volte porta a problemi di interoperabilità.
Esempi di problemi:
❌ "10/11/1996" è completamente inadatto per lo scambio globale
USA: 11 ottobre 1996
Europa: 10 novembre 1996
❌ Traduzione delle abbreviazioni dei mesi
Inglese: "Jan", "Feb", "Mar"
Francese: "Jan", "Fév", "Mar" ← Rompe l'interoperabilità
Poiché nessun formato di data e ora è leggibile secondo le convenzioni di tutti i paesi, i client Internet dovrebbero (SHOULD) essere preparati a trasformare le date in un formato di visualizzazione adatto alla località. Ciò può includere la traduzione dell'UTC in ora locale.
5.3. Rarely Used Options (Opzioni raramente utilizzate)
Un formato che include opzioni raramente utilizzate è probabile che causi problemi di interoperabilità. Questo perché le opzioni raramente utilizzate sono meno probabili da essere utilizzate nei test alpha o beta, quindi è meno probabile che vengano scoperti bug nell'analisi. Le opzioni raramente utilizzate dovrebbero essere rese obbligatorie o omesse per quanto possibile per motivi di interoperabilità.
Il formato definito di seguito include solo un'opzione raramente utilizzata: Frazioni di secondo (Fractions of a Second). Si prevede che questo sarà utilizzato solo da applicazioni che richiedono un ordinamento rigoroso dei timestamp di data/ora o che hanno requisiti di precisione insoliti.
5.4. Redundant Information (Informazioni ridondanti)
Se un formato di data/ora include informazioni ridondanti, introduce la possibilità che le informazioni ridondanti non siano correlate. Ad esempio, includere il giorno della settimana in un formato di data/ora introduce la possibilità che il giorno della settimana sia errato ma la data sia corretta, o viceversa. Poiché non è difficile calcolare il giorno della settimana dalla data (vedere Appendice B), il giorno della settimana non dovrebbe essere incluso in un formato di data/ora.
Esempio di problema:
❌ "Monday, 2002-07-16T10:00:00Z"
Problema: Il 16 luglio 2002 è in realtà un martedì, non un lunedì
Se il giorno e la data non corrispondono, quale dovrebbe essere attendibile?
✅ "2002-07-16T10:00:00Z"
Soluzione: Omettere il giorno della settimana, calcolare se necessario
5.5. Simplicity (Semplicità)
Il set completo di formati di data e ora specificati in ISO 8601 [ISO8601] è piuttosto complesso nel tentativo di fornire più rappresentazioni e rappresentazioni parziali. L'Appendice A contiene un tentativo di tradurre la sintassi completa di ISO 8601 in ABNF. I protocolli Internet hanno requisiti un po' diversi e la semplicità si è dimostrata una caratteristica importante. Inoltre, i protocolli Internet di solito necessitano di una specifica completa dei dati per ottenere una vera interoperabilità. Pertanto, la sintassi completa di ISO 8601 è ritenuta troppo complessa per la maggior parte dei protocolli Internet.
La sezione seguente definisce un profilo di ISO 8601 per l'uso su Internet. È un sottoinsieme coerente del formato esteso ISO 8601. La semplicità è ottenuta rendendo obbligatori la maggior parte dei campi e della punteggiatura.
5.6. Internet Date/Time Format (Formato data/ora Internet)
Il seguente profilo delle date ISO 8601 [ISO8601] dovrebbe (SHOULD) essere utilizzato nei nuovi protocolli su Internet. Questo è specificato utilizzando la notazione di descrizione della sintassi definita in [ABNF].
Definizione della sintassi ABNF
date-fullyear = 4DIGIT
date-month = 2DIGIT ; 01-12
date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
; month/year
time-hour = 2DIGIT ; 00-23
time-minute = 2DIGIT ; 00-59
time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second
; rules
time-secfrac = "." 1*DIGIT
time-numoffset = ("+" / "-") time-hour ":" time-minute
time-offset = "Z" / time-numoffset
partial-time = time-hour ":" time-minute ":" time-second
[time-secfrac]
full-date = date-fullyear "-" date-month "-" date-mday
full-time = partial-time time-offset
date-time = full-date "T" full-time
Note importanti
Sensibilità alle maiuscole/minuscole: Secondo [ABNF] e ISO8601, i caratteri "T" e "Z" in questa sintassi possono alternativamente essere rispettivamente in minuscolo "t" o "z".
Le specifiche che utilizzano questo formato in ambienti dove la distinzione tra maiuscole e minuscole è significativa (come XML) possono (MAY) limitare ulteriormente la sintassi di data/ora in modo che le lettere 'T' e 'Z' utilizzate nella sintassi di data/ora debbano essere sempre maiuscole. Le applicazioni che generano questo formato dovrebbero (SHOULD) utilizzare lettere maiuscole.
Delimitatori: ISO 8601 definisce data e ora separati da "T". Le applicazioni che utilizzano questa sintassi possono (MAY) scegliere, per motivi di leggibilità, di specificare un full-date e full-time separati da (ad esempio) un carattere spazio.
Esempi di formato
Formato standard:
2002-07-15T10:30:00Z
2002-07-15T10:30:00.123Z
2002-07-15T10:30:00+08:00
2002-07-15T10:30:00-04:00
Con secondi frazionari:
2002-07-15T10:30:00.123456Z
2002-07-15T10:30:00.52Z
Varianti leggibili (non standard ma consentite):
2002-07-15 10:30:00Z
2002-07-15t10:30:00z
5.7. Restrictions (Restrizioni)
L'elemento grammaticale date-mday rappresenta il numero del giorno all'interno del mese corrente. Il valore massimo varia in base al mese e all'anno:
| Numero mese | Mese/Anno | Massimo date-mday |
|---|---|---|
| 01 | Gennaio (January) | 31 |
| 02 | Febbraio, normale (February, normal) | 28 |
| 02 | Febbraio, anno bisestile (February, leap year) | 29 |
| 03 | Marzo (March) | 31 |
| 04 | Aprile (April) | 30 |
| 05 | Maggio (May) | 31 |
| 06 | Giugno (June) | 30 |
| 07 | Luglio (July) | 31 |
| 08 | Agosto (August) | 31 |
| 09 | Settembre (September) | 30 |
| 10 | Ottobre (October) | 31 |
| 11 | Novembre (November) | 30 |
| 12 | Dicembre (December) | 31 |
Secondi intercalari
L'elemento grammaticale time-second può (MAY) avere il valore "60" alla fine dei mesi in cui si verifica un secondo intercalare. I secondi intercalari sono utilizzati per mantenere l'UTC vicino al tempo di rotazione della Terra. Vedere l'Appendice D per ulteriori informazioni sui secondi intercalari.
Esempi di secondi intercalari:
1990-12-31T23:59:60Z ✅ Valido (secondo intercalare il 31 dicembre 1990)
1990-12-31T23:59:61Z ❌ Non valido (massimo è 60)
1990-06-15T23:59:60Z ❌ Non valido (secondi intercalari solo a fine mese)
5.8. Examples (Esempi)
Ecco alcuni esempi di timestamp di data/ora RFC 3339 validi:
1985-04-12T23:20:50.52Z
Rappresenta: 12 aprile 1985, 23:20:50.52 UTC
1996-12-19T16:39:57-08:00
Rappresenta: 19 dicembre 1996, 16:39:57 Pacific Standard Time (PST)
UTC equivalente: 1996-12-20T00:39:57Z
1990-12-31T23:59:60Z
Rappresenta: Secondo intercalare il 31 dicembre 1990
1990-12-31T15:59:60-08:00
Rappresenta: Secondo intercalare il 31 dicembre 1990 in PST
UTC equivalente: 1990-12-31T23:59:60Z
1937-01-01T12:00:27.87+00:20
Rappresenta: 1 gennaio 1937, 12:00:27.87, UTC+00:20
(Esempio di fuso orario storico)
Esempi non validi
❌ 1985-04-12 (ora mancante)
❌ 23:20:50.52Z (data mancante)
❌ 1985-04-12 23:20:50.52Z (dovrebbe usare 'T' non spazio, sebbene alcune implementazioni lo consentano)
❌ 1985-04-32T23:20:50.52Z (data non valida: aprile non ha il 32° giorno)
❌ 1985-02-29T23:20:50.52Z (data non valida: il 1985 non è un anno bisestile)
Raccomandazione per l'implementazione: Generare sempre il formato standard (utilizzando il delimitatore 'T' e 'Z' maiuscolo), ma analizzare in modo liberale (accettare 't', 'z' e possibilmente delimitatori di spazio).
6. Riferimenti
Normative References (Riferimenti normativi)
[ABNF]
Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, November 1997.
[ISO8601]
"Data elements and interchange formats -- Information interchange -- Representation of dates and times", ISO 8601:1988(E), International Organization for Standardization, June 1988.
Nota: ISO 8601:1988 è stato aggiornato da ISO 8601:2000, che a sua volta è stato aggiornato da ISO 8601:2004. RFC 3339 si basa sulla versione del 1988.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
Informative References (Riferimenti informativi)
[IMAIL]
Crocker, D., "Standard for the Format of Arpa Internet Text Messages", STD 11, RFC 822, August 1982.
[IMAIL-UPDATE]
Resnick, P., "Internet Message Format", RFC 2822, April 2001.
[HOST-REQ]
Braden, R., "Requirements for Internet Hosts -- Application and Support", STD 3, RFC 1123, October 1989.
[NTP]
Mills, D., "Network Time Protocol (Version 3) Specification, Implementation and Analysis", RFC 1305, March 1992.
[ITU-R-TF]
"Standard-frequency and time-signal emissions", ITU-R Recommendation TF.460-4, 1986.
[UNICODE]
The Unicode Consortium, "The Unicode Standard", Version 3.0, Reading, MA, Addison-Wesley, 2000, ISBN 0-201-61633-5.
Documenti RFC correlati
Documenti predecessori
- RFC 822 - Formato di posta elettronica (Standard for the Format of ARPA Internet Text Messages)
- RFC 2822 - Formato del messaggio Internet (Aggiorna RFC 822)
Standard correlati
- RFC 2234 - Specifica della sintassi ABNF
- RFC 2119 - Definizione delle parole chiave RFC
- RFC 1305 - Protocollo di tempo di rete (NTP)
Aggiornamenti successivi
- RFC 4287 - Formato di syndication Atom (utilizza timestamp RFC 3339)
- RFC 7493 - Formato del messaggio I-JSON (raccomanda RFC 3339)
- RFC 8259 - Formato di scambio dati JSON (raccomanda RFC 3339 per data-ora)
Standard esterni
Serie ISO 8601
- ISO 8601:1988 - Versione su cui si basa questo RFC
- ISO 8601:2000 - Prima revisione
- ISO 8601:2004 - Seconda revisione
- ISO 8601-1:2019 - Versione più recente, Parte 1: Regole di base
- ISO 8601-2:2019 - Versione più recente, Parte 2: Estensioni
Altri standard correlati
- IETF BCP 14 - Migliore pratica corrente composta da RFC 2119 e RFC 8174
- W3C Date and Time Formats - Basato su ISO 8601 e RFC 3339
- ECMA-262 - Formato della stringa data-ora JavaScript (basato su ISO 8601 semplificato)
Applicazioni pratiche
Il formato RFC 3339 è ampiamente utilizzato in:
Protocolli Internet:
- Intestazione HTTP Date (sebbene HTTP utilizzi un formato diverso definito in RFC 7231)
- Timestamp dei feed Atom/RSS
- Timestamp delle API JSON
- Tipo dateTime dello schema XML
Linguaggi di programmazione:
- JavaScript
Date.toISOString() - Python
datetime.isoformat() - Java
Instant.toString() - Go
time.RFC3339
Database:
- PostgreSQL
TIMESTAMPTZ - MongoDB
ISODate - MySQL
TIMESTAMPwith timezone
Nota: Sebbene RFC 3339 sia basato su ISO 8601:1988, è un profilo (sottoinsieme) di ISO 8601, non un'implementazione completa. RFC 3339 è più rigoroso e semplificato per garantire l'interoperabilità nei protocolli Internet.
7. Considerazioni sulla sicurezza
Poiché questo documento specifica solo un formato per rappresentare date e orari, i problemi di sicurezza discussi qui si limitano all'impatto che gli orologi non sincronizzati hanno sulle funzionalità di sicurezza.
Rischi di sicurezza degli orologi non sincronizzati
1. Errori di validazione dei certificati
Gli orologi non sincronizzati possono far apparire incorrettamente i certificati come scaduti o non ancora validi.
Esempio di rischio:
Orologio client: 2002-07-14T10:00:00Z (1 giorno avanti)
Validità del certificato:
Not Before: 2002-07-15T00:00:00Z
Not After: 2003-07-15T23:59:59Z
Risultato: Il client rifiuta un certificato valido ❌
Caso opposto:
Orologio client: 2003-07-20T10:00:00Z (2 anni indietro)
Validità del certificato:
Not After: 2003-07-15T23:59:59Z (già scaduto)
Risultato: Il client accetta un certificato scaduto ⚠️ Rischio di sicurezza!
2. Bypass della verifica dei timestamp
Molti protocolli di sicurezza si affidano ai timestamp per prevenire gli attacchi replay.
Esempio di attacco replay:
Richiesta legittima intercettata dall'attaccante:
POST /transfer HTTP/1.1
Timestamp: 2002-07-15T10:00:00Z
Amount: $1000
Signature: valid_signature
Se l'orologio del server è indietro di 1 ora, l'attaccante può ripetere questa richiesta
3. Log di audit inaffidabili
Se i timestamp dei log sono imprecisi, l'audit di sicurezza e l'analisi forense diventano impossibili o inaffidabili.
Scenario problematico:
Log del server A: 2002-07-15T10:00:00Z - Intrusione rilevata
Log del server B: 2002-07-15T09:45:00Z - Login anomalo (in realtà successivo ad A, ma orologio indietro)
Impossibile stabilire una timeline di attacco accurata ❌
Raccomandazioni di protezione
Utilizzare NTP (Network Time Protocol)
Tutti i sistemi connessi a Internet dovrebbero (SHOULD) utilizzare NTP o protocolli simili di sincronizzazione del tempo.
Esempio di configurazione NTP:
# Configurare il server NTP
ntpdate -u time.nist.gov
# Abilitare il demone ntpd
systemctl enable ntpd
systemctl start ntpd
# Verificare lo stato di sincronizzazione
ntpq -p
Tolleranza dei timestamp
Implementare finestre di tolleranza ragionevoli durante la validazione dei timestamp.
Esempio di implementazione:
def is_timestamp_valid(timestamp, max_age_seconds=300):
"""Verificare che il timestamp sia entro una finestra temporale accettabile"""
now = datetime.now(timezone.utc)
tolerance = timedelta(seconds=max_age_seconds)
# Consentire ±5 minuti di disallineamento dell'orologio
if abs(now - timestamp) > tolerance:
return False
return True
Utilizzare fonti di tempo affidabili
Server NTP pubblici raccomandati:
time.nist.gov (Istituto Nazionale di Standard e Tecnologia degli Stati Uniti)
time.google.com (Google)
time.apple.com (Apple)
time.cloudflare.com (Cloudflare)
pool.ntp.org (Progetto NTP Pool)
Migliori pratiche di validazione dei certificati
# Considerare il disallineamento dell'orologio durante la validazione dei certificati
def verify_certificate(cert, clock_tolerance=timedelta(minutes=5)):
now = datetime.now(timezone.utc)
# Verificare Not Before con indulgenza
if now < (cert.not_before - clock_tolerance):
raise CertificateNotYetValid()
# Verificare Not After rigorosamente (sicurezza prima)
if now > cert.not_after:
raise CertificateExpired()
Problemi di sicurezza relativi al fuso orario
1. Attacchi di confusione del fuso orario
La gestione incoerente dei fusi orari può portare a bypass di sicurezza.
Esempio di vulnerabilità:
Invio utente: 2002-07-15T23:00:00-08:00
Sistema A analizza come: 2002-07-16T07:00:00Z (corretto)
Sistema B analizza come: 2002-07-15T23:00:00Z (errato, ignora il fuso orario)
Se il sistema B viene utilizzato per decisioni di controllo accessi, può consentire accesso non autorizzato
2. Confini dell'ora legale
Ambiguità o problemi di sicurezza possono verificarsi durante le transizioni dell'ora legale.
Momenti a rischio:
10 marzo 2002 2:00 → 3:00 (salto di 1 ora)
Problema: 2:30 non esiste, come gestire questo timestamp?
3 novembre 2002 2:00 → 1:00 (ripetizione di 1 ora)
Problema: 1:30 si verifica due volte, quale è corretto?
Soluzione RFC 3339: Utilizzare l'offset UTC per eliminare l'ambiguità:
✅ 2002-11-03T01:30:00-05:00 (EDT, prima della fine dell'ora legale)
✅ 2002-11-03T01:30:00-04:00 (EST, dopo la fine dell'ora legale)
Impatto sulla sicurezza dei secondi intercalari
Sebbene rari, una gestione impropria dei secondi intercalari può causare problemi.
Problemi potenziali:
1990-12-31T23:59:60Z (secondo intercalare)
Se il sistema non supporta i secondi intercalari:
- Può rifiutare timestamp validi
- Può causare errori di ordinamento
- Può causare differenze di tempo di 1 secondo
Raccomandazione:
# Gestire i secondi intercalari con indulgenza
def parse_timestamp(ts_string):
try:
return datetime.fromisoformat(ts_string)
except ValueError as e:
# Verificare se è un secondo intercalare (secondo è 60)
if ':60Z' in ts_string or ':60+' in ts_string or ':60-' in ts_string:
# Convertire 60 secondi in 00 secondi del minuto successivo
ts_string = ts_string.replace(':60', ':59')
return datetime.fromisoformat(ts_string) + timedelta(seconds=1)
raise
Lista di controllo della sicurezza
Quando si implementano i timestamp RFC 3339, assicurarsi di:
- Sincronizzare gli orologi di sistema utilizzando NTP
- Utilizzare sempre UTC per l'archiviazione e il confronto interni
- Implementare una tolleranza ragionevole durante la validazione dei timestamp
- Gestire correttamente gli offset del fuso orario
- Registrare tutti gli eventi di sicurezza relativi al tempo
- Controllare regolarmente l'accuratezza dell'orologio di sistema
- Considerare il disallineamento dell'orologio nella validazione del certificato
- Implementare la protezione dagli attacchi replay (nonce + timestamp)
- Analizzare con indulgenza, generare rigorosamente
- Testare i casi limite (secondi intercalari, anni bisestili, fine mese)
Principio chiave: Non fare affidamento sui timestamp forniti dal client per decisioni di sicurezza critiche. Utilizzare sempre fonti di tempo affidabili lato server.
Appendix A. ISO 8601 Collected ABNF
Queste informazioni si basano sulla versione 1988 di ISO 8601. Potrebbero esserci alcune modifiche nella revisione del 2000.
Spiegazione
ISO 8601 non specifica una grammatica formale per i formati di data e ora che definisce. Quanto segue è un tentativo di creare una grammatica formale da ISO 8601. Questo è solo a scopo informativo e può contenere errori. ISO 8601 rimane il riferimento autorevole.
Ambiguità e interpretazioni
Si noti che a causa di ambiguità in ISO 8601, è stata necessaria una certa interpretazione:
-
Miscelazione di formati base ed estesi: ISO 8601 non è chiaro se la miscelazione di formato base ed esteso sia consentita. Questa grammatica permette la miscelazione.
-
24 ore: ISO 8601 non è chiaro se l'ora 24 sia consentita solo se minuti e secondi sono 0. Questa grammatica presume che l'ora 24 sia consentita in qualsiasi contesto.
-
Restrizioni di data: Si applicano le restrizioni nella sezione 5.7 riguardanti date-mday.
-
Delimitatore "T": ISO 8601 specifica che "T" può essere omesso in determinate circostanze. Questa grammatica richiede "T" per evitare ambiguità.
-
Punto decimale: ISO 8601 richiede (nella sezione 5.3.1.3) che se la frazione decimale è inferiore a 1, deve essere preceduta da "0". L'appendice B.2 di ISO 8601 fornisce esempi con frazioni decimali non precedute da "0". Questa grammatica presume che la sezione 5.3.1.3 sia corretta e l'appendice B.2 sia errata.
Grammatica ABNF completa ISO 8601
date-century = 2DIGIT ; 00-99
date-decade = DIGIT ; 0-9
date-subdecade = DIGIT ; 0-9
date-year = date-decade date-subdecade
date-fullyear = date-century date-year
date-month = 2DIGIT ; 01-12
date-wday = DIGIT ; 1-7 ; 1 is Monday, 7 is Sunday
date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31
date-yday = 3DIGIT ; 001-365, 001-366
date-week = 2DIGIT ; 01-52, 01-53
datepart-fullyear = [date-century] date-year ["-"]
datepart-ptyear = "-" [date-subdecade ["-"]]
datepart-wkyear = datepart-fullyear / datepart-ptyear
dateopt-century = "-" / date-century
dateopt-fullyear = "-" / datepart-fullyear
dateopt-year = "-" / (date-year ["-"])
dateopt-month = "-" / (date-month ["-"])
dateopt-week = "-" / (date-week ["-"])
datespec-full = datepart-fullyear date-month ["-"] date-mday
datespec-year = date-century / dateopt-century date-year
datespec-month = "-" dateopt-year date-month [["-"] date-mday]
datespec-mday = "--" dateopt-month date-mday
datespec-week = datepart-wkyear "W"
(date-week / dateopt-week date-wday)
datespec-wday = "---" date-wday
datespec-yday = dateopt-fullyear date-yday
date = datespec-full
/ datespec-year
/ datespec-month
/ datespec-mday
/ datespec-week
/ datespec-wday
/ datespec-yday
time-hour = 2DIGIT ; 00-24
time-minute = 2DIGIT ; 00-59
time-second = 2DIGIT ; 00-58, 00-59, 00-60
time-fraction = ("," / ".") 1*DIGIT
time-numoffset = ("+" / "-") time-hour [[":"] time-minute]
time-zone = "Z" / time-numoffset
timeopt-hour = "-" / (time-hour [":"])
timeopt-minute = "-" / (time-minute [":"])
timespec-hour = time-hour [[":"] time-minute [[":"] time-second]]
timespec-minute = timeopt-hour time-minute [[":"] time-second]
timespec-second = "-" timeopt-minute time-second
timespec-base = timespec-hour / timespec-minute / timespec-second
time = timespec-base [time-fraction] [time-zone]
iso-date-time = date "T" time
RFC 3339 vs ISO 8601 completo
RFC 3339 è un sottoinsieme limitato di ISO 8601, non un'implementazione completa:
| Caratteristica | ISO 8601 | RFC 3339 |
|---|---|---|
| Formato base (20020715) | ✅ Supportato | ❌ Non supportato |
| Formato esteso (2002-07-15) | ✅ Supportato | ✅ Supportato |
| Date di settimana (2002-W29-1) | ✅ Supportato | ❌ Non supportato |
| Date ordinali (2002-196) | ✅ Supportato | ❌ Non supportato |
| Date parziali (2002-07) | ✅ Supportato | ❌ Non supportato |
| 24 ore (2002-07-16T24:00:00) | ✅ Supportato | ❌ Non supportato |
| Fuso orario "Z" | ✅ Supportato | ✅ Supportato |
| Offset del fuso orario numerico | ✅ Supportato | ✅ Supportato (obbligatorio) |
| Secondi frazionari | ✅ Supportato | ✅ Supportato |
Motivi della semplificazione di RFC 3339
RFC 3339 ha scelto un sottoinsieme semplificato per:
- Interoperabilità: Ridurre le variazioni di implementazione
- Chiarezza: Evitare l'ambiguità
- Completezza: Richiedere informazioni complete su data-ora
- Semplicità: Più facile da implementare e testare
Nota: Se è necessaria la funzionalità completa di ISO 8601 (come le date di settimana), consultare direttamente lo standard ISO 8601. RFC 3339 si concentra sui casi d'uso di timestamp più comuni nei protocolli Internet.
Appendix B. Giorno della settimana
Questa appendice mostra come calcolare il giorno della settimana da qualsiasi data del calendario gregoriano. Questo è importante per comprendere perché RFC 3339 non include informazioni sul giorno della settimana—perché può essere calcolato con precisione.
Congruenza di Zeller
Un algoritmo comunemente utilizzato per calcolare il giorno della settimana è la congruenza di Zeller, inventata da Christian Zeller nel 1882.
Formula
h = (q + ⌊13(m+1)/5⌋ + K + ⌊K/4⌋ + ⌊J/4⌋ - 2J) mod 7
Dove:
h: Giorno della settimana (0 = sabato, 1 = domenica, 2 = lunedì, ..., 6 = venerdì)q: Giorno del mese (1-31)m: Mese (3-14, dove 3 = marzo, 4 = aprile, ..., 12 = dicembre, 13 = gennaio, 14 = febbraio)K: Anno del secolo (year % 100)J: Secolo (⌊year/100⌋)⌊x⌋: Funzione pavimento
Nota: Gennaio e febbraio sono trattati come il 13° e 14° mese dell'anno precedente.
Implementazione Python
def day_of_week_zeller(year, month, day):
"""
Calcolare il giorno della settimana usando la formula di Zeller
Restituisce: 0=sabato, 1=domenica, ..., 6=venerdì
"""
# Gennaio e febbraio sono trattati come mesi 13 e 14 dell'anno precedente
if month < 3:
month += 12
year -= 1
q = day
m = month
K = year % 100
J = year // 100
h = (q + (13 * (m + 1)) // 5 + K + K // 4 + J // 4 - 2 * J) % 7
# Convertire al formato comune: 0=lunedì, ..., 6=domenica
# Zeller: 0=Sab, 1=Dom, 2=Lun, 3=Mar, 4=Mer, 5=Gio, 6=Ven
# Aggiustare a: 0=Lun, 1=Mar, 2=Mer, 3=Gio, 4=Ven, 5=Sab, 6=Dom
return (h + 5) % 7
def day_name(year, month, day):
"""Restituire il nome del giorno della settimana"""
days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday', 'Sunday']
return days[day_of_week_zeller(year, month, day)]
# Esempi
print(day_name(2002, 7, 15)) # Monday
print(day_name(2000, 1, 1)) # Saturday
print(day_name(1999, 12, 31)) # Friday
Algoritmo più semplice
Per le implementazioni di programmazione, può essere utilizzato un algoritmo più intuitivo:
def day_of_week_simple(year, month, day):
"""
Calcolo semplificato del giorno della settimana
Restituisce: 0=lunedì, ..., 6=domenica
"""
# Giorni cumulativi prima di ogni mese (anno non bisestile)
t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
if month < 3:
year -= 1
y = year % 100
c = year // 100
return (y + y // 4 + c // 4 - 2 * c + t[month - 1] + day) % 7
Implementazione JavaScript
function dayOfWeek(year, month, day) {
// L'oggetto Date di JavaScript calcola automaticamente il giorno della settimana
const date = new Date(year, month - 1, day);
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday'];
return days[date.getDay()];
}
// Esempi
console.log(dayOfWeek(2002, 7, 15)); // Monday
Esempi di verifica
| Data | Giorno della settimana | Verificato |
|---|---|---|
| 2002-07-15 | Lunedì (Monday) | ✅ |
| 2000-01-01 | Sabato (Saturday) | ✅ |
| 1999-12-31 | Venerdì (Friday) | ✅ |
| 1985-04-12 | Venerdì (Friday) | ✅ |
| 1990-12-31 | Lunedì (Monday) | ✅ |
Perché RFC 3339 non include il giorno della settimana
1. Informazione ridondante
Il giorno della settimana può essere calcolato con precisione dalla data, quindi includerlo introduce potenziali incoerenze:
Esempio errato:
"Monday, 2002-07-16T10:00:00Z"
Problema: 2002-07-16 è in realtà martedì, non lunedì
A quale si dovrebbe dare fiducia? Giorno della settimana o data?
2. Complessità aumentata
I parser devono gestire la validazione e le incoerenze tra giorno della settimana e data.
3. Problemi di localizzazione
I nomi dei giorni della settimana differiscono tra le lingue:
Inglese: Monday, Tuesday, Wednesday, ...
Francese: Lundi, Mardi, Mercredi, ...
Italiano: Lunedì, Martedì, Mercoledì, ...
4. Non influisce sul punto temporale
Il giorno della settimana non influisce sulla determinazione del punto temporale, è solo per la leggibilità umana.
Raccomandazione
Se è necessario visualizzare il giorno della settimana:
from datetime import datetime
# Analizzare il timestamp RFC 3339
timestamp = "2002-07-15T10:00:00Z"
dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
# Calcolare e visualizzare il giorno della settimana
day_name = dt.strftime('%A')
print(f"{timestamp} is a {day_name}")
# Output: 2002-07-15T10:00:00Z is a Monday
Conclusione: Poiché il giorno della settimana può essere calcolato in modo preciso e deterministico dalla data, includerlo nel formato del timestamp non è solo non necessario ma dannoso.
Appendix D. Secondi intercalari
Questa appendice descrive il concetto, la storia e la gestione dei secondi intercalari in RFC 3339.
Cosa sono i secondi intercalari?
Un secondo intercalare viene occasionalmente aggiunto al Tempo Coordinato Universale (UTC) per mantenere l'UTC sincronizzato con la rotazione terrestre.
Perché i secondi intercalari?
Tempo Atomico Internazionale (TAI):
- Basato su orologi atomici, estremamente stabile
- 1 secondo = 9.192.631.770 oscillazioni di atomi di cesio
- Non cambia mai
Rotazione terrestre:
- Non perfettamente uniforme
- Influenzata dall'attrito delle maree
- Rallenta gradualmente (~1,4ms/giorno per secolo)
- Velocità imprevedibile
Come funzionano i secondi intercalari
Esempio di secondo intercalare positivo
Normale fine mese:
23:59:58
23:59:59
00:00:00 (giorno successivo)
Con secondo intercalare positivo:
23:59:58
23:59:59
23:59:60 ← Secondo intercalare!
00:00:00 (giorno successivo)
Rappresentazione RFC 3339
1990-12-31T23:59:60Z ✅ Valido (secondo intercalare il 31 dic 1990)
2012-06-30T23:59:60Z ✅ Valido (secondo intercalare il 30 giu 2012)
2015-06-30T23:59:60Z ✅ Valido (secondo intercalare il 30 giu 2015)
2016-12-31T23:59:60Z ✅ Valido (secondo intercalare il 31 dic 2016)
Secondi intercalari storici
Dall'introduzione dell'UTC nel 1972:
Data Ora UTC TAI-UTC
1972-06-30 23:59:60Z +11s
1972-12-31 23:59:60Z +12s
1990-12-31 23:59:60Z +26s
2012-06-30 23:59:60Z +35s
2015-06-30 23:59:60Z +36s
2016-12-31 23:59:60Z +37s (più recente)
Nota:
- Secondi intercalari aggiunti solo il 30 giugno o 31 dicembre
- 27 secondi intercalari dal 1972
- L'ultimo era il 31 dicembre 2016
Punto chiave: RFC 3339 consente i secondi intercalari ma la maggior parte delle implementazioni li mappa al secondo successivo per compatibilità pratica.