Подтвердить что ты не робот

Как Java-JVM (Oracle) знает секунду?

A произойдет прыжок второй раз 30 июня 2015 года. Кажется, что разные операционные системы справляются с этой ситуацией по-другому. В моем конкретном случае мы запускаем систему Red Hat 6.4 с пользовательским программным обеспечением Java (JDK 1.7), которое сильно зависит от времени. По некоторым данным недавняя информация о Red Hat, опубликованная мной, наш системный демон NTP обеспечит, чтобы ОС автоматически обрабатывала второй прыжок, повторяя дважды 23:59:59.

Мой вопрос: если у меня длительный процесс JDK 1.7, как он знает, что происходит скачок? Я имею в виду, как Java в конечном итоге знает, что IERS люди решили вставить секунду назад? Документация Date, по-видимому, указывает, что она знает о прыжках секунд, но кажется бесполезной. Могу ли я считать JDK, когда создан соответствующий объект Date или вызывается Calendar.getInstance(), это переход к основной обработке времени для обработки даты, чтобы получить соответствующее "реальное" значение времени? (Который, в моем случае, звучит так, будто он повторит второй 23:59:59, потому что это будет работать с ОС).

4b9b3361

Ответ 1

Это зависит от вашей версии jdk. Если, например, вы используете обновление 80, вы можете проверить примечания к выпуску:

JDK 7u80 содержит информацию о часовом поясе IANA версии 2015a. Для получения дополнительной информации см. Версии данных Timezone в программном обеспечении JRE.

Затем перейдите по ссылке на данные о часовых поясах и найдите 2015a. Затем следуйте ссылку на TZ Updater version1.4.11:

Новый прыжок второй 2015-06-30 23:59:60 UTC в соответствии с бюллетенем IERS C 49. (Спасибо Тиму Паренти.)

Кажется, он не был включен раньше, поэтому, если вы используете более старую версию JDK 7, вы, вероятно, не получите корректировку. Более подробная информация о том, как она работает внутри, доступна здесь.

Честно говоря, я никогда не тестировал, как это работает на практике.

Ответ 2

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

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

Просканированные секунды

Все распространенные фреймворки даты Java игнорируют скачки секунд, как я понимаю. К ним относятся:

  • java.time
  • Joda-Time
  • java.util.Date/.Calendar(теперь устаревший от java.time и Joda-Time)

Doc

Вот выдержки из каждой документации фреймворка, показывающей, что они фактически игнорируют "Секунды". Акцент, выделенный жирным шрифтом, принадлежит мне.

Документ java.time для Instant класс:

... Учитывая сложность точного хронометража, описанную выше, этот Java API определяет свой собственный временной шкал Java Time-Scale.

Шкала времени Java делит каждый календарный день ровно на 86400 подразделов, называемых секундами. Эти секунды могут отличаться от SI. Он тесно соответствует фактической международной шкале гражданского времени, определение которой время от времени меняется.

Шкала времени Java имеет несколько разные определения для разных сегментов временной линии, каждая из которых основана на общепринятой международной шкале времени, которая используется в качестве основы для гражданского времени. Всякий раз, когда согласованная на международном уровне временная шкала изменяется или заменяется, для нее должен быть определен новый сегмент Java Time-Scale. Каждый сегмент должен отвечать следующим требованиям:

  • Шкала времени Java должна точно соответствовать базовой шкале международного гражданского времени;
  • Шкала времени Java должна точно соответствовать международному гражданскому времени в полдень каждый день;
  • Шкала времени Java должна иметь четко определенную связь с международной шкалой гражданского времени.

В настоящее время с 2013 года существуют два сегмента в Java-времени.

Для сегмента с 1972 по 2011 гг. (точная граница, обсуждаемая ниже) до дальнейшего уведомления, общая международная шкала времени - это UTC (с прыжковыми секундами). В этом сегменте Java Time-Scale идентичен UTC-SLS. Это идентично UTC в дни, которые не имеют секунды прыжка. В дни, у которых есть секундомер, , вторая секунда скачка распределяется одинаково в течение последних 1000 секунд дня, поддерживая появление ровно 86400 секунд в день.

Для сегмента до 1972-11-03, проходящего сколь угодно далеко, консенсусная международная шкала времени определяется как UT1, применяемая пролептически, что эквивалентно (среднему) солнечному времени на основном меридиане (Гринвич), В этом сегменте Java Time-Scale идентичен согласованной международной шкале времени. Точная граница между двумя сегментами - это момент, когда UT1 = UTC между 1972-11-03T00: 00 и 1972-11-04T12: 00.

Реализации Java-шкалы с использованием JSR-310 API не требуются для обеспечения точности часов, которые являются второстепенными, или что монотонно или плавно прогрессирует. Таким образом, реализации не требуется для фактического выполнения UTC-SLS, или иначе быть в курсе секунд прыжка. Однако JSR-310 требует, чтобы реализации должны документировать подход, который они используют при определении часов, представляющих текущий момент. См. Часы для получения подробной информации о доступных часах.

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

Joda-Time FAQ:

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

java.util.Date класс doc:

