Правильно работать с високосными секундами
До и во время високосного 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
не упоминается в APIInstant
по отношению к так называемой "шкале времени 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 секунды - и ваше приложение не будет знать, является ли оно в секунду или нет.