Pourquoi TZ = UTC-8 produire des dates qui sont UTC + 8?

L'heure actuelle à Los Angeles est 18:05. Mais quand je cours TZ=UTC-8 date --iso=ns , j'obtiens:

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

L'utilitaire de date me dit que l'heure est 10:05, et dit même qu'il le rapporte comme UTC + 8. Pourquoi?

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

(Cela fonctionne parce qu'Unix a été développé aux États-Unis, ce qui est derrière l'UTC. Ce format permet aux fuseaux horaires américains d'être représentés par EST5, CST6, etc.)

Vous pouvez voir que c'est 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 format de timezone ISO -0800 prend l'approche inverse, avec - indiquant que la zone est derrière UTC, et + indiquant que la zone est en avance sur UTC.

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

Le décalage spécifie la valeur de time que vous devez append à l'heure locale pour get une valeur de time universel coordonné. Il a la syntaxe comme [+ | -] hh [: mm [: ss]]. Ceci est positif si le timezone local est à l'ouest du premier méridien et négatif s'il est à l'est. L'heure doit être comprise entre 0 et 23 et la minute et la seconde entre 0 et 59.

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

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

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

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

Exemple

$ zdump PST PST Sat Dec 7 03:25:27 PST 2013

J'ai fait ce script pour montrer plusieurs des fuseaux horaires + offsets que nous sums intéressés à utiliser zdump et la date afin que nous puissions 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 

Puis quand 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) 

Why?

Parce que POSIX le requirejs .

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

Donc, cela donnera du time près de [1] Los Angeles (avec n'importe quelle label de 3 lettres pour le timezone du text):

 $ 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 time près de Shanghai, China ou 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] Near car il peut y avoir un certain DST (Daylight Saving Time) qui change l'actuelle "heure locale".