Mysql
 sql >> Base de données >  >> RDS >> Mysql

Champs de date et d'heure MySQL et heure d'été -- comment puis-je faire référence à l'heure supplémentaire ?

Je l'ai compris pour mes besoins. Je vais résumer ce que j'ai appris (désolé, ces notes sont verbeuses ; elles sont autant pour ma future référence qu'autre chose).

Contrairement à ce que j'ai dit dans un de mes commentaires précédents, les champs DATETIME et TIMESTAMP font se comporter différemment. Les champs TIMESTAMP (comme l'indiquent les docs) prennent tout ce que vous leur envoyez au format "AAAA-MM-JJ hh:mm:ss" et le convertissent de votre fuseau horaire actuel en heure UTC. L'inverse se produit de manière transparente chaque fois que vous récupérez les données. Les champs DATETIME n'effectuent pas cette conversion. Ils prennent tout ce que vous leur envoyez et le stockent directement.

Ni les types de champs DATETIME ni TIMESTAMP ne peuvent stocker avec précision des données dans un fuseau horaire qui respecte l'heure d'été . Si vous stockez "2009-11-01 01:30:00", les champs n'ont aucun moyen de distinguer la version de 1h30 que vous vouliez -- la version -04:00 ou -05:00.

Ok, nous devons donc stocker nos données dans un fuseau horaire non DST (comme UTC). Les champs TIMESTAMP ne sont pas en mesure de gérer ces données avec précision pour des raisons que j'expliquerai :si votre système est défini sur un fuseau horaire DST, ce que vous mettez dans TIMESTAMP peut ne pas être ce que vous récupérez. Même si vous lui envoyez des données que vous avez déjà converties en UTC, il supposera toujours que les données sont dans votre fuseau horaire local et effectuera une autre conversion en UTC. Cet aller-retour local-vers-UTC-retour-vers-local imposé par TIMESTAMP est avec perte lorsque votre fuseau horaire local observe l'heure d'été (depuis "2009-11-01 01:30:00" correspond à 2 heures possibles différentes).

Avec DATETIME, vous pouvez stocker vos données dans le fuseau horaire de votre choix et être sûr que vous récupérerez tout ce que vous enverrez (vous n'êtes pas obligé de subir les conversions aller-retour avec perte que les champs TIMESTAMP vous imposent). La solution consiste donc à utiliser un champ DATETIME et avant d'enregistrer dans le champ convertir de votre fuseau horaire système dans n'importe quelle zone non DST dans laquelle vous souhaitez l'enregistrer (je pense que UTC est probablement la meilleure option). Cela vous permet de créer la logique de conversion dans votre langage de script afin que vous puissiez enregistrer explicitement l'équivalent UTC de "2009-11-01 01:30:00 -04:00" ou ""2009-11-01 01:30 :00 -05:00".

Une autre chose importante à noter est que les fonctions mathématiques de date/heure de MySQL ne fonctionnent pas correctement autour des limites DST si vous stockez vos dates dans un DST TZ. Raison de plus pour économiser en UTC.

En un mot, je fais maintenant ceci :

Lors de la récupération des données de la base de données :

Interprétez explicitement les données de la base de données comme UTC en dehors de MySQL afin d'obtenir un horodatage Unix précis. J'utilise la fonction strtotime() de PHP ou sa classe DateTime pour cela. Cela ne peut pas être fait de manière fiable à l'intérieur de MySQL en utilisant les fonctions CONVERT_TZ() ou UNIX_TIMESTAMP() de MySQL car CONVERT_TZ ne sortira qu'une valeur 'YYYY-MM-DD hh:mm:ss' qui souffre de problèmes d'ambiguïté, et UNIX_TIMESTAMP() assume son l'entrée est dans le fuseau horaire du système, et non dans le fuseau horaire dans lequel les données ont été réellement stockées (UTC).

Lors du stockage des données dans la base de données :

Convertissez votre date à l'heure UTC précise que vous désirez en dehors de MySQL. Par exemple :avec la classe DateTime de PHP, vous pouvez spécifier "2009-11-01 1:30:00 EST" distinctement de "2009-11-01 1:30:00 EDT", puis le convertir en UTC et enregistrer l'heure UTC correcte à votre champ DATETIME.

Phew. Merci beaucoup pour l'apport et l'aide de chacun. Espérons que cela évite à quelqu'un d'autre des maux de tête sur la route.

BTW, je vois ceci sur MySQL 5.0.22 et 5.0.27