Правильно работать с високосными секундами

До и во время високосного new Date() вернется 23:59:59 дважды (один раз перед високосной секундой и один раз в течение високосной секунды), а не 23:59:59 и 23:59:60.

Есть ли способ (кроме реализации NTP-клиента в приложении или проверки времени, чтобы часы пошли назад или повторились), чтобы определить, является ли данная секунда високосной или нет, чтобы правильно представить 23:59: 60 пользователю?

В связи с этим, имеют ли операционные системы хоста какие-либо хуки, чтобы определить, является ли это до или после високосной секунды?

2 ответа

Давайте посмотрим на исходный код java.util.Date:

public Date() {
    this(System.currentTimeMillis());
}

Так что вопрос можно прочитать как:

Будет System.currentTimeMillis() дать значение високосной секунды 60 или даже 61 (как претендует спецификация)?

Ответ в строгом смысле: это зависит от базовой операционной системы. Но факт таков: все известные операционные системы, такие как Windows, Linux, Apple, Android, не знают о високосных секундах. Вместо этого эти операционные системы производят любые манипуляции с часами в любое время (восстановление настроек и т. Д., Синхронизация с NTP-сервером...). Таким образом, вы не будете наблюдать дополнительную секунду, используя Date -API. Между прочим, значение 61 невозможно, потому что стандарт UTC предписывает, что UTC никогда не отклонится от UT1 более чем на 0,9 секунды, в результате чего не будет вставлена ​​двойная високосная секунда.

Происхождение "61" - просто грубое недоразумение из ранних спецификаций POSIX (где эта ошибка была исправлена ​​сейчас). К сожалению, старая Java-спецификация еще не была исправлена, вызывая недопонимание до сих пор.

О Java-8:

Да, так называемый "Java Time-Scale" формально определен как UTC-SLS - на основе просроченного предложения, намерение которого было скорее направлено на внутренние реализации NTP-серверов. Никакой реализации UTC-SLS не существует в реальном мире. Даже Java-8 не поддерживает UTC-SLS. Два факта подтверждают это утверждение:

  • Java-8 не содержит таблицу високосных секунд (которая была бы основой любой UTC-SLS-реализации). У проекта Threeten изначально был такой, но он был удален (теперь также удален из бэкпорта).

  • Преобразование из java.util.Date в Instant просто 1:1 (см. исходный код - оставляя в стороне разную точность в миллисекундах и наносах). Обратите внимание, что java.util.Date не упоминается в API Instant по отношению к так называемой "шкале времени Java".

Шкала времени Java используется для всех классов даты и времени. Это включает в себя Instant, LocalDate, LocalTime, OffsetDateTime, ZonedDateTime и Duration.

Кроме того: происхождение java.util.Date это с 1995 года (когда была изобретена Java), но UTC-SLS был предложен несколько лет спустя.

Так что же остается в Java-8 в качестве дополнительной поддержки? Пустые слова в спецификации вызывают много путаницы, больше ничего.

Что вы можете сделать еще? В рамках JDK просто ничего. То, что вам нужно, это внешняя сторонняя библиотека со встроенными данными в секунду. Пример - моя библиотека Time4J - см. Эту статью. Другим вариантом может быть библиотека Threeten-Extra с ее классом UTCInstant. Но я не проверял его преобразование в java.util.Date (кажется подозрительным?).

Согласно документации Java8 для класса Date, вызов Date в течение високосной секунды будет / действительно вернет:60 или:61.

Так что вам не нужно ничего делать.

Как это происходит, хотя и немного загадочно, поскольку базовый класс Instant распределяет скачок секунды в течение последних 1000 секунд дня - так что каждая из этих последних секунд фактически будет длиться 1,001 секунды - и ваше приложение не будет знать, является ли оно в секунду или нет.

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