Horodatage actuel MySQL : NOW(), CURRENT_TIMESTAMP, SYSDATE(), UTC et bonnes pratiques

目次

1. Le SQL le plus court pour obtenir la date/heure actuelle en MySQL

Si vous voulez obtenir la date/heure actuelle en MySQL, les premières fonctions à retenir sont NOW() et CURRENT_TIMESTAMP. Voici ci-dessous les exemples SQL les plus courts par cas d’utilisation.

1.1 Obtenir la date/heure actuelle (basique)

SELECT NOW();

ou

SELECT CURRENT_TIMESTAMP;
  • Les deux retournent la date/heure actuelle (YYYY-MM-DD HH:MM:SS) .
  • Au sein de la même requête, l’heure est fixée au « moment de début de la requête ».

Cas d’utilisation

  • Journalisation
  • Obtention d’un horodatage de création d’enregistrement
  • Obtention d’une heure de référence

Erreur courante

  • La zone horaire de l’application et celle de la base de données diffèrent et « les heures se décalent ». → Vérifiez avec SELECT @@session.time_zone;

1.2 Obtenir uniquement la date d’aujourd’hui

SELECT CURDATE();
  • Format de retour : YYYY-MM-DD
  • Le type est DATE (date uniquement, pas datetime)

Cas d’utilisation

  • Recherche de « données d’aujourd’hui »
  • Agrégation quotidienne

Notes

  • Contrairement à NOW() , cela n’inclut pas l’heure.
  • Si vous avez besoin de l’heure pour des requêtes de plage, utilisez NOW() .

1.3 Obtenir uniquement l’heure actuelle

SELECT CURTIME();
  • Format de retour : HH:MM:SS
  • Le type est TIME (heure uniquement)

Cas d’utilisation

  • Affichage du temps d’exécution par lots
  • Impression de la partie heure uniquement dans les journaux

Piège courant

  • Comme cela n’inclut pas de date, vous ne pouvez pas l’utiliser pour des comparaisons datetime.

1.4 Obtenir l’heure actuelle en UTC (important)

SELECT UTC_TIMESTAMP();
  • Retourne UTC indépendamment de la zone horaire du serveur.
  • Recommandé pour les services globaux.

Politique de base dans les projets réels

  • Stocker en UTC
  • Convertir en heure locale lors de l’affichage

Notes

  • Si l’application convertit déjà en UTC, méfiez-vous d’une double conversion.

1.5 Obtenir les millisecondes / microsecondes

SELECT NOW(3);  -- milliseconds (3 digits after the decimal point)
SELECT NOW(6);  -- microseconds (6 digits after the decimal point)
  • Disponible dans MySQL 5.6.4 et versions ultérieures.
  • Utilisé pour les journaux haute précision et l’audit des transactions.

Idée fausse courante

  • NOW() seul ne peut pas retourner de secondes fractionnaires.
  • Votre colonne doit également spécifier la précision, par ex. DATETIME(6) .

1.6 Meilleure fonction par cas d’utilisation (commencez ici si vous n’êtes pas sûr)

Use caseRecommended function
General current datetimeNOW()
Table default valueCURRENT_TIMESTAMP
Date onlyCURDATE()
Time onlyCURTIME()
Unified UTC managementUTC_TIMESTAMP()
High-precision logsNOW(6)

Points clés souvent manqués

  • NOW() et CURRENT_TIMESTAMP sont effectivement équivalents (même valeur)
  • Au sein de la même requête, l’heure est fixée
  • La valeur affichée change en fonction des paramètres de zone horaire
  • Pour les microsecondes, la définition de votre colonne doit spécifier la précision

2. Différences entre NOW() / CURRENT_TIMESTAMP / SYSDATE()

Il existe plusieurs fonctions pour obtenir l’heure actuelle, mais la partie la plus confuse est la différence entre NOW(), CURRENT_TIMESTAMP, et SYSDATE().
Si vous ne comprenez pas cela correctement, vous pouvez obtenir un comportement inattendu dans les journaux et le traitement des transactions.

2.1 NOW() et CURRENT_TIMESTAMP sont effectivement équivalents

SELECT NOW(), CURRENT_TIMESTAMP;
  • Les deux retournent la datetime actuelle (une valeur DATETIME) .
  • Au sein de la même requête, l’heure est fixée au « moment de début de la requête ».
  • CURRENT_TIMESTAMP peut également être utilisé avec la syntaxe d’appel de fonction :
    SELECT CURRENT_TIMESTAMP();
    

