- 1 1. L’SQL più breve per ottenere la data/ora corrente in MySQL
- 1.1 1.1 Ottieni la data/ora corrente (base)
- 1.2 1.2 Ottieni solo la data di oggi
- 1.3 1.3 Ottieni solo l’ora corrente
- 1.4 1.4 Ottieni l’ora corrente in UTC (importante)
- 1.5 1.5 Ottieni millisecondi / microsecondi
- 1.6 1.6 La migliore funzione per caso d’uso (inizia qui se non sei sicuro)
- 1.7 Punti chiave che la gente spesso dimentica
- 2 2. Differenze tra NOW() / CURRENT_TIMESTAMP / SYSDATE()
- 3 3. Modifica il formato di visualizzazione della data/ora corrente
- 4 4. Calcoli datetime usando il tempo corrente
- 4.1 4.1 Aggiungi/sottrai con INTERVAL
- 4.2 4.2 Ottieni dati dalle ultime 24 ore (pattern più comune)
- 4.3 4.3 Ottieni differenze di giorni con DATEDIFF()
- 4.4 4.4 Usa TIMESTAMPDIFF() per ore/minuti/secondi
- 4.5 4.5 Ottieni inizio mese / fine mese (trappola comune nel mondo reale)
- 4.6 Riepilogo errori comuni
- 4.7 Punti chiave di questa sezione
- 5 5. Per query di intervalli, questo è più sicuro di BETWEEN
- 5.1 5.1 Basi di BETWEEN e la trappola
- 5.2 5.2 Pattern più sicuro (raccomandato)
- 5.3 5.3 Il modo corretto per ottenere i dati di oggi
- 5.4 5.4 Modelli sicuri per gli ultimi 7 / ultimi 30 giorni
- 5.5 5.5 Regola chiave per mantenere gli indici efficaci
- 5.6 Riepilogo degli errori comuni
- 5.7 Punti chiave di questa sezione
- 6 6. DEFAULT CURRENT_TIMESTAMP e ON UPDATE (concetti base di progettazione tabelle)
- 6.1 6.1 Impostazione automatica di created_at (DEFAULT CURRENT_TIMESTAMP)
- 6.2 6.2 Aggiornamento automatico di updated_at (ON UPDATE)
- 6.3 6.3 DATETIME vs TIMESTAMP (importante)
- 6.4 6.4 CURRENT_TIMESTAMP può essere usato anche con DATETIME
- 6.5 6.5 Se vuoi usare NOW(): un’alternativa (trigger)
- 6.6 Errori comuni di progettazione
- 6.7 Punti chiave di questa sezione
- 7 7. Progettazione dei fusi orari (memorizzare in UTC, visualizzare in ora locale)
- 7.1 7.1 Verifica il fuso orario corrente
- 7.2 7.2 Cambia il fuso orario per sessione
- 7.3 7.3 Perché memorizzare in UTC (principio pratico)
- 7.4 7.4 Converti i fusi orari con CONVERT_TZ()
- 7.5 7.5 Perché CONVERT_TZ() restituisce NULL
- 7.6 7.6 Cambia il fuso orario a livello di server
- 7.7 Errori comuni
- 7.8 Punti chiave di questa sezione
- 8 8. Esempi pratici pronti all’uso
- 8.1 8.1 Inserire automaticamente l’ora corrente nei log
- 8.2 8.2 Aggiorna l’ora dell’ultimo accesso
- 8.3 8.3 Fissa un tempo di riferimento nei job batch
- 8.4 8.4 Aggregazione per oggi / ieri / ultimi 7 giorni
- 8.5 8.5 Controlli di scadenza (sessioni/token)
- 8.6 8.6 Ottieni righe che scadono entro N ore
- 8.7 Ciò che devi sempre tenere a mente
- 8.8 Punti chiave di questa sezione
- 9 9. Domande Frequenti (FAQ)
- 9.1 9.1 Qual è la differenza tra NOW() e CURRENT_TIMESTAMP?
- 9.2 9.2 Dovresti usare SYSDATE()?
- 9.3 9.3 Perché il tempo è spostato?
- 9.4 9.4 CONVERT_TZ() restituisce NULL
- 9.5 9.5 Spostamenti di intervallo con BETWEEN
- 9.6 9.6 Come scegli tra DATETIME e TIMESTAMP?
- 9.7 9.7 I microsecondi non vengono memorizzati
- 9.8 Punti chiave da questa sezione
- 10 10. Riepilogo
1. L’SQL più breve per ottenere la data/ora corrente in MySQL
Se vuoi ottenere la data/ora corrente in MySQL, le prime funzioni da ricordare sono NOW() e CURRENT_TIMESTAMP. Di seguito trovi gli esempi SQL più brevi per caso d’uso.
1.1 Ottieni la data/ora corrente (base)
SELECT NOW();
or
SELECT CURRENT_TIMESTAMP;
- Entrambi restituiscono la data/ora corrente (YYYY-MM-DD HH:MM:SS).
- All’interno della stessa query, l’ora è fissata al “tempo di inizio della query”.
Casi d’uso
- Log
- Ottenere il timestamp di creazione di un record
- Ottenere un’ora di riferimento
Errore comune
- Il fuso orario dell’app e quello del DB differiscono e si verificano “spostamenti di tempo”. → Verifica con
SELECT @@session.time_zone;
1.2 Ottieni solo la data di oggi
SELECT CURDATE();
- Formato di ritorno:
YYYY-MM-DD - Il tipo è DATE (solo data, non datetime)
Casi d’uso
- Ricerca dei dati “di oggi”
- Aggregazione giornaliera
Note
- A differenza di
NOW(), non include l’ora. - Se ti serve l’ora per query di intervallo, usa
NOW().
1.3 Ottieni solo l’ora corrente
SELECT CURTIME();
- Formato di ritorno:
HH:MM:SS - Il tipo è TIME (solo ora)
Casi d’uso
- Visualizzare il tempo di esecuzione di un batch
- Stampare solo la parte dell’ora nei log
Insidia comune
- Poiché non include una data, non può essere usato per confronti datetime.
1.4 Ottieni l’ora corrente in UTC (importante)
SELECT UTC_TIMESTAMP();
- Restituisce UTC indipendentemente dal fuso orario del server.
- Consigliato per servizi globali.
Politica di base nei progetti reali
- Memorizzare in UTC
- Convertire in ora locale al momento della visualizzazione
Note
- Se l’app converte già in UTC, attenzione alla doppia conversione.
1.5 Ottieni millisecondi / microsecondi
SELECT NOW(3); -- milliseconds (3 digits after the decimal point)
SELECT NOW(6); -- microseconds (6 digits after the decimal point)
- Disponibile in MySQL 5.6.4 e successive.
- Usato per log ad alta precisione e audit delle transazioni.
Idea sbagliata comune
NOW()da solo non può restituire secondi frazionari.- Anche la tua colonna deve specificare la precisione, ad es.
DATETIME(6).
1.6 La migliore funzione per caso d’uso (inizia qui se non sei sicuro)
| Use case | Recommended function |
|---|---|
| General current datetime | NOW() |
| Table default value | CURRENT_TIMESTAMP |
| Date only | CURDATE() |
| Time only | CURTIME() |
| Unified UTC management | UTC_TIMESTAMP() |
| High-precision logs | NOW(6) |
Punti chiave che la gente spesso dimentica
NOW()eCURRENT_TIMESTAMPsono effettivamente equivalenti (stesso valore)- All’interno della stessa query, l’ora è fissata
- Il valore visualizzato cambia a seconda delle impostazioni del fuso orario
- Per i microsecondi, la definizione della tua colonna deve specificare la precisione
2. Differenze tra NOW() / CURRENT_TIMESTAMP / SYSDATE()
Esistono diverse funzioni per ottenere l’ora corrente, ma la parte più confusa è la differenza tra NOW(), CURRENT_TIMESTAMP e SYSDATE().
Se non la comprendi correttamente, potresti ottenere comportamenti inattesi nei log e nell’elaborazione delle transazioni.
2.1 NOW() e CURRENT_TIMESTAMP sono effettivamente equivalenti
SELECT NOW(), CURRENT_TIMESTAMP;
- Entrambi restituiscono il datetime corrente (un valore DATETIME).
- All’interno della stessa query, l’ora è fissata al “tempo di inizio della query”.
CURRENT_TIMESTAMPpuò anche essere usato con la sintassi di chiamata funzione:SELECT CURRENT_TIMESTAMP();
Come scegliere nei progetti reali
| Use case | Recommended |
|---|---|
| Simple retrieval | NOW() |
| Table DEFAULT / ON UPDATE | CURRENT_TIMESTAMP |
Punti importanti
- Il significato del valore recuperato è lo stesso.
- La differenza principale è nella sintassi/uso (ad es., consentito in DEFAULT).
- Non è una differenza di tipo (facile da fraintendere).
2.2 SYSDATE() restituisce l’ora al “tempo di valutazione”
SYSDATE() sembra simile a NOW(), ma il momento in cui il valore viene fissato è diverso.
SELECT NOW(), SLEEP(2), NOW();
Risultato (esempio):
2025-02-23 14:00:00
2025-02-23 14:00:00
SELECT SYSDATE(), SLEEP(2), SYSDATE();
Risultato (esempio):
2025-02-23 14:00:00
2025-02-23 14:00:02
La differenza fondamentale
| Function | When the time is fixed |
|---|---|
NOW() | Query start time |
SYSDATE() | Evaluation time |
In altre parole, SYSDATE() può cambiare all’interno della stessa query man mano che il tempo avanza.
2.3 Note per le transazioni e la replica
Poiché NOW() è fissato all’inizio della query, è
più sicuro quando hai bisogno di un tempo di riferimento coerente all’interno di una transazione.
D’altra parte, poiché SYSDATE() dipende dal timing di esecuzione, può influire sulla riproducibilità in:
- Replica
- Lavori batch
- Elaborazione di log in blocco
Regola pratica
- Vuoi un tempo di riferimento fisso →
NOW() - Hai bisogno dell’istante esatto ogni volta →
SYSDATE()(uso limitato)
2.4 Nota: CURRENT_DATE / CURRENT_TIME / LOCALTIME
MySQL supporta anche:
SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT LOCALTIME;
CURRENT_DATE→ uguale aCURDATE()CURRENT_TIME→ uguale aCURTIME()LOCALTIME→ uguale aNOW()
Confusione comune
- Queste sono per lo più “differenze cosmetiche”; c’è poca differenza funzionale.
- Per sicurezza, dai priorità alla leggibilità e standardizza all’interno del progetto.
Punti chiave di questa sezione
NOW()eCURRENT_TIMESTAMPsignificano essenzialmente la stessa cosa.SYSDATE()si comporta diversamente perché si basa sul tempo di valutazione.- Per tempi di riferimento fissi, usa
NOW()come predefinito. - Usa
CURRENT_TIMESTAMPper DEFAULT e ON UPDATE.
3. Modifica il formato di visualizzazione della data/ora corrente
Il tempo corrente ottenuto con NOW() viene visualizzato per impostazione predefinita come YYYY-MM-DD HH:MM:SS. Nel lavoro reale, avrai spesso bisogno di cose come:
- Mostrare solo la data
- Usare
YYYY/MM/DD - Usare un formato localizzato (es., 23 feb 2025)
- Mostrare i millisecondi
Per questo, usa DATE_FORMAT() (converti un datetime in un formato stringa arbitrario).
3.1 Sintassi di base di DATE_FORMAT()
DATE_FORMAT(datetime, 'format_string')
Esempio: Converti il tempo corrente in YYYY/MM/DD HH:MM
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i');
Esempio di output:
2025/02/23 14:35
Specificatori di formato comuni
| Specifier | Meaning | Example |
|---|---|---|
%Y | 4-digit year | 2025 |
%m | 2-digit month | 02 |
%d | 2-digit day | 23 |
%H | Hour (24-hour) | 14 |
%i | Minutes | 35 |
%s | Seconds | 50 |
%f | Microseconds | 123456 |
Note
- Alcuni specificatori differiscono tra maiuscole e minuscole.
%hè il formato a 12 ore,%Hè il formato a 24 ore.
3.2 Esempi di formato comuni (frequenti nel lavoro reale)
1. Separato da slash
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d');
2. Localizzato (Inglese)
SELECT DATE_FORMAT(NOW(), '%b %d, %Y');
3. Senza secondi
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');
Trappola comune
- Poiché restituisce una stringa, non puoi usarla per calcoli numerici.
- Per confronti e ricerche, dovresti usare il tipo DATETIME originale.
3.3 Estrai solo la parte data o ora
Puoi anche recuperare le parti mantenendo il tipo (invece di formattare in una stringa).
SELECT DATE(NOW()); -- date only (DATE type)
SELECT TIME(NOW()); -- time only (TIME type)
SELECT YEAR(NOW()); -- year only
SELECT MONTH(NOW()); -- month only
SELECT DAY(NOW()); -- day only
Uso consigliato
| Goal | Recommended |
|---|---|
| Formatting for display | DATE_FORMAT |
| Calculation / comparison | DATE() / TIME() |
3.4 Visualizza con microsecondi
Quando hai bisogno di log ad alta precisione:
SELECT NOW(6);
Con formattazione:
SELECT DATE_FORMAT(NOW(6), '%Y-%m-%d %H:%i:%s.%f');
Note importanti
- La tua colonna deve essere
DATETIME(6)oTIMESTAMP(6), altrimenti la precisione non verrà memorizzata. - Non disponibile nelle versioni di MySQL precedenti alla 5.6.4 (dipendente dall’ambiente).
Errori comuni
Usare
DATE_FORMAT()in una clausola WHERE impedisce l’uso degli indici. wp:list /wp:list- Esempio errato:
WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-23' - Consigliato:
WHERE created_at >= '2025-02-23 00:00:00' AND created_at < '2025-02-24 00:00:00' - Memorizzare direttamente la stringa formattata per la visualizzazione (danneggia le prestazioni di ricerca)
- Esempio errato:
Punti chiave di questa sezione
- Usa
DATE_FORMAT()per cambiare i formati di visualizzazione. - Per calcoli/confronti, mantieni il tipo originale.
- Se hai bisogno di microsecondi, specifica la precisione nella definizione della colonna.
- Usare funzioni nelle clausole WHERE può causare problemi di prestazioni.
4. Calcoli datetime usando il tempo corrente
In MySQL, è comune calcolare cose come “N ore dopo”, “N giorni fa” o “gli ultimi N giorni” basati sull’ora corrente.
Il caso più comune nel mondo reale è “ottenere dati dalle ultime 24 ore.”
La base dell’aritmetica delle date e ore è INTERVAL (sintassi per aggiungere/sottrarre unità di tempo).
4.1 Aggiungi/sottrai con INTERVAL
Ottieni 1 ora dopo
SELECT NOW() + INTERVAL 1 HOUR;
Ottieni 3 giorni fa
SELECT NOW() - INTERVAL 3 DAY;
Ottieni 1 mese dopo
SELECT NOW() + INTERVAL 1 MONTH;
Unità comuni
| Unit | Meaning |
|---|---|
| SECOND | Seconds |
| MINUTE | Minutes |
| HOUR | Hours |
| DAY | Days |
| WEEK | Weeks |
| MONTH | Months |
| YEAR | Years |
Errori comuni
DAYinINTERVAL 1 DAYfunziona anche in minuscolo, ma dovresti standardizzare all’interno del team.- I calcoli di fine mese possono differire dalle aspettative perché il numero di giorni varia (ad es., 31 gen + 1 mese).
4.2 Ottieni dati dalle ultime 24 ore (pattern più comune)
SELECT *
FROM users
WHERE created_at >= NOW() - INTERVAL 1 DAY;
Significato
- Punta a “dal momento attuale indietro di 24 ore.”
Note
- Se usi
CURDATE(), la baseline diventa “oggi alle 00:00”, che cambia il significato.
Esempio (dati di oggi):
SELECT *
FROM users
WHERE created_at >= CURDATE();
Comprendere la differenza è critico
| Expression | Meaning |
|---|---|
NOW() - INTERVAL 1 DAY | Past 24 hours |
CURDATE() | Since today 00:00 |
4.3 Ottieni differenze di giorni con DATEDIFF()
SELECT DATEDIFF('2025-03-01', '2025-02-23');
Risultato:
6
- L’unità è “giorni”
- La parte oraria viene ignorata
Note
- Il segno cambia a seconda dell’ordine degli argomenti.
- Non puoi calcolare differenze in ore/minuti/secondi.
4.4 Usa TIMESTAMPDIFF() per ore/minuti/secondi
SELECT TIMESTAMPDIFF(HOUR,
'2025-02-23 12:00:00',
'2025-02-23 18:30:00');
Risultato:
6
Minuti
SELECT TIMESTAMPDIFF(MINUTE,
'2025-02-23 12:00:00',
'2025-02-23 12:30:00');
Secondi
SELECT TIMESTAMPDIFF(SECOND,
'2025-02-23 12:00:00',
'2025-02-23 12:00:45');
Casi d’uso
- Calcoli di durata sessione
- Controlli di scadenza
- Decisioni di timeout
4.5 Ottieni inizio mese / fine mese (trappola comune nel mondo reale)
Ottieni il primo giorno di questo mese:
SELECT DATE_FORMAT(NOW(), '%Y-%m-01');
Primo giorno del mese successivo:
SELECT DATE_FORMAT(NOW() + INTERVAL 1 MONTH, '%Y-%m-01');
Note
- La fine mese non è una data fissa.
- Per query di intervalli, “>= inizio AND < primo giorno del mese successivo” è sicuro.
Riepilogo errori comuni
- Usare
BETWEENcon valori di data-only e dimenticare l’ora - Disabilitare gli indici usando
DATE(created_at)nelle clausole WHERE - Cadere nella trappola del “giorno 31” nei calcoli mensili
- Fraintendere la differenza tra
NOW()eCURDATE()
Punti chiave di questa sezione
INTERVALè la base dell’aritmetica delle date e ore.- Ultime 24 ore =
NOW() - INTERVAL 1 DAY. - Giorni =
DATEDIFF(); unità più piccole =TIMESTAMPDIFF(). - Sii attento con le condizioni di fine per i calcoli basati su mesi.
5. Per query di intervalli, questo è più sicuro di BETWEEN
Quando si eseguono ricerche di intervalli di date in MySQL, molti principianti usano BETWEEN. Tuttavia, spesso produce risultati non intenzionali se non gestisci correttamente i confini temporali, quindi un pattern più sicuro è raccomandato nel lavoro reale.
5.1 Basi di BETWEEN e la trappola
Una query comune
SELECT *
FROM orders
WHERE order_date BETWEEN '2025-02-01' AND '2025-02-10';
Sembra a posto, ma internamente è equivalente a:
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date <= '2025-02-10 00:00:00'
Quindi non include dati dopo le 00:00 del 10 feb.
5.2 Pattern più sicuro (raccomandato)
Pattern raccomandato
SELECT *
FROM orders
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date < '2025-02-11 00:00:00';
Punti chiave
- Specificare il limite finale come “meno del giorno successivo alle 00:00”
- Più sicuro di
<= 23:59:59(supporta i microsecondi)
5.3 Il modo corretto per ottenere i dati di oggi
Esempio errato:
WHERE DATE(created_at) = CURDATE();
Problemi:
- Applicare una funzione alla colonna disabilita gli indici
- Può causare rallentamenti seri su tabelle grandi
Consigliato:
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
Questo assicura:
- Gli indici possono essere usati
- Ricerche veloci
- Nessun problema di limiti
5.4 Modelli sicuri per gli ultimi 7 / ultimi 30 giorni
Ultimi 7 giorni
WHERE created_at >= NOW() - INTERVAL 7 DAY;
Ultimi 30 giorni
WHERE created_at >= NOW() - INTERVAL 30 DAY;
Note
CURDATE() - INTERVAL 7 DAYsi basa su “oggi 00:00”NOW() - INTERVAL 7 DAYsi basa su “ora corrente”- Scegliere in base ai requisiti
5.5 Regola chiave per mantenere gli indici efficaci
Errato:
WHERE DATE(created_at) = '2025-02-23';
Corretto:
WHERE created_at >= '2025-02-23 00:00:00'
AND created_at < '2025-02-24 00:00:00';
Perché:
- Gli indici funzionano sulla “colonna stessa”
- Applicare una funzione impedisce l’uso dell’indice (scansione completa)
Riepilogo degli errori comuni
- Dimenticare di includere l’ora nel limite finale in
BETWEEN - Mancare i microsecondi quando si usa
23:59:59 - Usare
DATE()nelle clausole WHERE rallentando le query - Lasciare ambigua la differenza tra “now” e “today 00:00”
Punti chiave di questa sezione
- Le query di intervallo sono più sicure con
>= start AND < end. BETWEENrichiede una gestione attenta dei limiti.- Per mantenere gli indici efficaci, non avvolgere le colonne in funzioni.
- Scegliere chiaramente tra logica basata su
NOW()e logica basata suCURDATE().
6. DEFAULT CURRENT_TIMESTAMP e ON UPDATE (concetti base di progettazione tabelle)
Nella progettazione di database, è comune gestire automaticamente created_at e updated_at.
In MySQL, CURRENT_TIMESTAMP consente di impostare automaticamente l’ora corrente durante l’inserimento e l’aggiornamento.
6.1 Impostazione automatica di created_at (DEFAULT CURRENT_TIMESTAMP)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Comportamento:
INSERT INTO users (name) VALUES ('Alice');
→ L’ora corrente viene inserita automaticamente in created_at.
Punti chiave
CURRENT_TIMESTAMPpuò essere usato in DEFAULT.NOW()non può essere usato direttamente in DEFAULT.
Errore comune
created_at DATETIME DEFAULT NOW(); -- error
Motivo:
- In MySQL, generalmente non è possibile impostare una funzione come DEFAULT (l’eccezione è CURRENT_TIMESTAMP).
6.2 Aggiornamento automatico di updated_at (ON UPDATE)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
Comportamento:
UPDATE users SET name = 'Bob' WHERE id = 1;
→ updated_at viene aggiornato automaticamente all’ora corrente.
Casi d’uso
- Tracciamento ultimo accesso
- Cronologia aggiornamenti
- Log di audit
6.3 DATETIME vs TIMESTAMP (importante)
| Type | Range | Time zone impact |
|---|---|---|
| DATETIME | Year 1000 to 9999 | No |
| TIMESTAMP | 1970 to 2038 | Yes |
La differenza essenziale
TIMESTAMPè memorizzato internamente in UTC e convertito al fuso orario della sessione al momento della visualizzazione.DATETIMEmemorizza il valore letterale (senza conversione).
Linee guida
| Case | Recommended type |
|---|---|
| Log management | TIMESTAMP |
| Future dates (after 2038) | DATETIME |
| Fixed values not requiring TZ conversion | DATETIME |
6.4 CURRENT_TIMESTAMP può essere usato anche con DATETIME
In MySQL 5.6 e successive, è possibile specificare CURRENT_TIMESTAMP come DEFAULT e ON UPDATE anche per le colonne DATETIME.
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
Note
- Le versioni MySQL più vecchie hanno restrizioni (dipendenti dall’ambiente).
- Se serve precisione:
DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)
6.5 Se vuoi usare NOW(): un’alternativa (trigger)
CREATE TRIGGER set_created_at
BEFORE INSERT ON logs
FOR EACH ROW
SET NEW.created_at = NOW();
Casi d’uso
- Logica complessa di valore iniziale
- Assegnazione condizionale di timestamp
Note
- I trigger sono difficili da debug.
- Evitali a meno che non siano necessari.
Errori comuni di progettazione
- Aggiungere ON UPDATE sia a
created_atche aupdated_at - Confondere il comportamento di DATETIME e TIMESTAMP
- Rimandare le decisioni sui fusi orari
Punti chiave di questa sezione
- Usa
CURRENT_TIMESTAMPper DEFAULT. - Usa
ON UPDATE CURRENT_TIMESTAMPper il tracciamento degli aggiornamenti. - Scegli i tipi in base al comportamento dei fusi orari e al problema del 2038.
- Se ti serve precisione, non dimenticare
(6).
7. Progettazione dei fusi orari (memorizzare in UTC, visualizzare in ora locale)
Quando si gestisce l’ora corrente, una cattiva progettazione del fuso orario causa deriva temporale e doppia conversione.
In pratica, l’impostazione predefinita più sicura è “memorizzare in UTC, convertire in ora locale per la visualizzazione.”

