Ваше заключение верное: нет надежного способа идентифицировать time zone от offset-from-UTC.
Для вашего примера смещения -07:00
, я насчитать около трех десятков возможных часовых поясов в том числе: the current listAmerica/Boise
, America/Chihuahua
и America/Edmonton
.
часовой пояс фактически коллекции смещений, запись изменений, сделанных в течение долгого времени с определенным смещение, используемое в этом регионе в течение определенного периода времени, но затем изменился за другой определенный период времени.
Например, в America/Los_Angeles
часть каждого года имеет смещение -08:00
, а другая часть года - -07:00
. Так что часовой пояс накапливает историю как минимум двух смещений в год. Напротив, соседняя область, использующая часовой пояс America/Phoenix
, составляет , а не, скопив изменения в ее смещении, сохранив при этом то же самое -07:00
смещение в течение десятилетий.
Таким образом, у нас есть соотношение «многие-ко-многим» между смещениями и часовыми поясами. Смещение может появляться в одном или нескольких часовых поясах. И каждый часовой пояс может иметь один или несколько смещений (изменившихся по истории).
Включить имя часового пояса
Именно поэтому конструкторы класса java.time ZonedDateTime
взяли на себя смелость его метода toString
расширяет стандартный формат ISO 8601 используя только коррекции также добавить название часового пояса в квадратных скобках.
Например, вместо простого создания стандартного формата: 2007-12-03T10:15:30+01:00
, класс генерирует 2007-12-03T10:15:30+01:00[Europe/Paris]
с именем зоны Europe/Paris прилагается.
ZonedDateTime.now(ZoneId.of("America/Montreal"))
.toString()
2007-12-03T10: 15: 30 + 01: 00 [Европа/Париж]
Я надеюсь, что эта практика добавления имени часового пояса улавливает. Отсутствие названия часового пояса является неожиданным упущением со стороны комитетов по стандартам, которые в ином случае выполняли выдающуюся работу по проектированию ISO 8601.
Вы можете: Угадать о часовом поясе, используя подсказки из контекста вашего бизнес-сценария. Но я советую против этого. Угадывание является рискованным, особенно потому, что политики во всем мире склонны часто менять часовые пояса.
UTC
Лучшие практики в хранении, сериализации и обмена значениями даты и времени, как правило, для регулировки в UTC. Предполагая, что дата-время библиотеки tzdata является актуальной, настройка в UTC обеспечивает надежное значение, которое всегда правильно и однозначно.
В Java, например, это означает использование или извлечение объекта Instant
. Класс Instant
представляет собой момент на временной шкале в UTC с разрешением nanoseconds (до девяти (9) цифр десятичной дроби).
Instant instant = Instant.now();
... или ...
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/Montreal"));
Instant instant = zdt.toInstant();
Стандарт ИСО 8601 отформатирован строка, представляющая такое значение использует Z
, как короткий для Zulu
и это означает UTC.
2007-12-03T09: 15: 30z
OffsetDateTime
Если вы получаете строку, представляющую дату и время с только смещение, разобрать его, как OffsetDateTime
объекта.
OffsetDateTime odt = OffsetDateTime.parse("2007-12-03T10:15:30+01:00");
odt.toString(): 2007-12-03T10: 15: 30 + 01: 00
Оттуда вы можете извлечь значение в формате UTC, в Instant
.
Instant instant = odt.toInstant();
instant.toString(): 2007-12-03T09: 15: 30z
Или вы можете настроить в нужном часовом поясе, чтобы получить тот же самый момент, как ZonedDateTime
объекта.
ZoneId z = ZoneId.of("Asia/Kolkata");
ZonedDateTime zdt = odt.atZoneSameInstant(z);
zdt.toString(): 2007-12-03T14: 45: 30 + 05: 30 [Азия/Калькутта]
Терминология: «местный»
Предлагаю вы избегаете термин «местный», когда ссылаетесь на дату, скорректированную на конкретный регион wall-clock time. Слово «local» в классах java.time и в других контекстах означает любое местоположение, а не определенную локальность. Местный дата-время не определенный момент на шкале времени, только приблизительное представление о диапазоне возможных моментов.
Например, местное время начала Рождества в этом году - 2017-12-25T00:00:00
, но этот момент полуночи намного раньше в Окленде, чем в Калькутте, а еще через несколько часов в Париже, а еще больше часов в Монреале.
Я предлагаю вместо этого использовать термины zoned
или wall-clock time
, когда вы имеете в виду конкретный момент, наблюдаемый через объектив определенного часового пояса.
Подсказка: Смещение литералы
Вопрос произошло использовать буквы -7
при упоминании смещения. Я предлагаю всегда:
- Использование двойных цифр с дополнением нулевой, в соответствии с требованиями ISO 8601
- Используя оба часа и минуты, как ожидалось некоторыми библиотеками и форматами.
Поэтому используйте -07:00
, а не -7
.
Это замечательно! Большое вам спасибо за то, что поделились своими знаниями. –