будет ли gmtime() возвращать tm == 1998-12-31T23:59:60 для time_t = 915148800, а по истечении дополнительной секунды возвращать tm == 1999-01-01T00:00:00 для того же time_t?
Также стоит рассмотреть размытие с секундным прыжком. user2864740 18.02.2018
@user2864740 user2864740 Отлично, спасибо, что подняли этот вопрос, было бы также важно знать, как gmtime справится с этим. Yuki 18.02.2018
Короткий ответ: нет, практически говоря, gmtime_r никогда не заполнит tm_sec значением 60. Это печально, но неизбежно.
Фундаментальная проблема заключается в том, что time_t в соответствии со стандартом Posix представляет собой количество секунд с 01 января 1970 года по всемирному координированному времени, при условии отсутствия високосных секунд.
В течение последней дополнительной секунды прогресс был таким:
Да, там должна была быть дополнительная секунда, 23:59:60. Но нет никакого возможного значения time_t между 1483228799 и 1483228800.
Я знаю два способа для варианта gmtime вернуть время, заканчивающееся на :60:
Вы можете запустить часы вашей ОС на чем-то другом, кроме UTC, обычно TAI или TAI-10, и использовать так называемые "правильные" часовые пояса для преобразования в UTC (или местное время) для отображения. См. эту веб-страницу для обсуждения этого вопроса.
Вы можете использовать clock_gettime() и определить новое значение clkid, возможно, CLOCK_UTC, которое решает проблему time_t, используя при необходимости преднамеренно ненормализованные значения struct timespec. Например, способ получить значение времени между 1483228799 и 1483228800 состоит в том, чтобы установить tv_sec в 1483228799, а tv_nsec в 1000000000. Дополнительную информацию см. на этой веб-странице.
Способ № 1 работает очень хорошо, но никто не использует его, потому что никто не хочет запускать часы ядра на чем-то другом, кроме UTC, как это должно быть. (В конечном итоге у вас возникают проблемы с такими вещами, как временные метки файловой системы и такие программы, как tar, которые встраивают эти временные метки.)
Способ № 2 - прекрасная идея, ИМО, но, насколько мне известно, она никогда не была реализована в выпущенной ОС. (Случилось так, что у меня есть работающая реализация для Linux, но я еще не выпустил свою работу.) Чтобы способ № 2 работал, вам нужен новый вариант gmtime, возможно, gmtime_ts_r, который принимает struct timespec вместо time_t.
Приложение: Я только что перечитал заголовок вашего вопроса. Вы спросили: "Будет ли gmtime() сообщать о 60 секундах, когда сервер находится в високосной секунде?" Мы могли бы ответить на это, сказав "да, но" с оговоркой, что, поскольку большинство серверов не могут правильно представлять время в течение дополнительной секунды, они никогда не "на" дополнительную секунду.
Приложение 2: я забыл упомянуть, что схема № 1 работает лучше для местного времени, то есть, когда вы вызываете один из вариантов localtime, чем для времени UTC и gmtime. Очевидно, что на преобразования, выполняемые localtime, влияет установка переменной окружения TZ, но не совсем ясно, влияет ли TZ на gmtime. Я заметил, что на некоторые реализации gmtime влияет TZ, и поэтому они могут делать дополнительные секунды в соответствии с "правильными" зонами, а некоторые не могут. В частности, gmtime в GNU glibc, по-видимому, обращает внимание на информацию о дополнительных секундах в "правильная" зона, если TZ указывает ее, тогда как gmtime в распространении tzcode IANA этого не делает.
Ответ 2 · рейтинг 5 · Community
Вопрос в том, будет ли tm.tm_sec == 60 когда сервер находится в пределах дополнительной секунды?
Нет. В типичной системе UNIX time_t подсчитывает количество не високосных секунд с начала эпохи (1970-01-01 00:00:00 по Гринвичу). Таким образом, преобразование time_t в struct tm всегда будет давать временную структуру со значением tm_sec между 0 и 59.
Игнорирование високосных секунд при исчислении time_t позволяет преобразовать time_t в удобочитаемую дату/время без полного знания всех високосных секунд до этого времени. Это также позволяет однозначно преобразовывать значения time_t в будущем; включение високосных секунд сделало бы это невозможным, поскольку наличие високосной секунды неизвестно за 6 месяцев в будущем.
Существует несколько способов, с помощью которых UNIX и UNIX-подобные системы обрабатывают дополнительные секунды. Чаще всего либо:
Одно значение time_t повторяется для дополнительной секунды. (Это результат строгой интерпретации стандартов, но это приведет к сбоям во многих приложениях, поскольку кажется, что время пошло вспять.)
Системное время работает немного медленнее в течение некоторого времени вокруг дополнительной секунды, чтобы "размазать" дополнительную секунду по более широкому периоду. (Это решение было принято многими крупными облачными платформами, включая Google и Amazon. Это позволяет избежать любых несоответствий локальных часов за счет того, что затронутые системы остаются несинхронизированными до полусекунды с UTC на время действия.)
Системное время установлено на TAI. Поскольку это не включает дополнительные секунды, обработка дополнительных секунд не требуется. (Это случается редко, так как это приведет к рассинхронизации системы на несколько секунд с системами UTC, которые составляют большую часть мира. Но это может быть жизнеспособным вариантом для систем, которые практически не контактируют с внешним миром, и, следовательно, не имеют возможности узнать о предстоящих високосных секундах.)
Система совершенно не знает о високосных секундах, но ее клиент NTP исправит часы после того, как високосная секунда оставит системные часы на одну секунду от правильного времени. (Это это то, что делает Windows.)
Ответ 3 · рейтинг 2 · bazza
На это нет абсолютно никакого простого ответа. Чтобы было 60 секунд, когда есть дополнительная секунда, вам требуется 1) что-то в ОС, чтобы знать, что есть дополнительная секунда, и 2) для библиотеки C, которую вы используете, чтобы также знать о дополнительной секунде, и сделай что-нибудь с этим.
Очень много операционных систем и библиотек этого не делают.
Лучшее, что я нашел, - это современные версии ядра Linux, объединенные с gpsd и ntpd, использующие GPS-приемник в качестве эталона времени. GPS объявляет дополнительные секунды в своем системном потоке данных, а gpsd, ntpd и ядро Linux могут поддерживать CLOCK_TAI, пока происходит дополнительная секунда, и системные часы также верны. Я не знаю, делает ли glibc разумную вещь с дополнительной секундой.
На других UNIX ваш пробег будет другим. Значительно.
Windows - это ******* зона бедствия. Например, класс DateTime в C# не знает об исторических високосных секундах. Системные часы перескакивают на 1 секунду, когда в следующий раз будет получено обновление сетевого времени.
Ответ 4 · рейтинг 2 · R.. GitHub STOP HELPING ICE
POSIX определяет взаимосвязь между значениями time_t "Секунды с начала эпохи" и временем в разбивке (struct tm) точно таким образом, который не допускает високосных секунд или TAI, поэтому по существу (до некоторой двусмысленности в отношении того, что должно происходить рядом с високосными секундами), Значения POSIX time_t - это UT1, а не UTC, и результаты gmtime отражают это. На самом деле нет способа адаптировать или изменить это, совместимое с существующими спецификациями и существующим программным обеспечением, основанным на них.
Правильный путь вперед почти наверняка представляет собой сочетание того, что сделал Google с размазыванием секунды и стандартизированная формула для преобразования туда и обратно между "размазанным временем UTC" и "фактическим временем UTC" (и, следовательно, также TAI) в 24-часовом окне вокруг секунды координации и API для выполнения этих преобразований.
Ответ 5 · рейтинг 1 · gnasher729
Я прочитал это на www.cplusplus.com о gmtime: "Использует значение, указанное timer, для заполнения структуры tm значениями, которые представляют соответствующее время, выраженное как время UTC (т. Е. Время в часовом поясе GMT)".
Итак, есть противоречие. В UTC есть секунды абсолютно постоянной длины и, следовательно, нужны дополнительные секунды, в то время как в GMT дни составляют ровно 86 400 секунд с очень незначительной разницей в длине. gmtime() не может одновременно работать в UTC и GMT.
Когда нам говорят, что gmtime() возвращает "UTC без дополнительных секунд", я бы предположил, что это означает GMT. Это будет означать, что дополнительных секунд не записано, и это будет означать, что время медленно отклоняется от UTC, пока разница не составит около 0,9 секунды, а дополнительная секунда будет добавлена в UTC, но не в GMT. Разработчикам с этим легко справиться, но это не совсем точно.
Один из вариантов - иметь постоянные секунды, пока вы не приблизитесь к високосной секунде, а затем настроить, возможно, 1000 секунд вокруг этой високосной секунды. Кроме того, с ним легко работать, в большинстве случаев он точен на 100 %, а погрешность 0,1 % в течение секунды иногда составляет 1000 секунд.
И второй вариант - иметь постоянные секунды, иметь дополнительные секунды, а затем забыть о них. Таким образом, gmtime() будет возвращать одну и ту же секунду дважды подряд, начиная с x секунд 0 наносекунд до x секунд 999999999 наносекунд, затем снова от x секунд 0 наносекунд до x секунд 999999999 наносекунд, затем до x+1 секунд. Что вызовет затруднения.
Конечно, было бы полезно иметь другие часы, которые будут возвращать точное значение UTC, включая високосные секунды, с точными секундами. Чтобы перевести "секунды с эпохи" в год, месяц, день, часы, минуты, секунды, требуется знание всех високосных секунд с эпохи (или до эпохи, если вы обрабатываете время до этого). И часы, которые будут возвращать гарантированно точное время по Гринвичу без високосных секунд и секунд, которые являются почти, но не совсем постоянным временем.
Ответ 6 · bazza
Другой аспект их проблемы заключается в наличии библиотеки, которая "знает так" о високосных секундах. Большинство библиотек этого не делают, поэтому ответы, которые вы получаете от таких функций, как gmtime, строго говоря, неточны в течение високосной секунды. Кроме того, расчеты разницы во времени часто дают неточные результаты, охватывающие дополнительную секунду. Например, значение time_t, данное вам вчера в то же самое время UTC, ровно на 86400 секунд меньше сегодняшнего значения, даже если на самом деле была дополнительная секунда.
Астрономическое сообщество решило эту проблему. Вот библиотека SOFA, в которой есть правильные распорядки времени. См. их руководство (PDF), раздел о сроках. Если он является частью вашего программного обеспечения и поддерживается в актуальном состоянии (новая версия требуется для каждой новой дополнительной секунды), у вас есть точные расчеты времени, преобразования и отображение.