Fusi orari e timestamp
Salvataggio in UTC, conversione dei fusi orari e insidie sui timestamp sollevate nei colloqui.
Fusi orari e timestamp è una lezione Coding Interview Prep gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Coding Interview Prep, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Coding Interview Prep include 4 lezioni in totale.
Perché i fusi orari mettono in difficoltà i candidati
I fusi orari sono il punto in cui anche i candidati più sicuri inciampano, quindi gli intervistatori li verificano per valutare il livello di comprensione. La domanda fondamentale è sempre: "come si memorizzano e confrontano i timestamp tra regioni diverse?"
La risposta professionale consiste in una disciplina, non in una funzione: memorizzare tutto in UTC e convertire solo ai margini, per la visualizzazione. Se il modello di memorizzazione è corretto, la maggior parte delle query diventa banale.
- timestamp vs timestamptz
- Conversione tra fusi orari
- UTC come fonte di verità
timestamp vs timestamptz
PostgreSQL dispone di due tipi di timestamp e confonderli è uno degli errori più comuni nei colloqui.
timestamp(senza fuso orario): un valore dell'orologio locale con nessun fuso associato. Memorizza esattamente il valore fornito.timestamptz(con fuso orario): viene memorizzato internamente come UTC; in input viene convertito dal fuso della sessione, mentre in output viene riconvertito.
Nonostante il nome, timestamptz non memorizza un fuso; memorizza un istante preciso in UTC. È un dettaglio che fa una buona impressione agli intervistatori.
CREATE TABLE events (
id bigint,
occurred_at timestamptz -- recommended: an absolute instant
);Memorizzare in UTC, convertire ai margini
La regola d'oro. Si memorizzano gli istanti in UTC (usando timestamptz) e si converte in un fuso locale solo quando si presenta il valore a un utente. In questo modo si evitano le ambiguità legate all'ora legale e l'ordinamento temporale è corretto ovunque.
Se viene chiesto "perché UTC?", si può rispondere: UTC non subisce cambiamenti dovuti all'ora legale, quindi lo stesso valore dell'orologio locale non si verifica mai due volte né viene saltato, a differenza dell'ora locale.
-- Display a UTC instant in a user's zone (Postgres)
SELECT occurred_at AT TIME ZONE 'America/New_York' AS local_time
FROM events;Il doppio significato di AT TIME ZONE
AT TIME ZONE è un costrutto ingegnoso e una fonte frequente di errori, perché esegue due operazioni opposte a seconda del tipo dell'input:
- Applicato a un
timestamptz, converte l'istante assoluto nel fuso indicato e restituisce untimestampsemplice, cioè l'ora visualizzata in quel fuso. - Applicato a un
timestampsemplice, interpreta quell'ora locale come appartenente al fuso indicato e restituisce untimestamptz.
Il punto fondamentale è capire in quale direzione opera.
-- timestamptz -> local wall clock (returns timestamp)
SELECT TIMESTAMPTZ '2024-03-01 12:00:00+00'
AT TIME ZONE 'Asia/Tokyo'; -- 2024-03-01 21:00:00
-- plain timestamp interpreted in a zone (returns timestamptz)
SELECT TIMESTAMP '2024-03-01 12:00:00'
AT TIME ZONE 'Asia/Tokyo'; -- 2024-03-01 03:00:00+00Ottenere l'istante corrente
È importante conoscere le funzioni che restituiscono l'istante corrente. NOW() e CURRENT_TIMESTAMP restituiscono un timestamptz in Postgres. Restituiscono l'ora dell'inizio della transazione, non quella dell'istruzione, un aspetto importante nelle transazioni lunghe.
Per ottenere esplicitamente UTC, esegua la conversione: NOW() AT TIME ZONE 'UTC'. In MySQL, UTC_TIMESTAMP() restituisce direttamente l'ora UTC.
SELECT
NOW() AS tx_start_tz,
NOW() AT TIME ZONE 'UTC' AS utc_walltime;L'ora legale è il vero nemico
Chi conduce i colloqui ama i casi limite dell'ora legale. Quando gli orologi avanzano, un'ora dell'orologio locale non esiste; quando tornano indietro, un'ora si ripete. Memorizzare l'ora locale rende questi orari ambigui o non validi.
Memorizzare UTC evita completamente il problema: ogni istante è univoco e monotono. Indicare una regione come 'America/New_York', invece di un offset fisso come -05:00, consente al database di applicare correttamente le regole dell'ora legale per qualsiasi data.
-- Region name applies DST automatically for the given date
SELECT TIMESTAMPTZ '2024-07-01 12:00:00+00'
AT TIME ZONE 'America/New_York' AS summer, -- EDT (-04)
TIMESTAMPTZ '2024-01-01 12:00:00+00'
AT TIME ZONE 'America/New_York' AS winter; -- EST (-05)Raggruppare per giorno locale tra fusi orari
Un problema realistico: «utenti attivi giornalmente nel fuso locale di ciascun utente». Se si tronca direttamente il timestamp UTC, i confini della mezzanotte sono errati per gli utenti che non si trovano in UTC.
Converta il timestamp nel fuso dell'utente prima di troncarlo al giorno. La conversione sposta l'ora locale in modo che i confini del giorno siano allineati localmente.
SELECT
DATE_TRUNC('day', occurred_at AT TIME ZONE u.tz) AS local_day,
COUNT(DISTINCT e.user_id) AS dau
FROM events e
JOIN users u ON u.id = e.user_id
GROUP BY 1
ORDER BY 1;Confrontare i timestamp in sicurezza
Quando si filtra una colonna timestamptz, la si confronti con un istante esplicito, idealmente un valore letterale UTC o un timestamptz con offset. Il confronto con una stringa priva di indicazioni può essere interpretato nel fuso imprevedibile della sessione.
In questo modo il confronto resta non ambiguo, indipendentemente da chi esegue la query.
SELECT *
FROM events
WHERE occurred_at >= TIMESTAMPTZ '2024-03-01 00:00:00+00'
AND occurred_at < TIMESTAMPTZ '2024-04-01 00:00:00+00';Timestamp epoch e Unix
Molti sistemi memorizzano l'ora come Unix epoch, cioè i secondi trascorsi dal 1970-01-01 UTC. In un colloquio potrebbe ricevere una colonna intera e le potrebbe essere chiesto di interpretarla.
- Postgres:
TO_TIMESTAMP(epoch_seconds)restituisce untimestamptz. - Per tornare all'epoch:
EXTRACT(EPOCH FROM occurred_at). - MySQL:
FROM_UNIXTIME()eUNIX_TIMESTAMP().
I valori epoch sono intrinsecamente UTC, anche per questo sono molto usati per la memorizzazione.
SELECT
TO_TIMESTAMP(1709294400) AS as_ts, -- from epoch
EXTRACT(EPOCH FROM NOW())::bigint AS as_epoch; -- to epochNote sui fusi orari tra dialetti
Una mappa rapida per dimostrare padronanza in qualsiasi ambiente:
- Postgres:
timestamptzeAT TIME ZONE, con il supporto più completo. - MySQL:
TIMESTAMPesegue la conversione automatica tramitetime_zonedella sessione;CONVERT_TZ(t, from, to)esegue una conversione esplicita.DATETIMEnon tiene conto del fuso orario. - SQL Server:
datetimeoffsetmemorizza un offset;AT TIME ZONE 'name'converte usando i nomi dei fusi di Windows.
-- MySQL explicit conversion
SELECT CONVERT_TZ(event_dt, 'UTC', 'Europe/Istanbul') AS local_dt
FROM events;Esempio approfondito: sessioni che attraversano la mezzanotte
Una domanda di reporting sottile: contare le sessioni per giorno del calendario locale quando una sessione può attraversare la mezzanotte. La soluzione richiede la stessa disciplina: convertire all'ora locale e poi suddividere in intervalli.
Memorizzi l'inizio e la fine come timestamptz; per il reporting, ricavi il giorno locale dall'inizio convertito. Se una sessione deve essere suddivisa tra due giorni, dovrebbe eseguire un join con una sequenza di giorni, un ottimo punto da sollevare come approfondimento.
SELECT
DATE_TRUNC('day', started_at AT TIME ZONE 'Europe/Istanbul') AS local_day,
COUNT(*) AS sessions
FROM sessions
GROUP BY 1
ORDER BY 1;Verifica rapida
Confermi la strategia di memorizzazione consigliata e la motivazione.
Riepilogo: fusi orari e timestamp
La disciplina da portare con sé:
- Memorizzi UTC come
timestamptz; converta in un fuso denominato solo per la visualizzazione. timestamptzmemorizza un istante UTC, non un fuso orario, nonostante il nome.AT TIME ZONEopera in entrambe le direzioni a seconda del tipo dell'input: converte un timestamptz nell'ora locale oppure interpreta un timestamp semplice come appartenente a un fuso.- Utilizzi nomi di regioni come
'America/New_York', così l'ora legale viene applicata automaticamente; eviti gli offset fissi. - Converta all'ora locale prima di troncare al giorno e confronti le colonne con istanti UTC espliciti.
Domande Frequenti
La lezione «Fusi orari e timestamp» è gratuita?
Sì — il testo completo di «Fusi orari e timestamp» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Coding Interview Prep, passa a CoddyKit PRO. Il corso Coding Interview Prep include 4 lezioni in totale.
Cosa imparerò in «Fusi orari e timestamp»?
Salvataggio in UTC, conversione dei fusi orari e insidie sui timestamp sollevate nei colloqui. Eserciti Coding Interview Prep con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Coding Interview Prep?
Non è richiesta alcuna esperienza precedente. Coding Interview Prep su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Fusi orari e timestamp»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Coding Interview Prep?
Sì. Ogni lezione Coding Interview Prep include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Aritmetica delle date e intervalli
- Troncare e raggruppare le date
- Analizzare e formattare stringhe
- Fusi orari e timestamp