Comment choisir dans les projets réels

Use caseRecommended
Simple retrievalNOW()
Table DEFAULT / ON UPDATECURRENT_TIMESTAMP

Points importants

  • La signification de la valeur récupérée est la même.
  • La principale différence est la syntaxe/utilisation (par ex., autorisé dans DEFAULT).
  • Ce n’est pas une différence de type (facile à mal comprendre).

2.2 SYSDATE() retourne l’heure au « moment d’évaluation »

SYSDATE() ressemble à NOW(), mais le moment où la valeur est fixée est différent.

SELECT NOW(), SLEEP(2), NOW();

Résultat (exemple) :

2025-02-23 14:00:00
2025-02-23 14:00:00
SELECT SYSDATE(), SLEEP(2), SYSDATE();

Résultat (exemple) :

2025-02-23 14:00:00
2025-02-23 14:00:02

La différence essentielle

FunctionWhen the time is fixed
NOW()Query start time
SYSDATE()Evaluation time

En d’autres termes, SYSDATE() peut changer au sein de la même requête au fur et à mesure que le temps passe.

2.3 Notes pour les transactions et la réplication

Parce que NOW() est fixé au début de la requête, il est
plus sûr lorsque vous avez besoin d’un temps de référence cohérent à l’intérieur d’une transaction.

En revanche, comme SYSDATE() dépend du moment d’exécution, il peut affecter la reproductibilité dans :

  • Réplication
  • Jobs par lots
  • Traitement de journaux en masse

Règle générale

  • Vous voulez un temps de référence fixe → NOW()
  • Vous avez besoin de l’instant exact à chaque fois → SYSDATE() (usage limité)

2.4 Note : CURRENT_DATE / CURRENT_TIME / LOCALTIME

MySQL prend également en charge :

SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT LOCALTIME;
  • CURRENT_DATE → identique à CURDATE()
  • CURRENT_TIME → identique à CURTIME()
  • LOCALTIME → identique à NOW()

Confusion courante

  • Ce sont principalement des « différences cosmétiques » ; il y a peu de différence fonctionnelle.
  • Par mesure de sécurité, privilégiez la lisibilité et standardisez au sein du projet.

Points clés de cette section

  • NOW() et CURRENT_TIMESTAMP signifient essentiellement la même chose.
  • SYSDATE() se comporte différemment car il est basé sur le temps d’évaluation.
  • Pour des temps de référence fixes, utilisez NOW() par défaut.
  • Utilisez CURRENT_TIMESTAMP pour DEFAULT et ON UPDATE.

3. Modifier le format d’affichage de la date/heure actuelle

Le temps actuel que vous obtenez avec NOW() est affiché par défaut sous la forme YYYY-MM-DD HH:MM:SS. Dans le travail réel, vous aurez souvent besoin de choses comme :

  • Afficher uniquement la date
  • Utiliser YYYY/MM/DD
  • Utiliser un format localisé (p. ex., 23 févr. 2025)
  • Afficher les millisecondes

Pour cela, utilisez DATE_FORMAT() (convertir un datetime en une chaîne de format arbitraire).

3.1 Syntaxe de base de DATE_FORMAT()

DATE_FORMAT(datetime, 'format_string')

Exemple : convertir le temps actuel en YYYY/MM/DD HH:MM

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

Exemple de sortie :

2025/02/23 14:35

Spécificateurs de format courants

SpecifierMeaningExample
%Y4-digit year2025
%m2-digit month02
%d2-digit day23
%HHour (24-hour)14
%iMinutes35
%sSeconds50
%fMicroseconds123456

Remarques

  • Certains spécificateurs diffèrent entre majuscules et minuscules.
  • %h correspond à l’heure sur 12 h, %H à l’heure sur 24 h.

3.2 Exemples de formats courants (fréquents dans le travail réel)

1. Séparé par des barres obliques

SELECT DATE_FORMAT(NOW(), '%Y/%m/%d');

2. Localisé (anglais)

SELECT DATE_FORMAT(NOW(), '%b %d, %Y');

3. Sans secondes

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

