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

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

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

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


person xirt    schedule 01.07.2015    source источник
comment
Java SE 8 четко определяет поведение дополнительной секунды здесь: docs. oracle.com/javase/8/docs/api/java/time/Instant.html   -  person trognanders    schedule 01.07.2015
comment
Я не думаю, что такой метод, как размазывание скачка, можно квалифицировать как правильное представление дополнительной секунды, но это определенно допустимый способ обработки дополнительных секунд, по крайней мере, в контексте сервера/базы данных: stackoverflow.com/questions/19751115/   -  person Sandman    schedule 01.07.2015


Ответы (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» формально указана как 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 (кажется подозрительным?).

person Meno Hochschild    schedule 01.07.2015

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

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

Однако то, как это происходит, остается загадкой, поскольку лежащий в основе Мгновенный класс распределяет високосную секунду по последним 1000 секундам дня, поэтому каждая из этих последних секунд на самом деле будет длиться 1,001 секунды, и ваше приложение не будет знать, находится ли она на високосной секунде или нет.

person brendan    schedule 01.07.2015
comment
Насколько мне известно, класс java.time.Instant не лежит в основе класса java.util.Date. Обратите внимание на имена пакетов. Первый из совершенно новой (начиная с Java 8) фреймворка java.time. Последний очень старый, с первой версии Java. У Date есть несколько удобных методов преобразования для Instant, но их кодовые базы совершенно разные. - person Basil Bourque; 02.07.2015