Pourquoi TZ = UTC-8 produit-il des dates UTC + 8?

25

L'heure actuelle à Los Angeles est 18h05. Mais quand je cours TZ=UTC-8 date --iso=ns, je reçois:

2013-12-07T10:05:37,788173835+0800

L'utilitaire de date me dit que l'heure est 10h05 et dit même qu'il le signale en UTC + 8. Pourquoi?

Alex Henrie
la source

Réponses:

33

La raison en est qu'il TZ=UTC-8est interprété comme un fuseau horaire POSIX . Dans le format de fuseau horaire POSIX, les 3 lettres sont l'abréviation du fuseau horaire (qui est arbitraire) et le nombre est le nombre d'heures que le fuseau horaire est derrière UTC. Signifie donc UTC-8un fuseau horaire abrégé "UTC" qui est à -8 heures de retard sur le UTC réel, ou UTC + 8 heures.

(Cela fonctionne de cette façon car Unix a été développé aux États-Unis, derrière l'UTC. Ce format permet aux fuseaux horaires américains d'être représentés sous la forme EST5, CST6, etc.)

Vous pouvez voir ce qui se passe par ces exemples:

$ TZ=UTC-8 date +'%Z %z'
UTC +0800
$ TZ=UTC8 date +'%Z %z'
UTC -0800
$ TZ=FOO-8 date +'%Z %z'
FOO +0800

Le -0800format de fuseau horaire ISO adopte l'approche inverse, en -indiquant que la zone est derrière UTC et en +indiquant que la zone est en avance sur UTC.

cjm
la source
Ah donc ce que je voulais vraiment c'était TZ=PST+8 date. Merci. J'ai également trouvé cette explication sous man timezone: "La chaîne std spécifie le nom du fuseau horaire et doit comporter au moins trois caractères alphabétiques. La chaîne de décalage suit immédiatement std et spécifie la valeur d'heure à ajouter à l'heure locale pour obtenir le temps universel coordonné ( UTC). Le décalage est positif si le fuseau horaire local est à l'ouest du méridien principal et négatif s'il est à l'est. L'heure doit être comprise entre 0 et 24, et les minutes et secondes 0 et 59. "
Alex Henrie
3
@Alex non, ce que tu veux vraiment, c'est TZ=America/Los_Angeles. Vous oubliez que l'heure du Pacifique est de -7 pendant l'heure d'été.
Matt Johnson-Pint
3
@MattJohnson, tu veux dire TZ=:America/Los_Angeles. Les deux points indiquent qu'il s'agit d'un fichier de fuseau horaire Olson. Et dans un autre commentaire, il a mentionné qu'il voulait ignorer l'heure d'été, ce que cela ne ferait pas.
cjm
@cjm, merci, vous avez raison pour le colon, et je n'avais pas vu ce commentaire.
Matt Johnson-Pint
Amérique, cause du monde si cela signifie que nous devons l'être EST-5 CST-6.
Evan Carroll
7

Chaque fois que vous spécifiez un fuseau horaire au format +/- 00:00, vous spécifiez un décalage , pas le fuseau horaire réel. De la GNU libc documentation (qui suit la norme POSIX):

Le décalage spécifie la valeur de temps que vous devez ajouter à l'heure locale pour obtenir une valeur de temps universel coordonné. Il a une syntaxe comme [+ | -] hh [: mm [: ss]]. Ceci est positif si le fuseau horaire local est à l'ouest du méridien principal et négatif s'il est à l'est. L'heure doit être comprise entre 0 et 23, et les minutes et secondes entre 0 et 59.

C'est pourquoi cela semble être l'inverse de ce que vous attendez.

jordanm
la source
2

Why?

Parce que POSIX l'exige .

S'il est précédé d'un «-», le fuseau horaire doit être à l'est du premier méridien; sinon, il doit être ouest (ce qui peut être indiqué par un «+» précédent facultatif).

Ainsi, cela donnera l'heure près de [1] Los Angeles (avec n'importe quelle étiquette de 3 lettres pour le texte du fuseau horaire):

$ TZ=ANY8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 10:47:12 ANY-0800

$ TZ=GMT+8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 10:47:12 GMT-0800

Et cela devrait donner le temps proche Shanghai, Chinaou Perth, Australia:

$ TZ=ANY-8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-24 02:47:12 ANY+0800

$ TZ=CST-8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 02:47:12 CST+0800

[1] Proche car il peut y avoir un DST (Daylight Saving Time) en effet qui décale l'heure locale réelle.


la source
1

Comme méthode alternative, vous pouvez utiliser la commande zdumppour afficher l'heure actuelle dans d'autres fuseaux horaires + décalages.

Zdump imprime l'heure actuelle dans chaque nom de zone nommé sur la ligne de commande.

Les mêmes règles s'appliquent aux fuseaux horaires; à l'ouest du méridien principal étant "derrière" tandis qu'à l'est étant "devant".

Exemple

$ zdump PST PST sam 7 déc 03:25:27 2013 PST

J'ai créé ce script pour afficher plusieurs fuseaux horaires + décalages que nous souhaitons utiliser zdumpet datepour pouvoir les comparer.

$ cat cmd.bash
#!/bin/bash

printf "\ndate: %s\n\n" "$(date)"

for tz in EST PST PST+8 PST-8 UTC UTC+8 UTC-8; do
  echo "-- timezone $tz"
  printf "zdump: %s\n" "$(zdump $tz)"
  printf "date:         %s\n" "$(TZ=$tz date +'%a %b %d %T %Y - (%Z %z)')"
  echo ""
done

Ensuite, lorsque vous l'exécutez, vous pouvez voir la comparaison de zdumpà date:

$ ./cmd.bash 

date: Sat Dec  7 02:59:05 EST 2013

-- timezone EST
zdump: EST  Sat Dec  7 02:59:05 2013 EST
date:         Sat Dec 07 02:59:05 2013 - (EST -0500)

-- timezone PST
zdump: PST  Sat Dec  7 07:59:05 2013 PST
date:         Sat Dec 07 07:59:05 2013 - (PST +0000)

-- timezone PST+8
zdump: PST+8  Fri Dec  6 23:59:05 2013 PST
date:         Fri Dec 06 23:59:05 2013 - (PST -0800)

-- timezone PST-8
zdump: PST-8  Sat Dec  7 15:59:05 2013 PST
date:         Sat Dec 07 15:59:05 2013 - (PST +0800)

-- timezone UTC
zdump: UTC  Sat Dec  7 07:59:05 2013 UTC
date:         Sat Dec 07 07:59:05 2013 - (UTC +0000)

-- timezone UTC+8
zdump: UTC+8  Fri Dec  6 23:59:05 2013 UTC
date:         Fri Dec 06 23:59:05 2013 - (UTC -0800)

-- timezone UTC-8
zdump: UTC-8  Sat Dec  7 15:59:05 2013 UTC
date:         Sat Dec 07 15:59:05 2013 - (UTC +0800)
slm
la source
J'essaie en fait d'obtenir l'heure actuelle en heure normale du Pacifique, en ignorant l'heure d'été.
Alex Henrie
1
J'ai dû déprécier celui-ci car vous devinez que "UTC-8" est incorrect. C'est correct, il ne fait tout simplement pas ce que l'utilisateur attend. Je ne pense pas que cela réponde à la question de savoir pourquoi cela fonctionne de cette façon.
jordanm
@jordanm - voir le nettoyage.
slm
1
Il explique toujours ce qui se passe mais pas pourquoi et "pourquoi" est ce que OP demande. Je vais supprimer mon downvote mais je n'ai toujours pas l'impression que c'est une bonne réponse à la question.
jordanm