Piège courant

  • Comme il renvoie une chaîne, vous ne pouvez pas l’utiliser pour des calculs numériques.
  • Pour les comparaisons et les recherches, vous devez utiliser le type DATETIME original.

3.3 Extraire uniquement la partie date ou heure

Vous pouvez également récupérer des parties tout en conservant le type (au lieu de formater en chaîne).

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

Utilisation recommandée

GoalRecommended
Formatting for displayDATE_FORMAT
Calculation / comparisonDATE() / TIME()

3.4 Affichage avec microsecondes

Lorsque vous avez besoin de journaux haute précision :

SELECT NOW(6);

Avec formatage :

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

Notes importantes

  • Votre colonne doit être DATETIME(6) ou TIMESTAMP(6), sinon la précision ne sera pas stockée.
  • Non disponible dans les versions de MySQL antérieures à 5.6.4 (selon l’environnement).

Erreurs courantes

  • Utiliser DATE_FORMAT() dans une clause WHERE empêche l’utilisation des index. wp:list /wp:list

    • Mauvais exemple : WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-23'
    • Recommandé : WHERE created_at >= '2025-02-23 00:00:00' AND created_at < '2025-02-24 00:00:00'
    • Stocker directement la chaîne formatée pour l’affichage (dégrade les performances de recherche)

Points clés de cette section

  • Utilisez DATE_FORMAT() pour changer les formats d’affichage.
  • Pour les calculs/comparaisons, conservez le type original.
  • Si vous avez besoin de microsecondes, spécifiez la précision dans la définition de la colonne.
  • Utiliser des fonctions dans les clauses WHERE peut entraîner des problèmes de performance.

4. Calculs de datetime en utilisant le temps actuel

Dans MySQL, il est courant de calculer des choses comme « N heures plus tard », « N jours auparavant », ou « les N derniers jours » en fonction de l’heure actuelle.
Le cas réel le plus fréquent est « obtenir les données des dernières 24 heures ».

Le fondement de l’arithmétique des dates et heures est INTERVAL (syntaxe pour ajouter/soustraire des unités de temps).

4.1 Ajouter/soustraire avec INTERVAL

Obtenir 1 heure plus tard

SELECT NOW() + INTERVAL 1 HOUR;

Obtenir 3 jours auparavant

SELECT NOW() - INTERVAL 3 DAY;

Obtenir 1 mois plus tard

SELECT NOW() + INTERVAL 1 MONTH;

Unités courantes

UnitMeaning
SECONDSeconds
MINUTEMinutes
HOURHours
DAYDays
WEEKWeeks
MONTHMonths
YEARYears

Erreurs courantes

  • DAY dans INTERVAL 1 DAY fonctionne même en minuscules, mais vous devriez standardiser au sein de l’équipe.
  • Les calculs de fin de mois peuvent différer des attentes parce que le nombre de jours varie (par ex., 31 janv. + 1 mois).

4.2 Obtenir les données des dernières 24 heures (modèle le plus courant)

SELECT *
FROM users
WHERE created_at >= NOW() - INTERVAL 1 DAY;

Signification

  • Cible « à partir de maintenant jusqu’à il y a 24 heures ».

Notes

  • Si vous utilisez CURDATE(), la référence devient « aujourd’hui à 00 h », ce qui change le sens.

Exemple (données d’aujourd’hui) :

SELECT *
FROM users
WHERE created_at >= CURDATE();

Comprendre la différence est crucial

ExpressionMeaning
NOW() - INTERVAL 1 DAYPast 24 hours
CURDATE()Since today 00:00

4.3 Obtenir les différences de jours avec DATEDIFF()

SELECT DATEDIFF('2025-03-01', '2025-02-23');

Résultat :

6
  • L’unité est « jours »
  • La partie temps est ignorée

Notes

  • Le signe change selon l’ordre des arguments.
  • Vous ne pouvez pas calculer les différences en heures/minutes/secondes.

4.4 Utiliser TIMESTAMPDIFF() pour les heures/minutes/secondes

SELECT TIMESTAMPDIFF(HOUR,
                     '2025-02-23 12:00:00',
                     '2025-02-23 18:30:00');

Résultat :

6

Minutes

SELECT TIMESTAMPDIFF(MINUTE,
                     '2025-02-23 12:00:00',
                     '2025-02-23 12:30:00');

Secondes

