Почему TZ = UTC-8 производит даты с UTC + 8?

25

Текущее время в Лос-Анджелесе 18:05. Но когда я бегу TZ=UTC-8 date --iso=ns, я получаю:

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

Утилита date сообщает мне, что время 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.

CJM
источник
Ах, так что я действительно хотел 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):

Смещение указывает значение времени, которое вы должны добавить к местному времени, чтобы получить значение всемирного координированного времени. Он имеет синтаксис вроде [+ | -] чч [: мм [: сс]]. Это положительно, если местный часовой пояс находится к западу от премьер-меридиана, и отрицательно, если он восточнее. Час должен быть от 0 до 23, а минуты и секунды от 0 до 59.

Вот почему это похоже на то, что вы ожидаете.

jordanm
источник
2

Why?

Потому что POSIX требует этого .

Если перед ним стоит «-», часовой пояс должен быть восточнее премьер-меридиана; в противном случае он должен быть западным (что может быть указано необязательным предшествующим «+»).

Таким образом, это даст время около [1] Los Angeles (с любой трехбуквенной меткой для текста часового пояса):

$ 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] Близко, потому что может существовать некоторое летнее время, которое сдвигает фактическое «местное время».


источник
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)
SLM
источник
Я на самом деле пытаюсь узнать текущее время по тихоокеанскому стандартному времени, игнорируя переход на летнее время.
Алекс Генри
1
Я должен был понизить это, потому что вы предполагаете, что «UTC-8» неверен. Это правильно, он просто не делает то, что ожидает пользователь. Я не чувствую, что это отвечает на вопрос, почему это так работает.
Иордания
@jordanm - посмотри на уборку.
SLM
1
Это все еще объясняет, что происходит, но не почему, а «почему» - это то, что спрашивает ОП. Я уберу свое понижение, но я все еще не чувствую, что это хороший ответ на вопрос.
Иордания