Ora corrente in MySQL: NOW(), CURDATE(), UTC_TIMESTAMP(), Fusi orari e migliori pratiche

目次

1. Ottenere l’ora corrente in MySQL (In sintesi: la cheat sheet SQL più breve)

Se vuoi ottenere l’ora corrente in MySQL, ci sono solo poche funzioni SQL da ricordare.
Di seguito trovi la risposta più breve per la parola chiave di ricerca “MySQL get current time”.

1.1 Data e ora corrente in MySQL: NOW() / CURRENT_TIMESTAMP

Restituisce la data + ora corrente (YYYY-MM-DD HH:MM:SS).

SELECT NOW();
SELECT CURRENT_TIMESTAMP;

Esempio di output

2025-02-01 15:30:45
  • NOW() e CURRENT_TIMESTAMP di solito restituiscono lo stesso risultato.
  • Entrambi restituiscono la data e l’ora correnti.
  • Se hai bisogno dei millisecondi, usa il seguente.
    SELECT NOW(3);
    

Note (errori comuni)

  • Dipende dall’impostazione del fuso orario del server.
  • In un ambiente UTC, potresti ottenere UTC invece dell’ora giapponese.
  • Durante l’esecuzione della query, restituisce sostanzialmente la stessa ora (fissata all’interno di una singola istruzione).

1.2 Data corrente in MySQL: CURDATE()

Restituisce solo la data (senza ora).

SELECT CURDATE();

Esempio di output

2025-02-01

Casi d’uso

  • Interrogare i dati di oggi
  • Confronti di date (es., filtrare solo i record di oggi)

Note

  • Il valore restituito è di tipo DATE.
  • Non adatto quando è necessario gestire l’ora del giorno.

1.3 Ora corrente in MySQL: CURTIME()

Restituisce solo l’ora.

SELECT CURTIME();

Esempio di output

15:30:45

Casi d’uso

  • Verifica degli orari di lavoro
  • Logica di ramificazione per finestra temporale

Note

  • Non include informazioni sulla data.
  • Non può essere usato per confronti con colonne di tipo DATE.

1.4 Ora UTC corrente in MySQL: UTC_TIMESTAMP()

Restituisce l’ora in UTC (Coordinated Universal Time), indipendentemente dall’impostazione del fuso orario del server.

SELECT UTC_TIMESTAMP();

Esempio di output

2025-02-01 06:30:45

Quando dovresti usarlo

  • Servizi globali
  • Progettazioni che memorizzano i log in UTC in modo coerente

Errori comuni

  • Mescolarlo con NOW() provoca offset temporali
  • Se l’app presume JST, vedrai una differenza di 9 ore

1.5 Ora corrente in MySQL con millisecondi: NOW(3) / CURRENT_TIMESTAMP(3)

MySQL 5.6 e versioni successive supportano i secondi frazionari.

SELECT NOW(3);
SELECT CURRENT_TIMESTAMP(3);

Esempio di output

2025-02-01 15:30:45.123

Note per la memorizzazione

La tua colonna deve supportare anche i secondi frazionari.

DATETIME(3)
TIMESTAMP(3)

Se lo memorizzi in una colonna non supportata, la parte frazionaria verrà troncata.

1.6 Cheat sheet rapida per scopo

PurposeSQL
Current date and timeSELECT NOW();
Get UTCSELECT UTC_TIMESTAMP();
Date onlySELECT CURDATE();
Time onlySELECT CURTIME();
Get millisecondsSELECT NOW(3);

Riepilogo dei problemi comuni

  • L’ora è offset perché non hai verificato il fuso orario
  • Usare NOW(3) senza una colonna che supporti i millisecondi
  • Mescolare UTC e ora locale
  • Non comprendere la differenza tra DATETIME e TIMESTAMP

MySQL DATETIME と TIMESTAMP の違いを示した図。TIMESTAMPはUTC変換され、DATETIMEは変換されない。

Differenza tra MySQL DATETIME e TIMESTAMP (confronto se avviene la conversione del fuso orario)

2. Differenze tra MySQL NOW() e CURRENT_TIMESTAMP

NOW() e CURRENT_TIMESTAMP sembrano simili, ma non comprendere dove usarli e come si comportano può facilmente causare bug. Qui organizziamo le differenze, l’uso corretto e le insidie comuni.

2.1 Quale dovresti usare? (uso in SELECT / uso in DEFAULT)

■ Quando si recupera la data/ora corrente in SELECT

SELECT NOW();
SELECT CURRENT_TIMESTAMP;

