Dlaczego TZ = UTC-8 tworzy daty, które są UTC + 8?

25

Aktualny czas w Los Angeles to 18:05. Ale kiedy biegnę TZ=UTC-8 date --iso=ns, dostaję:

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

Narzędzie daty mówi mi, że jest godzina 10:05, a nawet twierdzi, że zgłasza to jako UTC + 8. Czemu?

Alex Henrie
źródło

Odpowiedzi:

33

Powodem jest to, że TZ=UTC-8jest interpretowana jako strefa czasowa POSIX . W formacie strefy czasowej POSIX trzy litery to skrót strefy czasowej (który jest dowolny), a liczba to liczba godzin, za którymi strefa czasowa znajduje się za czasem UTC. Więc UTC-8oznacza strefę czasową, w skrócie „UTC”, który jest -8 godziny za realną UTC, czyli UTC + 8 godzin.

(Działa to w ten sposób, ponieważ Unix został opracowany w USA, który stoi za UTC. Ten format umożliwia reprezentowanie stref czasowych w USA jako EST5, CST6 itp.)

Możesz zobaczyć, co dzieje się w tych przykładach:

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

-0800Format strefy czasowej ISO przyjmuje odwrotne podejście, -wskazując, że strefa znajduje się za UTC, a +strefa wyprzedza UTC.

cjm
źródło
Ach, więc tak naprawdę chciałem TZ=PST+8 date. Dzięki. Znalazłem również to wyjaśnienie w man timezone: „Ciąg std określa nazwę strefy czasowej i musi składać się z co najmniej trzech znaków alfabetycznych. Ciąg przesunięcia bezpośrednio następuje po std i określa wartość czasu, którą należy dodać do czasu lokalnego, aby uzyskać uniwersalny czas koordynowany ( UTC). Przesunięcie jest dodatnie, jeśli lokalna strefa czasowa znajduje się na zachód od Prime Meridian, i ujemne, jeśli jest na wschód. Godzina musi wynosić od 0 do 24, a minuty i sekundy 0 i 59. ”
Alex Henrie,
3
@Alex nie, naprawdę chcesz TZ=America/Los_Angeles. Zapominasz, że czas pacyficzny wynosi -7 w czasie letnim.
Matt Johnson-Pint,
3
@MattJohnson, masz na myśli TZ=:America/Los_Angeles. Dwukropek wskazuje, że jest to plik strefy czasowej Olsona. W innym komentarzu wspomniał, że chciałby zignorować czas letni, co by tego nie zrobiło.
cjm
@cjm, Dzięki, masz rację co do jelita grubego i nie widziałem tego komentarza.
Matt Johnson-Pint,
Ameryka, bo świat, jeśli to oznacza, że ​​musimy być EST-5 CST-6.
Evan Carroll
7

Ilekroć określisz strefę czasową w formacie +/- 00:00, określasz przesunięcie , a nie rzeczywistą strefę czasową. Z GNU libc dokumentacji (zgodnej ze standardem POSIX):

Przesunięcie określa wartość czasu, którą należy dodać do czasu lokalnego, aby uzyskać wartość uniwersalnego czasu koordynowanego. Ma składnię taką jak [+ | -] hh [: mm [: ss]]. Jest to pozytywne, jeśli lokalna strefa czasowa znajduje się na zachód od głównego południka, a ujemne, jeśli jest na wschodzie. Godzina musi wynosić od 0 do 23, a minuty i sekundy od 0 do 59.

Dlatego wydaje się, że jest odwrotnością tego, czego oczekujesz.

Jordan
źródło
2

Why?

Ponieważ POSIX tego wymaga .

Jeśli poprzedza ją „-”, strefa czasowa będzie na wschód od Pierwszego Południka; w przeciwnym razie będzie na zachód (co może być oznaczone opcjonalnym poprzedzającym „+”).

To da czas w pobliżu [1] Los Angeles (z dowolną trzyliterową etykietą dla tekstu strefy czasowej):

$ 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

To powinno dać czas w pobliżu Shanghai, Chinalub 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] Blisko, ponieważ może istnieć jakiś czas letni, który zmienia rzeczywisty „czas lokalny”.


źródło
1

Jako alternatywną metodę możesz użyć polecenia, zdumpaby wyświetlić bieżący czas w innych strefach czasowych + przesunięcia.

Zdump drukuje aktualny czas w każdej nazwie strefy z nazwy w wierszu poleceń.

Te same zasady obowiązują w strefach czasowych; na zachód od głównego południka jest „z tyłu”, a na wschodzie jest „z przodu”.

Przykład

$ zdump PST PST sob. 7 grudnia 03:25:27 2013 PST

Zrobiłem ten skrypt, aby pokazać kilku stref czasowych + ofsetów jesteśmy zainteresowani w użyciu zdump, a datewięc możemy je porównać.

$ 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

Wtedy, kiedy go uruchomić można zobaczyć porównanie zdumpdo 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
źródło
Właściwie próbuję uzyskać bieżący czas w Pacyfiku, ignorując czas letni.
Alex Henrie,
1
Musiałem głosować za tym, ponieważ zgadujesz, że „UTC-8” jest niepoprawny. To prawda, po prostu nie robi tego, czego oczekuje użytkownik. Nie sądzę, że odpowiada na pytanie, dlaczego tak działa.
jordanm,
@jordanm - zobacz porządki.
slm
1
Wciąż wyjaśnia, co się dzieje, ale nie dlaczego i dlaczego pyta OP. Usunę moją opinię, ale nadal nie wydaje mi się, aby była to dobra odpowiedź na pytanie.
jordanm