Как может 1 год (java) lib корректно выполнять UTC Time formatting, учитывая недавно введенный второй прыжок

Временная метка, выраженная в миллисекундах с 1.1.1970 UTC - это распространенный способ хранения временных меток, например, в Java.

например:

long timestampUtc = System.currentTimeMillis();

Такая временная метка может быть сформирована в формате человеческого времени считывания, например, используя этот код

    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    String humanTimeUtc = df.format(new Date(timestampUtc));
    System.out.println(humanTimeUtc);

который дает результат: 2014-02-14 14:58:05

Теперь представьте себе, что сегодня в полночь администрация времени вводит новый второй шаг UTC. Если я запустил код выше, java JRE в моей системе не может знать, что это второе вскармливание, и неверно отформатировало время (на одну секунду).

Правильно ли мое предположение? Как правильно форматировать время (например, в файле журнала) в системах, которые не всегда могут использовать обновленную JRE?.

Справочная информация:
Это используется во встроенном устройстве, которое синхронизирует свои системные часы с помощью GPS, имея GPS-диапазон секунд скачка, сдвинутый на UTC.

Ответы

Ответ 1

Java и Unix "эпоха" (количество секунд с 1 января 1970 г. 00:00:00 UTC) оба полностью игнорируют секунды прыжка, Оба они предполагают, что каждый день (измеренный в UTC) имеет ровно 86400 секунд. Простой блок кода для проверки:

    Calendar c = Calendar.getInstance();
    c.setTimeZone(TimeZone.getTimeZone("UTC"));
    c.set(2014, 0, 1, 0, 0, 0);
    c.set(Calendar.MILLISECOND, 0);
    System.out.println(c.getTimeInMillis());

Вы увидите, что количество секунд с 1/1/1970 до 1/1/2014 является точным кратным 86400 (это на самом деле ровно 44 года * 365,25 дня/год * 86400 секунд/день); это не должно быть, потому что в этот интервал было введено 25 секундных секунд.

Если вам нужно учитывать секунды прыжка, вам нужно найти библиотеку, которая сделает это, или придумать собственную настройку.

Ответ 2

Обработка второго прыжка сложна, и Java не особенно плоха в этом отношении.

Временная шкала NTP и прыжки секунд объясняет лишь некоторые из странностей:

Вставка секунд прыжка в UTC, а затем в NTP и POSIX влияет на системные часы и, следовательно, на переход между системным тактовым временем и обычным гражданским временем в часах, минутах и ​​секундах. Однако, поскольку единственной институциональной памятью, доступной для определения преобразования, являются национальные службы широковещательной передачи UTC, преобразование действует reset в UTC, поскольку каждый тайм-код вещания принимается. Таким образом, когда вторая секунда вставляется в UTC, а затем в NTP или POSIX, знание всех предыдущих секунд прыжка теряется.

Другой способ описать это - сказать, что столько времен NTP или POSIX, сколько исторических секунд прыжка. По сути, новая временная шкала восстанавливается после каждой новой секунды прыжка. Таким образом, все предыдущие скачкообразные секунды, не говоря уже о кажущемся происхождении самой временной шкалы, отступают назад на одну секунду, когда устанавливаются все новые временные рамки. Например, если часы, синхронизированные с UTC в 2005 году, использовались для установления эпохи UTC события, произошедшего в начале 1972 года без коррекции, событие появится на 22 секунды позже. В результате, для наиболее точного определения эпохи относительно исторического григорианского календаря и временного масштаба UTC пользователь должен вычесть из кажущейся NTP или POSIX эпоху соответствующее смещение, предоставляемое IERS. Это функция почти всех механизмов распределения сегодняшнего дня.

Секунды почти никогда не актуальны, если вы не выполняете астрономические расчеты или что-то еще, что зависит от положения Земли и Солнца.

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

  • стабильный (в обозримом будущем) способ преобразования из представления кортежа типа (год, месяц, день,...) в скалярное представление, такое как millis-since-epoch или
  • обрабатывать одно представление, а не смешивать и сопоставлять.

Я предпочитаю (2). Скалярное представление лучше для научных вычислений, а представление кортежей лучше подходит для бизнес-приложений и случайных приложений.

Ответ 3

Ответ dcsohl и ответ Майка Самуила верны.

Другие комментарии о временной базе данных, обновляемой Java, неверны. Да, база данных обновляется, но не для секунд прыжка. Секундные секунды полностью игнорируются Java, Joda-Time и другими ориентированными на Unix системами учета времени.

В вашем вопросе возникает проблема, в которой не существует.

Дрифт часов

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

Вставка секунды прыжка имеет тот же эффект, что и неточность ваших часов. Ваш компьютер выключен на секунду и вскоре будет исправлен путем регистрации с сервером времени.

Игнорирование прыжка второй

С точки зрения ваших данных, как связанный класс java.util.Date, так и популярная замена, Joda-Time, игнорировать прыжок второй. Поэтому подумайте о прыжке в секунду, как о том, что он растянулся на 59-й секунде в последний час дня прыжкового второго события. Что касается нашего календаря и часов вызова, ничего не произошло. Для всех приложений, связанных с бизнесом, и большинства практических целей большинства программ, игнорирование секунд прыжка не имеет отрицательных последствий.

Да, технически говоря, миллисекунды-эпохи, используемые java.util.Date и Joda-Time, неверны. Прямо сейчас сообщается 1392442622998 с начала 1970 года, в то время как фактически с 25 секундными прыжками, вставленными с 1972 года, это число должно "быть" 1 392 442 647 998 (еще 25 000). Да, вычисление прошедшего времени между двумя временными точками в течение нескольких лет будет коротким на несколько секунд. Но для большинства целей, кого это волнует? Мы скорректировали наши календари так, как будто не было никакой дополнительной секунды.