SELECT TIMESTAMPDIFF(SECOND,
                     '2025-02-23 12:00:00',
                     '2025-02-23 12:00:45');

Cas d’utilisation

  • Calculs de durée de session
  • Vérifications d’expiration
  • Décisions de timeout

4.5 Obtenir le début du mois / la fin du mois (piège réel courant)

Obtenir le premier jour de ce mois :

SELECT DATE_FORMAT(NOW(), '%Y-%m-01');

Premier jour du mois suivant :

SELECT DATE_FORMAT(NOW() + INTERVAL 1 MONTH, '%Y-%m-01');

Notes

  • La fin du mois n’est pas une date fixe.
  • Pour les requêtes de plage, « >= début ET < premier jour du mois suivant » est sûr.

Résumé des erreurs courantes

  • Utiliser BETWEEN avec des valeurs uniquement date et oublier l’heure
  • Désactiver les index en utilisant DATE(created_at) dans les clauses WHERE
  • Tomber dans le piège du « 31e jour » dans les calculs de mois
  • Mal comprendre la différence entre NOW() et CURDATE()

Points clés de cette section

  • INTERVAL est le fondement de l’arithmétique des dates et heures.
  • Les dernières 24 heures = NOW() - INTERVAL 1 DAY.
  • Jours = DATEDIFF() ; unités plus petites = TIMESTAMPDIFF().
  • Soyez prudent avec les conditions de fin pour les calculs basés sur les mois.

5. Pour les requêtes de plage, c’est plus sûr que BETWEEN

Lors de recherches de plages de dates dans MySQL, de nombreux débutants utilisent BETWEEN. Cependant, cela produit souvent des résultats inattendus si vous gérez mal les limites de temps, donc un modèle plus sûr est recommandé en pratique.

5.1 Bases de BETWEEN et le piège

Une requête courante

SELECT *
FROM orders
WHERE order_date BETWEEN '2025-02-01' AND '2025-02-10';

Cela semble correct, mais en interne c’est équivalent à :

WHERE order_date &gt;= '2025-02-01 00:00:00'
  AND order_date &lt;= '2025-02-10 00:00:00'

Donc cela n’inclut pas les données après 00 h le 10 févr.


5.2 Modèle plus sûr (recommandé)

Modèle recommandé

SELECT *
FROM orders
WHERE order_date &gt;= '2025-02-01 00:00:00'
  AND order_date &lt;  '2025-02-11 00:00:00';

Points clés

  • Spécifiez la limite de fin comme « inférieur au lendemain à 00:00 »
  • Plus sûr que <= 23:59:59 (supporte les microsecondes)

5.3 La bonne façon d’obtenir les données d’aujourd’hui

Mauvais exemple :

WHERE DATE(created_at) = CURDATE();

Problèmes :

  • Appliquer une fonction à la colonne désactive les index
  • Peut causer des ralentissements sérieux sur les grandes tables

Recommandé :

WHERE created_at &gt;= CURDATE()
  AND created_at &lt;  CURDATE() + INTERVAL 1 DAY;

Cela assure :

  • Les index peuvent être utilisés
  • Recherches rapides
  • Pas de problèmes de limites

5.4 Modèles sûrs pour les 7 derniers / 30 derniers jours

7 derniers jours

WHERE created_at &gt;= NOW() - INTERVAL 7 DAY;

30 derniers jours

WHERE created_at &gt;= NOW() - INTERVAL 30 DAY;

Notes

  • CURDATE() - INTERVAL 7 DAY est basé sur « aujourd’hui 00:00 »
  • NOW() - INTERVAL 7 DAY est basé sur « l’heure actuelle »
  • Choisissez en fonction des exigences

5.5 Règle clé pour garder les index efficaces

Mauvais :

WHERE DATE(created_at) = '2025-02-23';

Bon :

WHERE created_at &gt;= '2025-02-23 00:00:00'
  AND created_at &lt;  '2025-02-24 00:00:00';

Pourquoi :

  • Les index fonctionnent sur « la colonne elle-même »
  • Appliquer une fonction empêche l’utilisation de l’index (scan complet)

Résumé des erreurs courantes

  • Oublier d’inclure l’heure à la limite de fin dans BETWEEN
  • Manquer les microsecondes lors de l’utilisation de 23:59:59
  • Utiliser DATE() dans les clauses WHERE et ralentir les requêtes
  • Laisser ambigu « maintenant » vs « aujourd’hui 00:00 »

