Есть ли разница между java.time.Clock.systemDefaultZone(). GetZone() и java.util.TimeZone.getDefault(). ToZoneId()?

Есть ли разница между ними, учитывая, что оба java.time.Clock.systemDefaultZone().getZone() а также java.util.TimeZone.getDefault().toZoneId() вернуть тот же вывод.

Например, этот код

import java.time.Clock;
import java.util.TimeZone;

public class Main {

  public static void main(String[] args) {
    System.out.println("Clock.systemDefaultZone().getZone() : " 
        + Clock.systemDefaultZone().getZone());
    System.out.println("TimeZone.getDefault().toZoneId() : " 
        + TimeZone.getDefault().toZoneId());
  }

}

возвращает этот вывод

Clock.systemDefaultZone().getZone() : Europe/Paris
TimeZone.getDefault().toZoneId() : Europe/Paris

2 ответа

Решение

Оба возвращают часовой пояс JVM по умолчанию (в конце Clock звонки TimeZone.getDefault(), как объясняется в ответе @Kiskae), но не гарантируется, что все вызовы всегда будут возвращать одно и то же значение каждый раз.

Это потому, что часовой пояс по умолчанию можно изменить:

  • система, в которой работает JVM, может изменить свою конфигурацию. Например, на компьютерах с Windows эта информация считывается из реестра, а в Linux - из /etc/localtime (обычно ссылка на конкретный файл в /usr/share/zoneinfo) или другую аналогичную папку (она может варьироваться в зависимости от версии / дистрибутива) или путем установки TZ переменная окружения. Если эта конфигурация системы меняет ее и JVM перезапускается, ваш код неожиданно начинает возвращать разные значения
  • JVM может быть настроен на использование другого часового пояса, независимо от конфигурации ОС. Одним из примеров является случай, когда команда по обслуживанию / инфраструктуре изменяет эту конфигурацию (намеренно или случайно, и обычно не сообщая разработчикам...), и тогда ваш код больше не возвращает те же значения (и все, что зависит от часового пояса, будет вдруг сломается)
  • ваше приложение (или другое приложение с той же JVM) вызывает TimeZone.setDefault() метод. Это повлияет на все приложения, работающие в той же JVM, во время выполнения, поэтому, если вы запустите этот код:

    TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
    System.out.println(ZoneId.systemDefault());
    
    TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
    System.out.println(ZoneId.systemDefault());
    
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    System.out.println(ZoneId.systemDefault());
    

Выход будет:

Европа / Лондон
Америка / Триатлон
универсальное глобальное время

Обратите внимание, как легко часовой пояс по умолчанию изменяется во время выполнения, и на все последующие вызовы, чтобы получить его, влияют. То же самое произойдет, если вы позвоните Clock.systemDefaultZone().getZone() или же TimeZone.getDefault().toZoneId()потому что оба используют часовой пояс по умолчанию.

Поскольку это изменяет часовой пояс JVM по умолчанию, все приложения, работающие в той же JVM, будут затронуты этим. Это может привести к неожиданным ошибкам, которые трудно отладить.

Хотя методы, использующие часовой пояс по умолчанию, удобны, вы должны проверить, как от этого зависит ваш код и как на него может повлиять изменение зоны.

Если вы не хотите зависеть от значения по умолчанию, идеальным вариантом является использование определенного часового пояса, такого как ZoneId.of("Europe/Paris"), Всегда предпочитайте имена часовых поясов IANA (всегда в формате Region/City, лайк America/New_York или же Europe/Paris). Избегайте использования коротких сокращений (например, CET или же CEST) потому что они неоднозначны и не стандартны.

Вы можете получить список доступных часовых поясов (и выбрать тот, который лучше всего подходит вашей системе), позвонив ZoneId.getAvailableZoneIds(),

Глядя на исходный код grepcode, они в конечном итоге выполняют те же самые методы, что приводит к тому же результату. Clock.systemDefaultZone() звонки ZoneId.systemDefault(), который возвращает TimeZone.getDefault().toZoneId():

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/time/ZoneId.java#ZoneId.systemDefault%28%29

Другие вопросы по тегам