Вторая цифра представлена ​​целым числом от 0 до 61; значения 60 и 61 встречаются только для секунд прыжка и даже тогда только в реализациях Java, которые действительно правильно отслеживают секунды прыжка.

Насколько я знаю, реализации OpenJDK и Oracle, которые не выполняются, не отслеживают секунды прыжка. Отправьте такую ​​документацию, если найдете ее.

Отсутствие прыжка во втором случае при вычислении прошедшего времени

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

Вот пример кода, вычисляющего прошедшее время с минуты до полуночи до минуты с 30 июня по 1 июля 2015 года, когда Leap Second запланировано. Этот код проверяет Joda-Time 2.8.1 и java-time в java version "1.8.0_45". Я игнорировал java.util.Date/.Calendar, когда я избегаю этих классов, когда это возможно; не стесняйтесь добавлять код здесь для этого случая.

Сначала Joda-Time.

// Joda-Time 2.8.1
DateTime startJoda = new DateTime( 2015, 06, 30, 23, 59, 00, DateTimeZone.UTC );
DateTime stopJoda = new DateTime( 2015, 07, 01, 00, 01, 00, DateTimeZone.UTC );
long elapsedMillisJoda = ( stopJoda.getMillis( ) - startJoda.getMillis( ) );

System.out.println( "startJoda: " + startJoda + " stopJoda: " + stopJoda + " = elapsedMillisJoda: " + elapsedMillisJoda );

... и java.time...

// java.time
ZonedDateTime startZdt = ZonedDateTime.of( 2015, 06, 30, 23, 59, 00, 00, ZoneOffset.UTC );
ZonedDateTime stopZdt = ZonedDateTime.of( 2015, 07, 01, 00, 01, 00, 00, ZoneOffset.UTC );
long elapsedMillisZdt = startZdt.until( stopZdt, ChronoUnit.MILLIS );

System.out.println( "startZdt: " + startZdt + " stopZdt: " + stopZdt + " = elapsedMillisZdt: " + elapsedMillisZdt );

При запуске мы видим результат четных чисел, ровно две минуты, 120 секунд или 120 000 миллисекунд.

startJoda: 2015-06-30T23:59:00.000Z stopJoda: 2015-07-01T00:01:00.000Z = elapsedMillisJoda: 120000
startZdt: 2015-06-30T23:59Z stopZdt: 2015-07-01T00:01Z = elapsedMillisZdt: 120000

Ответ 3

Это мои фактические обсервации, работающие в режиме реального времени на RHEL 6.3, с Oracle Java JDK 1.7.0_55-b13 (I.e: устаревший JDK). Я добавил код отладки, который нокаутировал, записывая новую DateTime() каждые 0,5 секунды за минуту до второго прыжка 30 июня 2015 года 23:59 UTC, а затем выпрыгнул после того, как второй прыжок закончился. Далее следует журнал (для любопытных двойное число, напечатанное, представляет собой количество секунд с эпоха J2000)

2015-06-30 23:59:59.316 18349217 [main] INFO  - Leaper time is 488980799.316000 (Tue Jun 30 23:59:59 GMT-00:00 2015)
2015-06-30 23:59:59.817 18349718 [main] INFO  - Leaper time is 488980799.816000 (Tue Jun 30 23:59:59 GMT-00:00 2015)
2015-07-01 00:00:00.317 18350218 [main] INFO  - Leaper time is 488980800.317000 (Wed Jul 01 00:00:00 GMT-00:00 2015)
2015-07-01 00:00:00.817 18350718 [main] INFO  - Leaper time is 488980800.817000 (Wed Jul 01 00:00:00 GMT-00:00 2015)
2015-07-01 00:00:01.318 18351219 [main] INFO  - Leaper time is 488980801.318000 (Wed Jul 01 00:00:01 GMT-00:00 2015)

К сожалению, это не говорит мне многого, за исключением того, что он не вставлял канонический прыжок второй в 23:59:60 (так как оба assylias и Basil Bourque ответят, что это произойдет). Я надеялся, что "новая дата()" дойдет до базовой ОС (RHEL 6.3, которая, предположительно, будет отвечать на прыжок в секундах), чтобы спросить текущее время. Это, похоже, не так.

У меня не было ресурсов для запуска любых других комбинаций версии JDK и версии RHEL для тестирования эффектов. Моя лучшая догадка заключается в том, что документация Базиля Бурка, найденная о распространении секунды прыжка за последние 1000 секунд дня, относится к JDK 1.8 и более новой (поскольку она является частью Instant, которая является функцией Java 8). В моем конкретном случае, поскольку у моего старшего JDK 1.7.0_55 не было корректировки второго прыжка на 2015 год, я думаю, что наблюдение за аселией применяется. А именно, что наши процессы в реальном времени теперь работают на 1 секунду вперед, не обращая внимания на второй шаг.

Занятый здесь урок? Убедитесь, что ваши системы реального времени полностью исправлены с последними обновлениями, если вы хотите быть уверенными, что они учитывают предстоящие прыжки секунд. Мне нужно будет сделать некоторые наблюдения и анализ журналов, но наша конкретная система теперь, вероятно, работает на 1 секунду раньше реального времени, и нам нужно будет перезапустить наши службы, чтобы вернуться обратно в линию.