Points clés de cette section

  • Les requêtes de plage sont les plus sûres avec >= début AND < fin .
  • BETWEEN nécessite une gestion minutieuse des limites.
  • Pour garder les index efficaces, ne mettez pas les colonnes dans des fonctions.
  • Choisissez clairement entre la logique basée sur NOW() et celle basée sur CURDATE() .

6. DEFAULT CURRENT_TIMESTAMP et ON UPDATE (bases de conception de table)

Dans la conception de base de données, il est courant de gérer automatiquement created_at et updated_at.
En MySQL, CURRENT_TIMESTAMP vous permet de définir l’heure actuelle automatiquement lors de l’insertion et de la mise à jour.

6.1 Auto-définir created_at (DEFAULT CURRENT_TIMESTAMP)

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Comportement :

INSERT INTO users (name) VALUES ('Alice');

→ L’heure actuelle est automatiquement insérée dans created_at.

Points clés

  • CURRENT_TIMESTAMP peut être utilisé dans DEFAULT.
  • NOW() ne peut pas être utilisé directement dans DEFAULT.

Erreur courante

created_at DATETIME DEFAULT NOW();  -- error

Raison :

  • En MySQL, vous ne pouvez généralement pas définir une fonction comme DEFAULT (l’exception est CURRENT_TIMESTAMP).

6.2 Auto-mettre à jour 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
);

Comportement :

UPDATE users SET name = 'Bob' WHERE id = 1;

updated_at est automatiquement mis à jour avec l’heure actuelle.

Cas d’utilisation

  • Suivi de la dernière connexion
  • Historique des mises à jour
  • Journaux d’audit

6.3 DATETIME vs TIMESTAMP (important)

TypeRangeTime zone impact
DATETIMEYear 1000 to 9999No
TIMESTAMP1970 to 2038Yes

La différence essentielle

  • TIMESTAMP est stocké en interne en UTC et converti vers le fuseau horaire de la session lors de l’affichage.
  • DATETIME stocke la valeur littérale (pas de conversion).

Directives

CaseRecommended type
Log managementTIMESTAMP
Future dates (after 2038)DATETIME
Fixed values not requiring TZ conversionDATETIME

6.4 CURRENT_TIMESTAMP peut aussi être utilisé avec DATETIME

En MySQL 5.6 et versions ultérieures, vous pouvez spécifier CURRENT_TIMESTAMP comme DEFAULT et ON UPDATE pour les colonnes DATETIME également.

created_at DATETIME DEFAULT CURRENT_TIMESTAMP

Notes

  • Les anciennes versions de MySQL ont des restrictions (dépendantes de l’environnement).
  • Si vous avez besoin de précision :
    DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)
    

6.5 Si vous voulez utiliser NOW() : une alternative (déclencheur)

CREATE TRIGGER set_created_at
BEFORE INSERT ON logs
FOR EACH ROW
SET NEW.created_at = NOW();

Cas d’utilisation

  • Logique de valeur initiale complexe
  • Attribution conditionnelle de l’horodatage

Remarques

  • Les déclencheurs sont difficiles à déboguer.
  • Évitez-les sauf si nécessaire.

Erreurs de conception courantes

  • Ajouter ON UPDATE à la fois sur created_at et updated_at
  • Confondre le comportement de DATETIME et TIMESTAMP
  • Reporter les décisions de fuseau horaire

Points clés de cette section

  • Utilisez CURRENT_TIMESTAMP pour DEFAULT.
  • Utilisez ON UPDATE CURRENT_TIMESTAMP pour le suivi des mises à jour.
  • Choisissez les types en fonction du comportement du fuseau horaire et du problème de 2038.
  • Si vous avez besoin de précision, n’oubliez pas (6).

7. Conception des fuseaux horaires (stockage en UTC, affichage en heure locale)

Lorsqu’on travaille avec l’heure actuelle, une mauvaise conception des fuseaux horaires entraîne une dérive temporelle et une double conversion.
En pratique, le paramètre par défaut le plus sûr est « stocker en UTC, convertir en heure locale pour l’affichage ».

MySQL timezone architecture storing timestamps in UTC and converting to local time (JST)

Figure : Architecture de base pour stocker l’UTC dans MySQL et afficher l’heure locale