Normalmente, entrambi restituiscono lo stesso risultato.

  • Sono equivalenti (sinonimi)
  • Il valore restituito è equivalente a DATETIME
  • Influenzato dall’impostazione del fuso orario

Considerazione pratica

  • Preferisci la leggibilità → NOW()
  • Preferisci lo stile SQL standard → CURRENT_TIMESTAMP

■ Quando si imposta un valore di default per una colonna

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Il punto chiave qui è:

Per un valore di default, è comune usare CURRENT_TIMESTAMP.

Alcuni ambienti consentono anche NOW(), ma il comportamento può differire a seconda della versione di MySQL e della modalità SQL. La scelta più sicura è CURRENT_TIMESTAMP.

2.2 Uso corretto di DEFAULT / ON UPDATE

Se vuoi aggiornare automaticamente un timestamp “updated at”:

CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        ON UPDATE CURRENT_TIMESTAMP
);

Comportamento

  • In INSERT → imposta l’ora corrente per created_at / updated_at
  • In UPDATE → aggiorna solo updated_at

Errori comuni

  • Non corrispondere alla precisione frazionaria dei secondi quando si usa DATETIME
  • Incontrare le limitazioni delle versioni più vecchie di MySQL con più colonne TIMESTAMP (MySQL 5.6 e precedenti avevano restrizioni)

2.3 Differenze tra NOW() e SYSDATE() (Importante)

Il punto facile da trascurare è la differenza rispetto a SYSDATE().

SELECT NOW(), SYSDATE();

■ Differenze di comportamento

  • NOW() → fissato all’inizio della query
  • SYSDATE() → restituisce l’ora al momento della chiamata

Esempio:

SELECT NOW(), SLEEP(3), NOW();

NOW() restituisce lo stesso valore.

SELECT SYSDATE(), SLEEP(3), SYSDATE();

SYSDATE() mostra una differenza di 3 secondi.

2.4 Quale dovresti usare?

FunctionBehaviorRecommended use
NOW()Fixed within a queryLogging, consistency-focused
SYSDATE()Call-time valuePrecise real-time retrieval

Perché NOW() è spesso consigliato nei sistemi reali

  • Mantiene la coerenza all’interno di una transazione (un meccanismo che elabora più istruzioni SQL insieme)
  • Più sicuro negli ambienti di replica

2.5 Malintesi comuni e problemi

❌ “NOW() e CURRENT_TIMESTAMP sono esattamente gli stessi, quindi non c’è bisogno di pensarci.”

→ Le differenze possono emergere nei valori di default o nel comportamento di aggiornamento, a seconda dell’ambiente.

❌ “SYSDATE() è più accurato, quindi è sempre migliore.”

→ Può causare problemi negli ambienti di replica.

❌ Non verificare il fuso orario

SHOW VARIABLES LIKE '%time_zone%';

Se lo usi senza controllare, potresti ottenere scostamenti temporali.

2.6 Best practice pratiche

  • Recupero con SELECT → NOW()
  • Default della colonna → CURRENT_TIMESTAMP
  • Aggiornamento automatico → ON UPDATE CURRENT_TIMESTAMP
  • Focalizzato sulla coerenza → default a NOW()
  • Progettazione basata su UTC → TIMESTAMP + memorizzare in UTC
  1. Formattazione dell’ora corrente in MySQL (DATE_FORMAT / TIME_FORMAT)
    Dopo aver recuperato l’ora corrente in MySQL, è molto comune modificare il formato di visualizzazione.
    Per l’intento di ricerca “MySQL current time format”, la funzione più importante da capire è DATE_FORMAT().

3.1 Formattazione datetime MySQL: DATE_FORMAT(NOW(), …)

Sintassi di base:

sql
SELECT DATE_FORMAT(target_datetime, 'format_string');

Esempio: formattare l’ora corrente

sql
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

Esempio di output

2025-02-01 15:30:45

Specificatori di formato più usati

SpecificatoreSignificatoEsempio
%YAnno (4 cifre)2025
%mMese (2 cifre)02
%dGiorno (2 cifre)01
%HOra (formato 24h)15
%hOra (formato 12h)03
%iMinuto30
%sSecondo45
%pAM/PMPM

3.2 Conversione in formato giapponese o a 12 ore

■ Formato in stile giapponese

sql
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');

Esempio di output:

2025-02-01 15:30

■ Formato a 12 ore + AM/PM

sql
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %h:%i:%s %p');

Esempio di output:

2025-02-01 03:30:45 PM

3.3 Formattazione solo ora in MySQL: TIME_FORMAT()

Funzione di formattazione specifica per dati di tipo TIME.

sql
SELECT TIME_FORMAT(CURTIME(), '%H:%i');

