Чому TZ = UTC-8 створює дати, які є UTC + 8?


25

Поточний час у Лос-Анджелесі о 18:05. Але коли я біжу TZ=UTC-8 date --iso=ns, я отримую:

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

Утиліта дати повідомляє мені, що час 10:05, і навіть каже, що вона повідомляє про це як UTC + 8. Чому?

Відповіді:


33

Причина в тому, що TZ=UTC-8інтерпретується як часовий пояс POSIX . У форматі часового поясу POSIX 3 букви - це абревіатура часового поясу (яка є довільною), а кількість - кількість годин, за якими часовий пояс знаходиться за UTC. Значить, UTC-8часовий пояс скорочено "UTC", який на −8 годин відстає від реального UTC, або UTC + 8 годин.

(Це працює так, тому що Unix був розроблений в США, який відстає від UTC. Цей формат дозволяє часовим поясам США представлятись як EST5, CST6 тощо)

Ви можете бачити, що відбувається за цими прикладами:

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

Формат -0800часового поясу ISO застосовує протилежний підхід, із -зазначенням, що зона відстає від UTC, а +зона - попереду UTC.


Так, я дуже хотів TZ=PST+8 date. Спасибі. Це пояснення я також знайшов під заголовком man timezone: "Строка std вказує назву часового поясу і повинна містити три або більше алфавітних символів. Зсувна рядок негайно слідує за std і визначає значення часу, яке потрібно додати до місцевого часу для отримання загального координованого часу ( UTC). Зсув є позитивним, якщо місцевий часовий пояс знаходиться на захід від головного меридіана, і негативним, якщо він є східним. Година повинна становити між 0 і 24, а хвилини та секунди - 0 і 59 ".
Алекс Генрі

3
@ Алекс ні, те, що ти насправді хочеш TZ=America/Los_Angeles. Ви забуваєте, що тихоокеанський час становить -7 під час літнього часу.
Метт Джонсон-Пінт

3
@MattJohnson, ти маєш на увазі TZ=:America/Los_Angeles. Двокрапка вказує, що це файл часового поясу Олсона. І в іншому коментарі він зазначив, що хоче ігнорувати літній час, що це не зробить.
cjm

@cjm, Спасибі, ти маєш рацію щодо товстої кишки, і я не бачив цього коментаря.
Метт Джонсон-Пінт

Америку, викликай світ, якщо це означає, що ми маємо бути EST-5 CST-6.
Еван Керролл

7

Щоразу, коли ви задаєте часовий пояс у форматі +/- 00:00, ви вказуєте зміщення , а не фактичний часовий пояс. З GNU libc документації (яка відповідає стандарту POSIX):

Зсув визначає значення часу, яке потрібно додати до місцевого часу, щоб отримати координоване загальне значення часу. Він має синтаксис, як [+ | -] hh [: mm [: ss]]. Це позитивно, якщо місцевий часовий пояс знаходиться на захід від головного меридіана і негативний, якщо він східний. Година повинна становити між 0 і 23, а хвилина і секунди між 0 і 59.

Ось чому це, здається, є зворотним для того, що ви очікуєте.


2

Why?

Тому що POSIX цього вимагає .

Якщо передує "-", часовий пояс знаходиться на схід від основного меридіана; в іншому випадку це захід (що може бути позначено необов'язковим попереднім "+").

Отже, це дасть час поблизу [1] Los Angeles (з будь-якою 3-літерною міткою для тексту часового поясу):

$ 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

І це повинно дати час поруч Shanghai, Chinaабо 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] Поруч, оскільки може бути деякий DST (літній час), який змінює фактичний "місцевий час".


1

Як альтернативний метод, ви можете використовувати команду zdumpдля відображення поточного часу в інших часових поясах + зміщення.

Zdump друкує поточний час у кожній назві зони, названій у командному рядку.

Такі ж правила застосовуються і до часових поясів; на захід від основного меридіана "позаду", а на сході - "попереду".

Приклад

$ zdump PST PST Сб 7 грудня 03:25:27 2013 PST

Я створив цей сценарій, щоб показати декілька часових поясів + зміщення, які ми зацікавлені в використанні, zdumpі dateми могли б порівняти їх.

$ 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

Тоді при запуску ви можете побачити порівняння 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)

Я насправді намагаюся отримати поточний час у тихоокеанський стандартний час, ігноруючи літній час.
Алекс Генрі

1
Мені довелося порушити цю заяву, оскільки ви здогадуєтесь, що "UTC-8" невірно. Це правильно, він просто не робить те, що очікує користувач. Я не відчуваю, що це відповідає на питання, чому це працює саме так.
Йорданм

@jordanm - див. прибирання.
slm

1
Це все ще пояснює, що відбувається, але не чому і "чому" - це те, що задається ОП. Я вилучу свій потік, але все ще не відчуваю, що це гарна відповідь на питання.
jordanm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.