7.1 Vérifier le fuseau horaire actuel

Tout d’abord, vérifiez quel fuseau horaire MySQL utilise.

SELECT @@global.time_zone, @@session.time_zone;
  • @@global.time_zone → paramètre global du serveur
  • @@session.time_zone → paramètre de la connexion/session actuelle
  • Si cela indique SYSTEM, cela dépend du paramètre du système d’exploitation

Problèmes courants

  • Les serveurs de production et de développement ont des fuseaux horaires OS différents
  • L’application convertit en UTC, puis la base de données reconvertit (double conversion)

7.2 Modifier le fuseau horaire par session

SET time_zone = 'Asia/Tokyo';

ou uniformiser en UTC :

SET time_zone = '+00:00';

Points importants

  • Il revient à l’original lorsque la connexion est fermée
  • Si vous utilisez un pool de connexions, vérifiez les paramètres de votre application

7.3 Pourquoi stocker en UTC (principe du monde réel)

Politique recommandée

  1. Stocker les données en UTC
  2. Convertir dans le fuseau horaire de l’utilisateur lors de l’affichage

Raisons :

  • Support international plus facile
  • Éviter les problèmes liés à l’heure d’été (DST)
  • Minimiser l’impact lors du déplacement des serveurs

Obtenir l’UTC :

SELECT UTC_TIMESTAMP();

7.4 Convertir les fuseaux horaires avec CONVERT_TZ()

Exemple : UTC → JST

SELECT CONVERT_TZ('2025-02-23 05:35:00', '+00:00', '+09:00');

Utilisation des noms de fuseau horaire :

SELECT CONVERT_TZ('2025-02-23 05:35:00', 'UTC', 'Asia/Tokyo');

Exemple du monde réel

SELECT CONVERT_TZ(created_at, 'UTC', 'Asia/Tokyo')
FROM users;

7.5 Pourquoi CONVERT_TZ() renvoie NULL

Si elle renvoie NULL, les causes courantes incluent :

  • Les tables de fuseaux horaires de MySQL ne sont pas chargées
  • Le nom de fuseau horaire spécifié n’existe pas

Exemple de chargement sous Linux :

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

Remarques

  • En production, confirmez les permissions et si un redémarrage est nécessaire
  • Dans Docker, zoneinfo peut ne pas être inclus selon l’image

7.6 Modifier le fuseau horaire global du serveur

Fichier de configuration (my.cnf / my.ini) :

[mysqld]
default_time_zone = '+00:00'

Vérifier après redémarrage :

SELECT @@global.time_zone;

Important

  • Pour les changements en production, confirmez l’étendue de l’impact
  • Soyez prudent avec les données existantes (parfois seules les affichages changent)

Erreurs courantes

  • Stocker l’heure locale au lieu de l’UTC, puis ajouter le support international plus tard
  • Double conversion entre l’application et la base de données
  • Concevoir avec DATETIME sans prendre en compte les fuseaux horaires
  • Paramètres de fuseau horaire différents entre test et production

Points clés de cette section

  • Stocker en UTC et convertir lors de l’affichage.
  • Utilisez UTC_TIMESTAMP().
  • Lors de l’utilisation de CONVERT_TZ(), vérifiez les tables de fuseaux horaires.
  • Prenez toujours en compte les différences d’environnement au niveau des fuseaux horaires.

8. Exemples pratiques prêts à l’emploi

Voici des exemples SQL concrets montrant comment utiliser l’heure actuelle de MySQL dans le développement/opérations réelles.
Ils sont rédigés pour que vous puissiez les copier‑coller directement.

8.1 Insérer automatiquement l’heure actuelle dans les journaux

Créer la table

CREATE TABLE system_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    level VARCHAR(50),
    message TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Insertion du journal

INSERT INTO system_logs (level, message)
VALUES ('ERROR', 'Failed to connect to the DB');

Points clés

  • created_at est inséré automatiquement
  • Pas besoin de transmettre un horodatage depuis l’application
  • Conception essentielle pour l’audit et l’investigation d’incidents

Erreurs courantes

  • Gérer le temps à la fois dans l’application et la base de données
  • Incohérences temporelles dues à des fuseaux horaires non unifiés

8.2 Mettre à jour l’heure de la dernière connexion

Conception de la table

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255),
    last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP
               ON UPDATE CURRENT_TIMESTAMP
);