Esempio di output:

15:30

Note
TIME_FORMAT() è solo per il tipo TIME
Per DATETIME, usare DATE_FORMAT()

3.4 Conversione stringa → datetime: STR_TO_DATE()

Per convertire dati stringa in un tipo datetime:

sql
SELECT STR_TO_DATE('2025-02-01 15:30:45', '%Y-%m-%d %H:%i:%s');

Esempio di output:

2025-02-01 15:30:45

Errori comuni
– Incompatibilità di formato restituisce NULL
– Confondere %m e %c (mese con zero iniziale vs senza zero)

3.5 Punti importanti in produzione

❌ Non confrontare dopo la formattazione
Esempio errato:

sql
WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-01';

Questo non è consigliato perché gli indici diventano inefficaci (le prestazioni della query peggiorano).

Consigliato:

sql
WHERE created_at >= '2025-02-01' AND created_at < '2025-02-02';

❌ Non sovra‑formattare sul lato DB
Nelle applicazioni web, la formattazione per la visualizzazione è solitamente più flessibile sul lato applicazione.
Il database dovrebbe concentrarsi su “memorizzazione e calcolo”.

3.6 Formattazione con millisecondi

sql
SELECT DATE_FORMAT(NOW(3), '%Y-%m-%d %H:%i:%s.%f');

%f rappresenta i microsecondi (6 cifre).

Nota
Se la colonna non è DATETIME(3) o simile, la parte frazionaria verrà troncata.
Disponibile in MySQL 5.6 e versioni successive.

3.7 Riepilogo per scopo di formattazione

ScopoFunzione
Cambiare formato di visualizzazioneDATE_FORMAT
Formattare solo l’oraTIME_FORMAT
Conversione stringa → datetimeSTR_TO_DATE
Visualizzare millisecondi%f
  1. Aggiunta/Sottrazione di date e ore in MySQL (DATE_ADD / DATE_SUB)
    Anche se riesci a recuperare l’ora corrente, non puoi usarla efficacemente in produzione senza calcoli di data/ora come “X giorni dopo” o “X ore fa.”
    Qui spieghiamo come utilizzare DATE_ADD() e DATE_SUB() con l’ora corrente in MySQL.

4.1 Aggiunta datetime MySQL: DATE_ADD()

Sintassi di base:

sql
SELECT DATE_ADD(base_datetime, INTERVAL value unit);

Esempio: 7 giorni da ora

sql
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY);

Esempio: 2 ore dopo

sql
SELECT DATE_ADD(NOW(), INTERVAL 2 HOUR);

Unità più usate

UnitàSignificato
SECONDSecondi
MINUTEMinuti
HOUROre
DAYGiorni
MONTHMesi
YEARAnni

4.2 Sottrazione datetime MySQL: DATE_SUB()

Sintassi di base:

sql
SELECT DATE_SUB(base_datetime, INTERVAL value unit);

Esempio: 30 giorni fa

sql
SELECT DATE_SUB(NOW(), INTERVAL 30 DAY);

Esempio: 1 ora fa

sql
SELECT DATE_SUB(NOW(), INTERVAL 1 HOUR);

Casi d’uso
– Controlli di scadenza
– Cancellazione di log vecchi
– Estrazione di dati recenti

4.3 Pattern comuni in produzione

■ Recuperare dati dalle ultime 24 ore

sql
SELECT * FROM logs WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 DAY);

■ Impostare una scadenza 7 giorni dopo

sql
INSERT INTO tasks (deadline) VALUES (DATE_ADD(NOW(), INTERVAL 7 DAY));

4.4 Errori comuni e precauzioni
❌ Applicare funzioni alle colonne
Esempio errato:
WHERE DATE(created_at) = CURDATE();
Questo disabilita gli indici (ottimizzazione delle prestazioni della query).
Consigliato:
WHERE created_at >= CURDATE() AND created_at < DATE_ADD(CURDATE(), INTERVAL 1 DAY);
❌ Ignorare i fusi orari
NOW() si basa sul fuso orario del server
Se memorizzi in UTC, usa UTC_TIMESTAMP() come base
Esempio:
SELECT DATE_ADD(UTC_TIMESTAMP(), INTERVAL 1 DAY);
❌ Insidie nell’aggiunta di mesi
SELECT DATE_ADD('2025-01-31', INTERVAL 1 MONTH);
→ A causa della regolazione di fine mese, la data può cambiare.
(Il risultato può diventare 2025-02-28 a seconda dell’ambiente.)
Comprendi la specifica prima di utilizzare calcoli basati sui mesi.
4.5 Aggiunta con millisecondi
SELECT DATE_ADD(NOW(3), INTERVAL 500 MILLISECOND);
※ MySQL non supporta direttamente MILLISECOND.
Specifica in microsecondi:
SELECT DATE_ADD(NOW(3), INTERVAL 500000 MICROSECOND);
4.6 Buone pratiche
Standardizza su NOW() o UTC_TIMESTAMP() come base
Non applicare funzioni alle colonne nella clausola WHERE
Comprendi il comportamento dell’aggiunta basata sui mesi
Se è necessaria precisione, usa DATETIME(3) o superiore

