L'oggetto Date è un istante nel tempo
In JavaScript una Date rappresenta un singolo istante: internamente è solo un numero di millisecondi a partire dal 1° gennaio 1970 UTC (la "Unix epoch"). Tutto il resto (anni, mesi, giorni, fusi orari, formattazione) è una vista costruita sopra quel numero.
now.getTime() è il conteggio grezzo dei millisecondi. Tutto ciò che fa una Date (confrontare, aggiungere giorni, formattare) si riduce a manipolare quel numero e poi reinterpretarlo.
Tieni a mente questo modello. Una Date non è "14 marzo a Parigi". È un istante universale che può essere mostrato come 14 marzo a Parigi, o 13 marzo a Los Angeles, a seconda del fuso orario da cui lo guardi.
Creare le date
Ci sono quattro modi principali per costruire una Date:
Due cose da notare:
- Il costruttore per parti usa mesi con indice da zero.
2significa marzo. Gennaio è0. È una fonte costante di errori di uno: anche nel resto dell'API i mesi partono da 0, quindi almeno è coerente con sé stessa. new Date("2026-03-14")(senza orario) viene interpretata come mezzanotte UTC.new Date("2026-03-14T09:30")(senzaZ) viene interpretata come ora locale. Questa asimmetria è un tranello classico.
Per avere "adesso" come numero, preferisci Date.now(): evita di creare l'oggetto:
Date.now() è lo strumento giusto per misurare il tempo trascorso, per i timeout e per tutto ciò in cui non ti servono calcoli sul calendario.
Leggere le parti di una data
Una volta che hai una Date, ne estrai i componenti con i getter. Ognuno esiste in due versioni: ora locale e UTC.
Quelli locali dipendono dalla macchina su cui gira il codice. Se salvi o confronti date tra utenti e server diversi, scegli esplicitamente UTC o finirai a inseguire bug fantasma. Regola pratica: usa i getter UTC per tutto ciò che va in un database o in un log; usa i getter locali per tutto ciò che stai per mostrare a una persona.
Non usare getYear(). È un metodo legacy che restituisce year - 1900 ed esiste solo per compatibilità. Usa sempre getFullYear().
Formattare per le persone
Evita date.toString() per qualsiasi cosa ti importi: il suo output dipende dalle impostazioni locali e dal motore. Ci sono due formattatori da conoscere.
Per una stringa standard leggibile dalle macchine, usa toISOString():
È il formato da usare per i log, per salvare in JSON o per inviare dati in rete. È sempre in UTC e sempre non ambiguo.
Per una stringa destinata alle persone, usa Intl.DateTimeFormat o i metodi toLocale*, che lo usano internamente:
Intl.DateTimeFormat gestisce lingue, fusi orari e ogni combinazione di campi che potresti volere. Usalo prima di scrivere a mano una formattazione come ${year}-${month}-${day}: è in quel tipo di costruzione di stringhe che si nascondono gli errori di un mese.
Confrontare le date
Due oggetti Date che rappresentano lo stesso istante non sono uguali con ===: === controlla l'identità dell'oggetto, non il valore. Confronta invece i loro timestamp:
Per l'ordinamento, gli operatori di confronto funzionano direttamente perché convertono in numeri:
La sottrazione ti dà la distanza in millisecondi. Dividi per 1000 * 60 * 60 * 24 per ottenere i giorni. Scrivi la costante per esteso la prima volta; dopo un po' riconoscerai 86_400_000 a colpo d'occhio.
Calcoli con le date
Non esiste un metodo addDays. Il modo idiomatico è usare setDate, setMonth e simili: accettano valori fuori intervallo e passano correttamente al periodo successivo:
Due cose da sottolineare:
new Date(date)copia la data.setDatemodifica l'oggetto, quindi copia sempre prima, altrimenti cambierai il valore di chi ha chiamato la funzione.setDate(35)su un mese di 31 giorni passa automaticamente al mese successivo. Lo stesso vale persetMonth(14), che fa avanzare l'anno. Questo rende i calcoli molto meno dolorosi di quanto sembri.
Per qualsiasi cosa complessa (giorni lavorativi, eventi ricorrenti, durate che tengono conto dei mesi) usa una libreria (date-fns, Luxon o la futura API Temporal). Scriverti da solo la matematica del calendario oltre il "aggiungi qualche giorno" è una palude.
Fusi orari: un bagno di realtà
I fusi orari sono la più grande fonte di bug con le date. Le regole da assimilare:
- Una
Datememorizza un istante UTC. Il fuso orario viene applicato solo quando ne leggi le parti o la formatti. - Il fuso orario usato da
getHours(),getDate()e simili è quello locale della macchina che esegue il codice. Server e browser spesso non sono d'accordo. new Date("2026-03-14")(solo data) viene interpretata come UTC.new Date("2026-03-14T00:00")(con orario, senza fuso) come ora locale.new Date(2026, 2, 14)(per parti) è in ora locale.
Quando ti serve un fuso orario specifico per la visualizzazione, passa timeZone a Intl.DateTimeFormat:
Stesso istante, due viste. L'oggetto Date in sé non è cambiato.
Un piccolo esempio funzionante
Mettiamo tutto insieme: una funzione che indica quanto tempo fa è successo qualcosa:
Timestamp in ingresso, stringa leggibile in uscita. È la forma del 90% del codice reale sulle date: sottrai due istanti, dividi per un'unità, arrotonda, formatta.
Cosa portarti a casa
- Una
Dateè un istante UTC. I fusi orari compaiono quando la leggi o la formatti. - Usa
Date.now()per i timestamp,new Date()per i calcoli sul calendario. - Usa
toISOString()per il salvataggio e i log,Intl.DateTimeFormatper gli utenti. - Confronta con
getTime()o con</>. Mai con===. - I mesi partono da 0. Attenzione alla trappola del parsing delle stringhe con la sola data.
- Per calcoli seri sulle date, usa una libreria.
Prossimo passo: URL e query string
Le date compaiono spesso negli URL: filtri per intervallo di date, timestamp passati come parametri di query. Analizzare e costruire URL a mano è soggetto a errori tanto quanto formattare le date a mano, e la libreria standard ha un oggetto URL che se ne occupa in modo pulito. È il prossimo argomento.
Domande frequenti
Come si ottiene la data corrente in JavaScript?
Chiama new Date() senza argomenti. Restituisce un oggetto Date che rappresenta l'istante in cui è stato eseguito il costruttore. Se ti serve solo un timestamp numerico (millisecondi dal 1970), usa Date.now(): è più veloce e non crea un oggetto completo.
Come si confrontano due date in JavaScript?
Confronta i loro timestamp, non gli oggetti Date in sé. a.getTime() < b.getTime() funziona, e funziona anche a < b perché < converte le date in numeri. Ma a === b no: === controlla l'identità degli oggetti, quindi due oggetti Date che rappresentano lo stesso istante non sono mai strettamente uguali.
Come si formatta una data in JavaScript?
Per tutto ciò che vede l'utente, usa Intl.DateTimeFormat o date.toLocaleDateString(): gestiscono correttamente lingue e fusi orari. Per un output leggibile dalle macchine, date.toISOString() ti dà una stringa standard come 2026-03-14T09:30:00.000Z. Evita date.toString() per salvare i dati: il formato dipende dalle impostazioni locali.
Perché la mia data in JavaScript è sbagliata di un giorno?
Di solito è un problema di fuso orario. new Date('2026-03-14') viene interpretata come mezzanotte UTC, ma date.getDate() restituisce il giorno nel fuso orario locale, che può essere il giorno prima. Usa getUTCDate() per il giorno in UTC, oppure costruisci le date con new Date(year, month, day), che usa l'ora locale fin dall'inizio.