Mise à jour lors de la connexion

UPDATE users
SET last_login = NOW()
WHERE id = 1;

Remarques

  • ON UPDATE ne s’active que lorsque la colonne change
  • Certaines instructions UPDATE peuvent ne pas modifier la valeur et donc ne pas mettre à jour

8.3 Fixer une heure de référence dans les jobs batch

Pour les processus de longue durée, il est plus sûr de fixer une heure de référence.

SET @base_time = NOW();

SELECT *
FROM orders
WHERE created_at &gt;= @base_time - INTERVAL 1 DAY;

Pourquoi

  • Le temps ne change pas en cours de processus
  • La cohérence est maintenue

8.4 Agrégation pour aujourd’hui / hier / les 7 derniers jours

Ventes d’aujourd’hui

SELECT SUM(amount)
FROM orders
WHERE created_at &gt;= CURDATE()
  AND created_at &lt;  CURDATE() + INTERVAL 1 DAY;

Ventes d’hier

SELECT SUM(amount)
FROM orders
WHERE created_at &gt;= CURDATE() - INTERVAL 1 DAY
  AND created_at &lt;  CURDATE();

7 derniers jours

SELECT COUNT(*)
FROM users
WHERE created_at &gt;= NOW() - INTERVAL 7 DAY;

Important

  • Ne pas appliquer de fonctions aux colonnes dans les clauses WHERE
  • Écrire des conditions qui conservent l’utilisabilité des index

8.5 Vérifications d’expiration (sessions/jetons)

SELECT *
FROM sessions
WHERE expires_at &gt; NOW();

Supprimer les lignes expirées

DELETE FROM sessions
WHERE expires_at &lt;= NOW();

Erreurs courantes

  • Utiliser CURDATE() en ignorant l’heure
  • Stocker en UTC mais comparer avec le NOW() local

8.6 Obtenir les lignes expirant dans N heures

SELECT *
FROM coupons
WHERE expires_at &lt;= NOW() + INTERVAL 1 HOUR;

Cas d’utilisation :

  • Alertes d’expiration
  • Notifications d’expiration

Ce que vous devez toujours garder à l’esprit

  • Soyez explicite quant à savoir si votre référence est « maintenant » ou « aujourd’hui 00:00 »
  • Écrivez des prédicats qui maintiennent l’efficacité des index
  • Décidez dès le départ de la conception du fuseau horaire
  • Ne mélangez pas NOW() et UTC_TIMESTAMP() sans une politique claire

Points clés de cette section

  • Pour les journaux/audits/suivi des mises à jour, utilisez CURRENT_TIMESTAMP
  • Pour l’agrégation, utilisez le modèle sûr >= ET <
  • Pour la gestion des sessions, comparez avec NOW()
  • Fixez une heure de référence pour garder le traitement cohérent

9. Questions fréquemment posées (FAQ)

Voici des questions courantes sur l’heure actuelle de MySQL, notamment les pièges qui apparaissent dans le travail réel.

9.1 Quelle est la différence entre NOW() et CURRENT_TIMESTAMP ?

Conclusion : la signification de la valeur retournée est la même.

SELECT NOW(), CURRENT_TIMESTAMP;

Les deux renvoient la date et l’heure actuelles.

La principale différence réside dans l’utilisation syntaxique

  • CURRENT_TIMESTAMP peut être utilisé dans DEFAULT et ON UPDATE
  • NOW() ne peut pas être utilisé directement dans DEFAULT

Remarques

  • Ce n’est pas une différence de type
  • Vous pouvez spécifier la précision avec des arguments comme (6)

9.2 Devriez-vous utiliser SYSDATE() ?

SYSDATE() renvoie l’heure au moment de « l’évaluation ».

SELECT SYSDATE(), SLEEP(2), SYSDATE();

La valeur peut changer même au sein de la même requête.

Quand l’utiliser

  • Lorsque vous devez enregistrer l’instant réel exact

Quand l’éviter

  • Réplication
  • Traitement de transaction où la cohérence est importante

Dans la plupart des cas, l’utilisation de NOW() suffit.

9.3 Pourquoi l’heure est-elle décalée ?

Causes principales :

  1. Paramètres de fuseau horaire du serveur
  2. Paramètres de fuseau horaire de la session
  3. Conversion double avec l’application
  4. Comportement de conversion automatique du type TIMESTAMP