5. Calcolare le differenze di data/ora in MySQL (DATEDIFF / TIMESTAMPDIFF)

Nei sistemi di produzione, recuperare semplicemente l’ora corrente non è sufficiente. Spesso è necessario calcolare quanti giorni sono passati o quante ore rimangono.

5.1 Calcolare le differenze di data: DATEDIFF()

DATEDIFF() calcola la differenza in giorni tra due date.

SELECT DATEDIFF('2025-02-10', '2025-02-01');

Risultato

9

Punti chiave

  • Restituisce la differenza solo in giorni
  • La parte oraria è ignorata
  • Il risultato può essere negativo

Esempio: calcolare i giorni dalla creazione

SELECT DATEDIFF(NOW(), created_at)
FROM users;

5.2 Calcolare le differenze per unità: TIMESTAMPDIFF()

TIMESTAMPDIFF() consente di specificare l’unità.

SELECT TIMESTAMPDIFF(unit, start_datetime, end_datetime);

Esempio: differenza in ore

SELECT TIMESTAMPDIFF(HOUR, '2025-02-01 10:00:00', '2025-02-01 15:00:00');

Risultato

5

Unità comuni

UnitMeaning
SECONDSeconds
MINUTEMinutes
HOURHours
DAYDays
MONTHMonths
YEARYears

Esempio: calcolare i minuti dal login

SELECT TIMESTAMPDIFF(MINUTE, login_at, NOW())
FROM users;

5.3 Casi d’uso in produzione

  • Controlli di timeout della sessione
  • Controlli di scadenza dell’abbonamento
  • Calcolo del tempo trascorso nei log
  • Logica di limitazione del rate

5.4 Errori comuni

❌ Usare DATEDIFF quando è richiesta precisione temporale

DATEDIFF() ignora ore e minuti.

❌ Invertire l’ordine degli argomenti

L’ordine è:

TIMESTAMPDIFF(unit, start, end)

Se invertito, il risultato diventa negativo.

❌ Ignorare i fusi orari

Se si mescolano UTC e ora locale, le differenze possono essere errate.

5.5 Buone pratiche

  • Usa TIMESTAMPDIFF() quando la precisione temporale è importante
  • Usa DATEDIFF() per semplici calcoli di giorni
  • Assicurati di un uso coerente del fuso orario
  • Standardizza su UTC nei sistemi distribuiti

6. Query di intervallo di date usando l’ora corrente

Uno dei requisiti reali più comuni è recuperare record entro un intervallo di tempo specifico, come:

  • Record di oggi
  • Ultimi 7 giorni
  • Ultime 24 ore
  • Questo mese

6.1 Recuperare i record di oggi (ottimizzato per indice)

SELECT *
FROM logs
WHERE created_at >= CURDATE()
  AND created_at < DATE_ADD(CURDATE(), INTERVAL 1 DAY);

Perché è corretto

  • Nessuna funzione è applicata alla colonna
  • Gli indici rimangono utilizzabili
  • Query di intervallo efficiente

6.2 Ultimi 7 giorni

SELECT *
FROM logs
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);

6.3 Ultime 24 ore

SELECT *
FROM logs
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 DAY);

6.4 Questo mese

SELECT *
FROM logs
WHERE created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')
  AND created_at < DATE_ADD(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 MONTH);

Nei sistemi di produzione, è spesso meglio calcolare i limiti sul lato dell’applicazione e passarli come parametri.

6.5 Errori comuni di prestazioni

❌ Applicare funzioni a colonne indicizzate

WHERE DATE(created_at) = CURDATE();

Questo impedisce l’uso dell’indice e provoca scansioni complete della tabella.

❌ Usare BETWEEN incautamente

BETWEEN è inclusivo e può causare problemi di un secondo di scarto.

6.6 Riepilogo delle migliori pratiche

  • Usa sempre condizioni di intervallo per il filtraggio delle date
  • Evita di applicare funzioni a colonne indicizzate
  • Preferisci la memorizzazione in UTC nei sistemi globali
  • Sii esplicito riguardo alle assunzioni sul fuso orario