web-dev-qa-db-fra.com

MySQL CONVERT_TZ ()

J'essaie de mettre en place une base de données qui stocke les heures d'alerte quotidiennes spécifiées par les utilisateurs. Par exemple, l'utilisateur souhaite recevoir une alerte si un critère est respecté chaque jour entre 7h00 et 7h30. En essayant de mettre en œuvre cela, je dois tenir compte de l'heure d'été. Voici ma tentative de solution:

  1. Stockez les informations du fuseau horaire local des utilisateurs (sous forme longue, par exemple "US/Eastern") dans une table (par exemple userInfo) et les heures d'alarme dans une autre table (par exemple userAlarms).
  2. Lors de l'interrogation de la table userAlarms, convertissez l'heure UTC en heure locale des utilisateurs comme spécifié par la colonne tz stockée dans la table userInfo via CONVERT_TZ(UTC_TIME(), 'UTC', userInfo.tz).

Question 1. D'après ma compréhension, en spécifiant le nom du fuseau horaire (comme US/Eastern) devrait prendre en compte l'heure d'été. Par exemple, l'appel de CONVERT_TZ('00:00:00', 'UTC', 'US/EASTERN') le 1er janvier devrait donner '19: 00: 00 ', mais le 1er juillet, l'appel devrait donner '20: 00: 00'. Ai-je raison?

Question 2. Si Q1 est correct, dois-je constamment mettre à jour la table des fuseaux horaires de MySQL pour garder les décalages UTC de fuseau horaire à jour?

Question 3. L'exemple donné dans la documentation MySQL SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET') donne "NULL" lorsqu'il est exécuté sur mon serveur. Cela peut-il être dû au fait que les tables de fuseaux horaires ne sont pas configurées?

Comment puis-je vérifier cela?

37
johnnyspo

Si cela donne null alors les tables TZ n'ont pas été configurées:

SELECT CONVERT_TZ(now(),'US/Eastern','US/Central');

Si vous n'avez pas configuré les tables de fuseaux horaires, vous pouvez mettre à jour le décalage horaire dans la table utilisateur, puis procédez comme suit:

select utc_timezone() - interval user_timezone_offset_in_hours hour
from userinfo a
where user_id = 999;

Cependant, vous auriez toujours besoin d'un moyen de mettre à jour le fuseau horaire de l'utilisateur.

Si vous écrivez ceci pour une application Web, vous pouvez obtenir le fuseau horaire via javascript, voici un article qui décrit comment (je n'ai pas essayé cela mais il semble que cela fonctionnera).

Un peu d'explication par rapport à 'intervalle' ci-dessus ...

L'une des constructions les plus astucieuses de MySQL est l'utilisation du mot clé INTERVAL, mieux illustré par l'exemple (la valeur numérique peut être une expression ou la valeur du champ)

select now() today, now() - interval 1 day yesterday;
+---------------------+---------------------+
| today               | yesterday           |
+---------------------+---------------------+
| 2011-05-26 13:20:55 | 2011-05-25 13:20:55 |
+---------------------+---------------------+

Vous pouvez les ajouter et les soustraire comme vous le souhaitez, c'est pourquoi je ne me dérange jamais avec les fonctions d'ajout/soustraction/conversion de date/heure

select now() a, now() - interval 1 day + interval 4 hour + interval 8 minute b;
+---------------------+---------------------+
| a                   | b                   |
+---------------------+---------------------+
| 2011-05-26 13:24:16 | 2011-05-25 17:32:16 |
+---------------------+---------------------+

Vous pouvez utiliser des nombres négatifs (devrait être bon pour les décalages de fuseau horaire négatifs), ce sont les mêmes:

select now() - interval 1 month a, now() + interval -1 month b;
+---------------------+---------------------+
| a                   | b                   |
+---------------------+---------------------+
| 2011-04-26 13:38:05 | 2011-04-26 13:38:05 |
+---------------------+---------------------+
27
dave

J'ai trouvé ce fil utile et j'ai décidé de partager la page doc pour importer ces informations. J'ai fait exactement comme indiqué ci-dessous dans CentOS et dans RHEL et cela a fonctionné parfaitement. Je peux maintenant utiliser la fonction CONVERT_TZ avec des arguments comme "GMT" et "US/Eastern".

À partir de la documentation MySQL, voici comment importer les informations de la table des fuseaux horaires MySQL:

http://dev.mysql.com/tech-resources/articles/4.1/time.html


Pour tous les utilisateurs exécutant MySQL 4.1.3 ou version ultérieure sur un système basé sur Unix (rappelez-vous que cela ne fonctionne pas encore sur les systèmes Windows):

Remplissez les tables de fuseaux horaires.

Pour ce faire, exécutez le mysql_tzinfo_to_sql programme, fourni avec la distribution MySQL. mysql_tzinfo_to_sql lit les fichiers de fuseau horaire du système d'exploitation et en génère des instructions SQL. Les instructions SQL sont ensuite traitées par mysql, pour charger les tables de fuseaux horaires.

Courir mysql_tzinfo_to_sql avec succès, il faut savoir où sont stockés les fichiers de fuseau horaire du système d'exploitation de la machine serveur; rechercher un répertoire avec un nom similaire à /usr/share/zoneinfo. Passez le nom du répertoire sur la ligne de commande à mysql_tzinfo_to_sql, et envoyer la sortie dans le programme mysql. Voici un exemple.

Shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

Remarque: La commande ci-dessus suppose que "mysql_tzinfo_to_sql" et "mysql" se trouvent sur votre chemin. Si ce n'est pas le cas, vous devrez fournir le chemin d'accès complet aux deux lors de l'exécution de la commande, ou basculer dans le dossier bin mysql et utiliser une commande comme celle-ci:

Shell> ./mysql_tzinfo_to_sql /usr/share/zoneinfo | ./mysql -u root mysql
25
philwinkle

Q1: Oui, le CONVERT_TZ prend en compte l'heure d'été pour vous. Ces informations et l'heure de début/fin de l'heure d'été pour chaque fuseau horaire sont stockées dans les tables time_zone_ *.

Q2: Oui, comme indiqué dans la documentation mysql, les informations de fuseau horaire changent en fonction de la politique de chaque zone. Vous devrez mettre à jour les tables time_zone_ * à chaque fois qu'un changement se produit. Ça craint d'être IT parfois, c'est l'un d'entre eux.

Q3: Ce sont les 5 tables de fuseau horaire, interrogez-les pour voir si elles contiennent quelque chose:

select * from mysql.time_zone_transition_type;
select * from mysql.time_zone_transition;
select * from mysql.time_zone_name;
select * from mysql.time_zone_leap_second;
select * from mysql.time_zone;
19
David Parks