Vérifiez avec :

SELECT @@global.time_zone, @@session.time_zone;

Atténuation

  • Stocker en UTC par défaut
  • Convertir seulement lors de l’affichage
  • Unifier la politique entre l’app et la DB

9.4 CONVERT_TZ() retourne NULL

Causes :

  • Les tables de fuseaux horaires ne sont pas chargées
  • Nom de fuseau horaire incorrect

Correction :

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

Soyez particulièrement prudent dans les environnements Docker.

9.5 Décalages de plage avec BETWEEN

Mauvais :

WHERE created_at BETWEEN '2025-02-01' AND '2025-02-10';

Sûr :

WHERE created_at &gt;= '2025-02-01 00:00:00'
  AND created_at &lt;  '2025-02-11 00:00:00';

Raisons :

  • Problème de temps de limite finale
  • Fuite de microsecondes
  • Efficacité de l’index

9.6 Comment choisir entre DATETIME et TIMESTAMP ?

  • Support international / gestion UTC → TIMESTAMP
  • Après 2038 ou datetimes fixes → DATETIME

Décidez cela lors de la conception.

9.7 Les microsecondes ne sont pas stockées

Cause :

  • Aucune précision spécifiée dans la définition de la colonne

Correction :

created_at DATETIME(6)

Points clés de cette section

  • Commencez avec NOW() et CURRENT_TIMESTAMP
  • Pour les requêtes de plage, utilisez >= AND <
  • Le stockage UTC est le défaut le plus sûr
  • N’oubliez pas la sélection du type et la précision

10. Résumé

Cet article organise des méthodes pratiques pour récupérer, formater, calculer et gérer l’heure actuelle en MySQL.
Enfin, voici les essentiels minimaux que vous devriez connaître pour rester en sécurité.

10.1 Obtenir l’heure actuelle (basics)

  • Récupération générale → NOW()
  • DEFAULT de table / suivi de mise à jour → CURRENT_TIMESTAMP
  • Date seulement → CURDATE()
  • Heure seulement → CURTIME()
  • UTC → UTC_TIMESTAMP()
  • Haute précision → NOW(6)

Règles empiriques

  • Si vous n’êtes pas sûr, utiliser NOW() est bien dans la plupart des cas.
  • Pour la conception de schéma, utilisez CURRENT_TIMESTAMP .

10.2 Requêtes de plage : « >= AND < » est la règle d’or

Modèle sûr :

WHERE created_at &gt;= 'START'
  AND created_at &lt;  'END'

Pourquoi :

  • Évite de manquer les lignes de limite finale
  • Fonctionne avec les microsecondes
  • Maintient les index utilisables

Mauvais exemple

WHERE DATE(created_at) = CURDATE();

Ne mettez pas la colonne dans une fonction.

10.3 Bases de l’arithmétique datetime

  • Ajouter/soustraire → INTERVAL
  • Différences de jours → DATEDIFF()
  • Différences de temps → TIMESTAMPDIFF()

Gardez toujours à l’esprit si votre base est « maintenant » ou « aujourd’hui 00:00 ».

10.4 Principes de conception des fuseaux horaires

  • Stocker en UTC
  • Convertir à l’affichage
  • Unifier la politique entre l’app et la DB

Vérifiez avec :

SELECT @@global.time_zone, @@session.time_zone;

10.5 Meilleures pratiques pour la conception de table

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
           ON UPDATE CURRENT_TIMESTAMP
  • Équipement standard pour l’audit/journalisation/suivi de mise à jour
  • Si vous avez besoin de précision, spécifiez (6)

Les 4 points les plus importants du monde réel

  1. Ne méprenez pas la différence entre NOW() et CURRENT_TIMESTAMP
  2. Pour les requêtes de plage, utilisez >= AND <
  3. Stocker en UTC par défaut
  4. Décidez des types (DATETIME vs TIMESTAMP) lors de la conception

La gestion de l’heure actuelle en MySQL est fondamentale pour la journalisation, l’agrégation des ventes, la gestion d’authentification/sessions, les travaux par lots, et plus encore.
Si vous suivez les principes de cet article, vous pouvez éviter de nombreux problèmes courants tels que la dérive temporelle, les bugs de limite, et la dégradation des performances.