Figura: Architettura di base per memorizzare UTC in MySQL e visualizzare l’ora locale
7.1 Verifica il fuso orario corrente
Prima, verifica quale fuso orario sta usando MySQL.
SELECT @@global.time_zone, @@session.time_zone;
@@global.time_zone→ impostazione a livello di server@@session.time_zone→ impostazione della connessione/sessione corrente- Se mostra
SYSTEM, dipende dall’impostazione del sistema operativo
Problemi comuni
- I server di produzione e sviluppo hanno fusi orari OS diversi
- L’app converte in UTC e il DB converte di nuovo (doppia conversione)
7.2 Cambia il fuso orario per sessione
SET time_zone = 'Asia/Tokyo';
o uniformare a UTC:
SET time_zone = '+00:00';
Punti importanti
- Torna allo stato precedente quando la connessione è chiusa
- Se usi il pooling delle connessioni, controlla le impostazioni dell’applicazione
7.3 Perché memorizzare in UTC (principio pratico)
Politica consigliata
- Memorizzare i dati in UTC
- Convertire nel fuso orario dell’utente al momento della visualizzazione
Motivi:
- Supporto internazionale più semplice
- Evitare problemi di ora legale (DST)
- Minimizzare l’impatto quando si spostano i server
Ottieni UTC:
SELECT UTC_TIMESTAMP();
7.4 Converti i fusi orari con CONVERT_TZ()
Esempio: UTC → JST
SELECT CONVERT_TZ('2025-02-23 05:35:00', '+00:00', '+09:00');
Usando i nomi dei fusi orari:
SELECT CONVERT_TZ('2025-02-23 05:35:00', 'UTC', 'Asia/Tokyo');
Esempio pratico
SELECT CONVERT_TZ(created_at, 'UTC', 'Asia/Tokyo')
FROM users;
7.5 Perché CONVERT_TZ() restituisce NULL
Se restituisce NULL, le cause comuni includono:
- Le tabelle dei fusi orari di MySQL non sono caricate
- Il nome del fuso orario specificato non esiste
Esempio di caricamento su Linux:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Note
- In produzione, conferma i permessi e se è necessario un riavvio
- In Docker, zoneinfo potrebbe non essere incluso a seconda dell’immagine
7.6 Cambia il fuso orario a livello di server
File di configurazione (my.cnf / my.ini):
[mysqld]
default_time_zone = '+00:00'
Verifica dopo il riavvio:
SELECT @@global.time_zone;
Importante
- Per modifiche in produzione, conferma l’ambito di impatto
- Fai attenzione ai dati esistenti (a volte cambiano solo le visualizzazioni)
Errori comuni
- Memorizzare l’ora locale invece di UTC, poi aggiungere il supporto internazionale in seguito
- Doppia conversione tra l’app e il DB
- Progettare con DATETIME senza considerare i fusi orari
- Impostazioni TZ diverse tra test e produzione
Punti chiave di questa sezione
- Memorizzare in UTC e convertire al momento della visualizzazione.
- Usa
UTC_TIMESTAMP(). - Quando usi
CONVERT_TZ(), verifica le tabelle TZ. - Considera sempre le differenze ambientali nei fusi orari.
8. Esempi pratici pronti all’uso
Ecco esempi SQL concreti che mostrano come usare l’ora corrente di MySQL nello sviluppo/operazioni reali.
Sono scritti in modo da poter copiare e incollare direttamente.
8.1 Inserire automaticamente l’ora corrente nei log
Crea tabella
CREATE TABLE system_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
level VARCHAR(50),
message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Inserisci log
INSERT INTO system_logs (level, message)
VALUES ('ERROR', 'Failed to connect to the DB');
Punti chiave
created_atviene inserito automaticamente- Non è necessario passare un timestamp dall’app
- Progettazione essenziale per audit e indagine di incidenti
Errori comuni
- Gestire il tempo sia nell’app che nel DB
- Incoerenze temporali dovute a fusi orari non unificati
8.2 Aggiorna l’ora dell’ultimo accesso
Progettazione della tabella
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
Aggiornamento al login
UPDATE users
SET last_login = NOW()
WHERE id = 1;
Note
ON UPDATEsi attiva solo quando la colonna cambia- Alcune istruzioni UPDATE potrebbero non modificare il valore e quindi non aggiornare
8.3 Fissa un tempo di riferimento nei job batch
Per processi a lunga esecuzione, è più sicuro fissare un tempo di riferimento.
SET @base_time = NOW();
SELECT *
FROM orders
WHERE created_at >= @base_time - INTERVAL 1 DAY;
Perché
- Il tempo non cambia a metà processo
- La coerenza è mantenuta
8.4 Aggregazione per oggi / ieri / ultimi 7 giorni
Vendite di oggi
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
Vendite di ieri
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE() - INTERVAL 1 DAY
AND created_at < CURDATE();
Ultimi 7 giorni
SELECT COUNT(*)
FROM users
WHERE created_at >= NOW() - INTERVAL 7 DAY;
Importante
- Non applicare funzioni alle colonne nelle clausole WHERE
- Scrivi condizioni che mantengano gli indici utilizzabili
8.5 Controlli di scadenza (sessioni/token)
SELECT *
FROM sessions
WHERE expires_at > NOW();
Elimina righe scadute
DELETE FROM sessions
WHERE expires_at <= NOW();
Errori comuni
- Usare
CURDATE()ignorando l’ora - Memorizzare in UTC ma confrontare con
NOW()locale
8.6 Ottieni righe che scadono entro N ore
SELECT *
FROM coupons
WHERE expires_at <= NOW() + INTERVAL 1 HOUR;
Casi d’uso:
- Avvisi di scadenza
- Notifiche di scadenza
Ciò che devi sempre tenere a mente
- Sii esplicito se la tua base temporale è “now” o “oggi 00:00”
- Scrivi predicati che mantengano gli indici efficaci
- Decidi il design del fuso orario in anticipo
- Non mescolare
NOW()eUTC_TIMESTAMP()senza una politica chiara
Punti chiave di questa sezione
- Per log/audit/tracciamento degli aggiornamenti, usa
CURRENT_TIMESTAMP - Per aggregazione, usa il pattern sicuro
>= AND < - Per la gestione delle sessioni, confronta con
NOW() - Fissa un tempo di base per mantenere il processo coerente
9. Domande Frequenti (FAQ)
Ecco le domande comuni sul tempo corrente di MySQL, soprattutto le insidie che emergono nel lavoro reale.
9.1 Qual è la differenza tra NOW() e CURRENT_TIMESTAMP?
Conclusione: il significato del valore restituito è lo stesso.
SELECT NOW(), CURRENT_TIMESTAMP;
Entrambi restituiscono la data e ora corrente.
La principale differenza è l’uso sintattico
CURRENT_TIMESTAMPpuò essere usato inDEFAULTeON UPDATENOW()non può essere usato direttamente inDEFAULT
Note
- Non è una differenza di tipo
- Puoi specificare la precisione con argomenti come
(6)
9.2 Dovresti usare SYSDATE()?
SYSDATE() restituisce il tempo al “momento di valutazione”.
SELECT SYSDATE(), SLEEP(2), SYSDATE();
Il valore può cambiare anche all’interno della stessa query.
Quando usarlo
- Quando hai bisogno di registrare l’esatto istante reale
Quando evitarlo
- Replicazione
- Elaborazione di transazioni dove la coerenza è importante
Nella maggior parte dei casi, usare NOW() è sufficiente.
9.3 Perché il tempo è spostato?
Cause principali:
- Impostazioni del fuso orario del server
- Impostazioni del fuso orario della sessione
- Conversione doppia con l’applicazione
- Comportamento di conversione automatica del tipo TIMESTAMP
Verifica con:
SELECT @@global.time_zone, @@session.time_zone;
Mitigazione
- Memorizza in UTC per impostazione predefinita
- Converti solo durante la visualizzazione
- Unifica la policy tra app e DB
9.4 CONVERT_TZ() restituisce NULL
Cause:
- Le tabelle dei fusi orari non sono caricate
- Nome del fuso orario errato
Correzione:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Sii particolarmente attento negli ambienti Docker.
9.5 Spostamenti di intervallo con BETWEEN
Cattivo:
WHERE created_at BETWEEN '2025-02-01' AND '2025-02-10';
Sicuro:
WHERE created_at >= '2025-02-01 00:00:00'
AND created_at < '2025-02-11 00:00:00';
Motivi:
- Problema di tempo al confine finale
- Perdita di microsecondi
- Efficienza degli indici
9.6 Come scegli tra DATETIME e TIMESTAMP?
- Supporto internazionale / gestione UTC → TIMESTAMP
- Dopo il 2038 o datetime fissi → DATETIME
Decidi questo durante la progettazione.
9.7 I microsecondi non vengono memorizzati
Causa:
- Nessuna precisione specificata nella definizione della colonna
Correzione:
created_at DATETIME(6)
Punti chiave da questa sezione
- Inizia con
NOW()eCURRENT_TIMESTAMP - Per le query di intervallo, usa
>= AND < - L’archiviazione UTC è l’impostazione predefinita più sicura
- Non dimenticare la selezione del tipo e la precisione
10. Riepilogo
Questo articolo ha organizzato modi pratici per recuperare, formattare, calcolare e gestire l’ora corrente in MySQL.
Infine, ecco i essenziali minimi che dovresti sapere per rimanere al sicuro.
10.1 Ottenere l’ora corrente (basi)
- Recupero generale →
NOW() - DEFAULT della tabella / tracciamento aggiornamenti →
CURRENT_TIMESTAMP - Solo data →
CURDATE() - Solo ora →
CURTIME() - UTC →
UTC_TIMESTAMP() - Alta precisione →
NOW(6)
Regole empiriche
- Se non sei sicuro, usare
NOW()va bene nella maggior parte dei casi. - Per la progettazione dello schema, usa
CURRENT_TIMESTAMP.
10.2 Query di intervallo: “>= AND <” è la regola d’oro
Pattern sicuro:
WHERE created_at >= 'START'
AND created_at < 'END'
Perché:
- Previene la perdita di righe al confine finale
- Funziona con i microsecondi
- Mantiene gli indici utilizzabili
Esempio cattivo
WHERE DATE(created_at) = CURDATE();
Non avvolgere la colonna in una funzione.
10.3 Basi dell’aritmetica datetime
- Aggiungi/sottrai →
INTERVAL - Differenze di giorni →
DATEDIFF() - Differenze di tempo →
TIMESTAMPDIFF()
Tieni sempre a mente se la tua baseline è “ora” o “oggi 00:00.”
10.4 Principi di progettazione dei fusi orari
- Memorizza in UTC
- Converti durante la visualizzazione
- Unifica la policy tra app e DB
Verifica con:
SELECT @@global.time_zone, @@session.time_zone;
10.5 Migliori pratiche per la progettazione delle tabelle
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
- Attrezzatura standard per auditing/logging/tracciamento aggiornamenti
- Se hai bisogno di precisione, specifica
(6)
I 4 punti più importanti nel mondo reale
- Non fraintendere la differenza tra
NOW()eCURRENT_TIMESTAMP - Per le query di intervallo, usa
>= AND < - Memorizza in UTC per impostazione predefinita
- Decidi i tipi (DATETIME vs TIMESTAMP) durante la progettazione
La gestione dell’ora corrente in MySQL è fondamentale per logging, aggregazione vendite, gestione auth/sessione, job batch e altro.
Se segui i principi in questo articolo, puoi evitare molti problemi comuni come deriva temporale, bug ai confini e degradazione delle prestazioni.


