Время Java отличается от времени ОС - PullRequest
0 голосов
/ 09 сентября 2018

Когда я печатаю дату в Unix, она показывает время UTC

[app@host ~]$ date
Thu Sep  6 21:16:07 UTC 2018

Когда я печатаю дату из Java на том же компьютере

public static void main(String[] args) {
  System.out.println("date=" + new Date());
  System.out.println("date from mills=" + new Date(System.currentTimeMillis()));
  System.out.println(TimeZone.getDefault().getDisplayName());

  Instant instant = Instant.now();
  System.out.println("instant=" + instant);
  System.out.println("instant from mills=" + new Date(instant.toEpochMilli()));
}

печатает время PST

[app@host ~]$ java TimeTest
date=Thu Sep 06 14:17:09 PDT 2018
date from mills=Thu Sep 06 14:17:09 PDT 2018
Pacific Standard Time
instant=2018-09-06T21:17:09.030Z
instant from mills=Thu Sep 06 14:17:09 PDT 2018

Как Java получает часовой пояс PST?

Кроме того, ротация файла журнала происходит во время UTC, а время, указанное в файле журнала, показывает время PST.

1 Ответ

0 голосов
/ 09 сентября 2018

ТЛ; др

Использовать только java.time классы.

Никогда не используйте Date класс.

Используйте UTC при регистрации.

Instant.now().toString()

2018-01-23T01: 23: 45.123456Z

Подробнее

Это уже много раз решалось при переполнении стека.

Ужасные старые классы даты и времени изобилуют неудачным выбором дизайна. Среди этих неудачных вариантов - поведение метода Date::toString динамического применения текущего часового пояса JVM по умолчанию при генерации строки. Благонамеренный, но вводящий в заблуждение, как java.util.Date, как java.time.Instant, представляет момент в UTC.

6 сентября этого года в 22:00 по западному побережью большей части Северной Америки одновременно происходит 21:00 по UTC со смещением от UTC на семь часов после UTC в летнее время (DST). Тот же самый момент, та же самая точка на временной шкале, другое время настенных часов.

Почему ФДТ?

Почему, в частности, тихоокеанское летнее время? Ваша JVM всегда имеет текущий часовой пояс по умолчанию. По-видимому, для вашей JVM установлена ​​текущая зона по умолчанию, такая как America/Los_Angeles (PDT не является часовым поясом реального времени).

Способ установки этого значения по умолчанию зависит от реализации JVM и ваших настроек. Обычно JVM при запуске обнаруживает текущую зону по умолчанию операционной системы хоста. Вы можете передать аргументы при запуске JVM, чтобы указать зону, а не выбрать по умолчанию хост-ОС.

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

Это означает, что вы никогда не должны полагаться на текущую зону по умолчанию для чего-то критического, так как ее значение не зависит от вас, как программиста. Всегда указывайте желаемый / ожидаемый часовой пояс в явном виде. Даже если вы хотите использовать текущее значение по умолчанию, сделайте явный вызов ZoneId.systemDefault.

Бонусный совет: То же самое для Locale. Всегда текущий по умолчанию. Но указывайте явно, а не полагайтесь неявно по умолчанию.

Использование java.time

Никогда не используйте устаревшие классы дат. Используйте только java.time классы.

При ведении журнала всегда используйте UTC. Визуализация текста в стандартном формате ISO 8601, как показано в Instant::toString.

Instant instant = Instant.now() ;

Если вы хотите просмотреть этот момент в часах настенного времени, используемых людьми определенного региона, примените часовой пояс (ZoneId), чтобы получить ZonedDateTime.

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java.time классы.

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

...