Если у вас есть точный ориентированный ум, как и я, вам нужно время, чтобы обернуть голову тем, что игнорирование секунд прыжка не оказывает практического влияния на отслеживание календаря. Основная проблема:

  • Время дня - это то, как мы читаем вращение планеты (которая замедляется), а дата/календарь - это то, как мы читаем орбиту планеты вокруг Солнца.
  • Те два, время дня и дата/календарь не имеют ничего общего друг с другом. Они независимые реальности. Но мы, люди, смешаем их вместе, чтобы понять смысл времени, как мы сливаем арахисовое масло и банан вместе, чтобы сделать бутерброд. И точно так же, как мы могли бы мерить мед между pb и бананом, чтобы свести их вместе, прыжки-секунды объединяют часы + календарь в едином порядке для нашего умственного потребления.

Одна из возможных проблем

Единственной реальной практической проблемой является то, что, как сообщается, некоторые системы генерируют фактическую 60-ю секунду, время 23:59:60. Это значение времени может привести к хаосу с некоторым программным обеспечением, написанным в то время, когда он не знает секунд прыжка. Такое программное обеспечение ошибочно предполагает, что ценность невозможна и может вызывать ошибки или иным образом терпеть неудачу. Правильно информированное программное обеспечение должно знать, что (а) у нас могут быть дополнительные секунды, поэтому 23:59:60 и 23:59:61 являются правовыми значениями, и (б) скачок может быть отрицательным. (Пока у нас были только отдельные положительные секунды прыжка, я помню, что читал, что возможно более одного, но не ожидаемого. Я не могу найти источник на этом.) Помните, что эта проблема возникает только в том случае, если ОС или поставщик значений времени фактически отслеживает эти прыжки вторых событий - мало кто делает, поэтому они никогда не видят второго номера 60.

Подробнее

Страница Википедии содержит дополнительную информацию о прыжке в секунду.

Ответ 4

Моя новая библиотека Time4J способна обрабатывать секунды прыжка, поэтому это одна из нескольких уникальных функций этой библиотеки. Я не знаю никакой другой библиотеки, которая может делать форматирование секунд прыжка. Конкретно о вашем вопросе подробно:

Пример кода с использованием стандартного Java

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String humanTimeUtc = df.format(new Date(timestampUtc));
System.out.println(humanTimeUtc);

смотрит в Time4J как:

ChronoFormatter<Moment> formatter =
  ChronoFormatter.setUp(Moment.class, Locale.US)
                 .addPattern("uuuu-MM-dd HH:mm:ss", PatternType.CLDR)
                 .build();
Moment timestampUTC = SystemClock.INSTANCE.currentTime();
System.out.println(formatter.format(timestampUTC));
// output: 2014-02-20 14:16:25

a) Источник времени SystemClock основан на System.currentTimeMillis(). Этот источник никогда не рассчитывает секунды прыжка и также никогда не может дать временную отметку времени прыжка - если предположить, что базовая ОС - leapsecond-unaware. Таким образом, выход в этом примере никогда не отображает второе значение скачка 60.

b) Внутренне объект типа Moment содержит в себе состояние posix-timestamp и бит lapsecond-bit. Таким образом, с помощью внешней таблицы leapsecond (которая фактически хранится в маленьком файле в classpath) каждый Moment будет корректно отображать то же самое время, даже когда системный администратор позже обновит файл leapsecond и вставляет новый. Это не влияет на Moment за пределами прыжковых секунд, следовательно, нет односекундной ошибки. = > Если вы повторно запускаете код после вставки новой секунды прыжка, то отметка времени сохраненного момента остается прежней. Отформатированный вывод не изменяется, что хорошо.

c) Вы можете построить Moment, которые представляют собой прыжок второй либо путем выбора специализированного источника времени (в будущем я доставляю SNTP-клиент, который может отслеживать скачок второй), либо путем применения подходящего количество секунд SI, добавленных к нормальному Moment. Отформатированный вывод для такой временной метки действительно отображает второе значение 60, при условии, что вторая таблица скачков является актуальной. Если вы переносите этот leapsecond-moment на другой JVM с помощью сериализации, где таблица leapsecond не обновляется, тогда она будет обрабатываться там как одна секунда (и если вы сериализуете ее обратно на правильно обновленную JVM или если получатель -JVM должным образом обновляется позже, тогда снова будет отображаться leapsecond).

d) Time4J также поддерживает шкалу времени GPS. Вы можете построить Moment, указав истекшие секунды с момента GPS (1980-01-06 в полночь при запуске) и указав масштаб времени GPS. Внутренне Moment преобразует данные в состояние UTC, которое не является потерянным при условии, что таблица leapsecond является актуальной. Конечно, если ваша конфигурация не обновлена, и источник GPS испускает несколько прошедших секунд, представляющих событие leapsecond, тогда будет одна ошибка в секунду. Чтобы избежать таких крошечных и редких ошибок из-за того, что в JVM-клиентах неправильно управляются таблицы leapsecond, может быть хорошей идеей установить другой механизм для настройки. Time4J определяет SPI-интерфейс для этой цели.

Ответ 5

Мы столкнулись с этим с С# в Windows, а также с использованием класса .NET DateTime: он не учитывает секунды прыжка, даже если в документации MSDN подразумевается иное.

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

Если у кого-то есть другие яркие идеи на С# или Java, мы будем рады их услышать. Спасибо.