Il semble que le fuseau horaire sur le serveur n'a pas d'importance tant que l'heure est correctement définie pour le fuseau horaire actuel, que vous connaissez le fuseau horaire des colonnes datetime que vous stockez et que vous êtes conscient des problèmes liés à l'heure d'été. /P>
D'autre part, si vous contrôlez les fuseaux horaires des serveurs avec lesquels vous travaillez, vous pouvez tout régler sur UTC en interne et ne jamais vous soucier des fuseaux horaires et de l'heure d'été.
Voici quelques notes que j'ai recueillies sur la façon de travailler avec les fuseaux horaires comme une forme de feuille de triche pour moi-même et d'autres qui pourraient influencer le fuseau horaire que la personne choisira pour son serveur et comment il/elle stockera la date et l'heure.
Feuille de triche du fuseau horaire MySQL
Remarques :
-
La modification du fuseau horaire ne modifiera pas la date/heure ou l'horodatage enregistré , mais il sélectionnera une date/heure différente des colonnes d'horodatage
-
Attention ! UTC a des secondes intercalaires, celles-ci ressemblent à '2012-06-30 23:59:60' et peuvent être ajoutées au hasard, avec un préavis de 6 mois, en raison du ralentissement de la rotation de la Terre
-
GMT confond les secondes, c'est pourquoi UTC a été inventé.
-
Attention ! différents fuseaux horaires régionaux peuvent produire la même valeur datetime en raison de l'heure d'été
-
La colonne d'horodatage ne prend en charge que les dates 1970-01-01 00:00:01 à 2038-01-19 03:14:07 UTC, en raison de une restriction .
-
En interne, une colonne d'horodatage MySQL est stocké en tant que UTC mais lors de la sélection d'une date, MySQL la convertira automatiquement dans le fuseau horaire de la session en cours.
Lors du stockage d'une date dans un horodatage, MySQL supposera que la date est dans le fuseau horaire de la session en cours et le convertira en UTC pour le stockage.
-
MySQL peut stocker des dates partielles dans des colonnes datetime, celles-ci ressemblent à"2013-00-00 04:00:00"
-
MySQL stocke "0000-00-00 00:00:00" si vous définissez une colonne datetime comme NULL, à moins que vous ne définissiez spécifiquement la colonne pour autoriser null lorsque vous la créez.
Pour sélectionner une colonne d'horodatage au format UTC
quel que soit le fuseau horaire dans lequel se trouve la session MySQL en cours :
SELECT
CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime`
FROM `table_name`
Vous pouvez également définir le fuseau horaire du serveur ou de la session globale ou actuelle sur UTC, puis sélectionner l'horodatage comme suit :
SELECT `timestamp_field` FROM `table_name`
Pour sélectionner la date et l'heure actuelles en UTC :
SELECT UTC_TIMESTAMP();
SELECT UTC_TIMESTAMP;
SELECT CONVERT_TZ(NOW(), @@session.time_zone, '+00:00');
Exemple de résultat :2015-03-24 17:02:41
Pour sélectionner la date et l'heure actuelles dans le fuseau horaire de la session
SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_TIMESTAMP();
Pour sélectionner le fuseau horaire défini lors du lancement du serveur
SELECT @@system_time_zone;
Renvoie "MSK" ou "+04:00" pour l'heure de Moscou par exemple, il y a (ou il y avait) un bogue MySQL où s'il était défini sur un décalage numérique, il n'ajusterait pas l'heure d'été
Pour obtenir le fuseau horaire actuel
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
Il renverra 02:00:00 si votre fuseau horaire est +2:00.
Pour obtenir l'horodatage UNIX actuel (en secondes) :
SELECT UNIX_TIMESTAMP(NOW());
SELECT UNIX_TIMESTAMP();
Pour obtenir la colonne d'horodatage en tant qu'horodatage UNIX
SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`
Pour obtenir une colonne date/heure UTC en tant qu'horodatage UNIX
SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`
Obtenir une date et une heure de fuseau horaire actuel à partir d'un entier positif d'horodatage UNIX
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
Obtenir une date/heure UTC à partir d'un horodatage UNIX
SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00')
FROM `table_name`
Obtenir une date et une heure de fuseau horaire actuel à partir d'un entier négatif d'horodatage UNIX
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
Il existe 3 endroits où le fuseau horaire peut être défini dans MySQL :
Remarque :Un fuseau horaire peut être défini dans 2 formats :
- un décalage par rapport à UTC :'+00:00', '+10:00' ou '-6:00'
- comme fuseau horaire nommé :"Europe/Helsinki", "US/Eastern" ou "MET"
Les fuseaux horaires nommés ne peuvent être utilisés que si les tables d'informations sur les fuseaux horaires dans la base de données mysql ont été créées et remplies.
dans le fichier "mon.cnf"
default_time_zone='+00:00'
ou
timezone='UTC'
Variable @@global.time_zone
Pour voir à quelle valeur ils sont définis
SELECT @@global.time_zone;
Pour lui attribuer une valeur, utilisez l'une des deux :
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone='+00:00';
Variable @@session.time_zone
SELECT @@session.time_zone;
Pour le définir, utilisez l'un ou l'autre :
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";
"@@global.time_zone variable" et "@@session.time_zone variable" peuvent renvoyer "SYSTEM", ce qui signifie qu'elles utilisent le fuseau horaire défini dans "my.cnf".
Pour que les noms de fuseau horaire fonctionnent (même pour le fuseau horaire par défaut), vous devez configurer vos tableaux d'informations sur les fuseaux horaires : http://dev.mysql.com/doc /refman/5.1/en/time-zone-support.html
Remarque :vous ne pouvez pas le faire car cela renverra NULL :
SELECT
CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime`
FROM `table_name`
Configurer les tables de fuseaux horaires mysql
Pour CONVERT_TZ
pour fonctionner, vous avez besoin que les tables de fuseaux horaires soient remplies
SELECT * FROM mysql.`time_zone` ;
SELECT * FROM mysql.`time_zone_leap_second` ;
SELECT * FROM mysql.`time_zone_name` ;
SELECT * FROM mysql.`time_zone_transition` ;
SELECT * FROM mysql.`time_zone_transition_type` ;
S'ils sont vides, remplissez-les en exécutant cette commande
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
si cette commande vous donne l'erreur "data too long for column 'abbreviation' at row 1 ", cela peut être dû à l'ajout d'un caractère NULL à la fin de l'abréviation du fuseau horaire
le correctif étant d'exécuter ceci
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
(if the above gives error "data too long for column 'abbreviation' at row 1")
mysql_tzinfo_to_sql /usr/share/zoneinfo > /tmp/zut.sql
echo "SET SESSION SQL_MODE = '';" > /tmp/mysql_tzinfo_to.sql
cat /tmp/zut.sql >> /tmp/mysql_tzinfo_to.sql
mysql --defaults-file=/etc/mysql/my.cnf --user=verifiedscratch -p mysql < /tmp/mysql_tzinfo_to.sql
(assurez-vous que les règles dst de vos serveurs sont à jour zdump -v Europe/Moscow | grep 2011
https://chrisjean.com/updating-daylight-saving-time- sur-linux/
)
Consultez l'historique complet des transitions DST (heure d'été) pour chaque fuseau horaire
SELECT
tzn.Name AS tz_name,
tztt.Abbreviation AS tz_abbr,
tztt.Is_DST AS is_dst,
tztt.`Offset` AS `offset`,
DATE_ADD('1970-01-01 00:00:00',INTERVAL tzt.Transition_time SECOND) AS transition_date
FROM mysql.`time_zone_transition` tzt
INNER JOIN mysql.`time_zone_transition_type` tztt USING(Time_zone_id, Transition_type_id)
INNER JOIN mysql.`time_zone_name` tzn USING(Time_zone_id)
-- WHERE tzn.Name LIKE 'Europe/Moscow' -- Moscow has weird DST changes
ORDER BY tzt.Transition_time ASC
CONVERT_TZ
applique également tous les changements d'heure d'été nécessaires en fonction des règles des tableaux ci-dessus et de la date que vous utilisez.
Remarque :
Selon les documents , la valeur que vous définissez pour time_zone ne change pas, si vous la définissez comme "+01:00" par exemple, alors le fuseau horaire sera défini comme un décalage par rapport à UTC, qui ne suit pas l'heure d'été, il restera donc le même tout toute l'année.
Seuls les fuseaux horaires nommés changera d'heure pendant l'heure d'été.
Des abréviations telles que CET
sera toujours une heure d'hiver et CEST
sera l'heure d'été tandis que +01:00 sera toujours UTC
temps + 1 heure et les deux ne changeront pas avec l'heure d'été.
Le system
timezone sera le fuseau horaire de la machine hôte sur laquelle mysql est installé (sauf si mysql ne parvient pas à le déterminer)
Vous pouvez en savoir plus sur l'utilisation de l'heure d'été ici
Quand ne pas utiliser UTC par le légendaire Jon Skeet :https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (Par exemple, un événement programmé dans le futur qui représente une heure, pas un instant dans le temps)
questions connexes :
- Comment définir le fuseau horaire de MySQL ?
- MySql - SELECT TimeStamp Column au format UTC
- Comment obtenir l'horodatage Unix dans MySQL à partir de l'heure UTC ?
- Conversion de l'horodatage MySQL du serveur en UTC
- https://dba. stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
- Comment faire J'obtiens le fuseau horaire actuel de MySQL ?
- Champs de date/heure MySQL et heure d'été -- comment puis-je référencer l'heure "supplémentaire" ?
- Convertir les valeurs négatives de FROM_UNIXTIME
Origine :
- https://bugs.mysql.com/bug.php?id=68861
- http://dev. mysql.com/doc/refman/5.0/en/date-and-time-functions.html
- http://dev.mysql.com/doc/ refman/5.1/en/datetime.html
- http://en.wikipedia.org/wiki/Coordinated_Universal_Time
- http://shafiqissani.wordpress.com/2010/09/30/how-to-get-the-current-epoch-time-unix-timestamp/
- https://web.ivy.net/~carton/ rant/MySQL-timezones.txt