Будет ли `gmtime()` сообщать о секундах как о 60, когда это високосная секунда?

У меня есть сервер, работающий в TZ=UTC, и у меня есть такой код:

time_t t = time(NULL);
struct tm tm;
gmtime_r(&t, &tm);

Вопрос в том, будет ли tm.tm_sec == 60 когда сервер находится в пределах високосной секунды?

Например, если бы я находился в следующем промежутке времени:

1998-12-31T23:59:60.00 - 915 148 800.00
1998-12-31T23:59:60.25 - 915 148 800.25
1998-12-31T23:59:60.50 - 915 148 800.50
1998-12-31T23:59:60.75 - 915 148 800.75
1999-01-01T00:00:00.00 - 915 148 800.00

будет ли gmtime() возвращать tm == 1998-12-31T23:59:60 для time_t = 915148800, а по истечении дополнительной секунды возвращать tm == 1999-01-01T00:00:00 для того же time_t?


person Yuki    schedule 17.02.2018    source источник
comment
Также стоит рассмотреть размытие с секундным прыжком.   -  person user2864740    schedule 18.02.2018
comment
@user2864740 user2864740 Отлично, спасибо, что подняли этот вопрос, было бы также важно знать, как gmtime справится с этим.   -  person Yuki    schedule 18.02.2018


Ответы (6)


Короткий ответ: нет, практически говоря, gmtime_r никогда не заполнит tm_sec значением 60. Это печально, но неизбежно.

Фундаментальная проблема заключается в том, что time_t в соответствии со стандартом Posix представляет собой количество секунд с 01 января 1970 года по всемирному координированному времени, при условии отсутствия високосных секунд.

В течение последней дополнительной секунды прогресс был таким:

1483228799    2016-12-31 23:59:59
1483228800    2017-01-01 00:00:00

Да, там должна была быть дополнительная секунда, 23:59:60. Но нет никакого возможного значения time_t между 1483228799 и 1483228800.

Я знаю два способа для варианта gmtime вернуть время, заканчивающееся на :60:

  1. Вы можете запустить часы вашей ОС на чем-то другом, кроме UTC, обычно TAI или TAI-10, и использовать так называемые «правильные» часовые пояса для преобразования в UTC (или местное время) для отображения. См. эту веб-страницу для обсуждения этого вопроса.

  2. Вы можете использовать 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 этого не делает.

person Steve Summit    schedule 17.02.2018
comment
Относительно gmtime_r никогда не заполнит tm_sec значением 60, это неправда. См. coliru.stacked-crooked.com/a/622da23fd57dabca. - person Yuki; 18.02.2018
comment
@Юки Верно. Похоже, вы получили свой комментарий до того, как я закончил свой ответ. Это способ №1. - person Steve Summit; 18.02.2018
comment
@SteveSummit И это показывает, что не так с этим подходом! Обычно gmtime() не должно волновать, что установлено $TZ; правильные часовые пояса составляют причудливое исключение. - person ; 18.02.2018
comment
Правильные часовые пояса ужасно неверны. Это не просто нормально; gmtime даже разрешено зависеть от $TZ. - person R.. GitHub STOP HELPING ICE; 18.02.2018

Вопрос в том, будет ли 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-подобные системы обрабатывают дополнительные секунды. Чаще всего либо:

  1. Одно значение time_t повторяется для дополнительной секунды. (Это результат строгой интерпретации стандартов, но это приведет к сбоям во многих приложениях, поскольку кажется, что время пошло вспять.)

  2. Системное время работает немного медленнее в течение некоторого времени вокруг дополнительной секунды, чтобы «размазать» дополнительную секунду по более широкому периоду. (Это решение было принято многими крупными облачными платформами, включая Google и Amazon. Это позволяет избежать любых несоответствий локальных часов за счет того, что затронутые системы остаются несинхронизированными до полусекунды с UTC на время действия.)

  3. Системное время установлено на TAI. Поскольку это не включает дополнительные секунды, обработка дополнительных секунд не требуется. (Это случается редко, так как это приведет к рассинхронизации системы на несколько секунд с системами UTC, которые составляют большую часть мира. Но это может быть жизнеспособным вариантом для систем, которые практически не контактируют с внешним миром, и, следовательно, не имеют возможности узнать о предстоящих високосных секундах.)

  4. Система совершенно не знает о високосных секундах, но ее клиент NTP исправит часы после того, как високосная секунда оставит системные часы на одну секунду от правильного времени. (Это это то, что делает Windows.)

person Community    schedule 17.02.2018
comment
преобразование time_t в struct tm всегда даст результат... это неверно, иначе в спецификации не было бы значения 60 для секунд. - person Yuki; 18.02.2018
comment
time_t это TAI, это тоже неверно, time_t это не TAI, time_t это временная метка Unix, это разные вещи. TAI всегда монотонна, а time_t — нет. - person Yuki; 18.02.2018
comment
@Yuki 1) Это результат исторической ошибки. Некоторые старые системы сохраняли таблицу дополнительных секунд в данных часового пояса, что теоретически позволяло localtime() выполнять коррекцию дополнительных секунд. К счастью, это было сочтено безумием и больше не используется. - person ; 18.02.2018
comment
@Yuki 2) Я думаю, вы неправильно поняли мой комментарий о TAI. Я говорю о том, что некоторые системы используют TAI для системных часов (и, следовательно, time_t), что делает ненужной обработку дополнительных секунд. Поскольку это затрудняет преобразование в UTC, это редкость. - person ; 18.02.2018
comment
Современный Linux, имеющий оперативный источник обновлений секунд координации от ntpd (например, через gpsd), поддерживает точное значение CLOCK_TAI. Это можно получить с помощью clock_gettime(). Время time_t, которое вы получите из этого, можно сравнить с обычным time_t, чтобы определить текущее смещение секунды координации. - person bazza; 18.02.2018
comment
time_t по сути является UT1 (потомком исторического GMT), за исключением некоторых разногласий по поводу того, как он течет рядом с високосной секундой. Это точно не ТАЙ. - person R.. GitHub STOP HELPING ICE; 18.02.2018
comment
@R .. Поскольку это, кажется, вызывает много путаницы, я переписал это, поскольку системное время установлено на TAI. - person ; 18.02.2018
comment
Откуда берется системное время? В частности, можете ли вы найти какой-либо источник, в котором говорится, что он поставляет TAI для вашей системы? Ответ на этот вопрос — нет. Таким образом, CLOCK_TAI — это искусственная шкала времени, которая вряд ли согласуется с любой другой системой, которая думает, что использует CLOCK_TAI. - person Steve Allen; 19.02.2018

На это нет абсолютно никакого простого ответа. Чтобы было 60 секунд, когда есть дополнительная секунда, вам требуется 1) что-то в ОС, чтобы знать, что есть дополнительная секунда, и 2) для библиотеки C, которую вы используете, чтобы также знать о дополнительной секунде, и сделай что-нибудь с этим.

Очень много операционных систем и библиотек этого не делают.

Лучшее, что я нашел, — это современные версии ядра Linux, объединенные с gpsd и ntpd, использующие GPS-приемник в качестве эталона времени. GPS объявляет дополнительные секунды в своем системном потоке данных, а gpsd, ntpd и ядро ​​Linux могут поддерживать CLOCK_TAI, пока происходит дополнительная секунда, и системные часы также верны. Я не знаю, делает ли glibc разумную вещь с дополнительной секундой.

На других UNIX ваш пробег будет другим. Значительно.

Windows — это ******* зона бедствия. Например, класс DateTime в C# не знает об исторических високосных секундах. Системные часы перескакивают на 1 секунду, когда в следующий раз будет получено обновление сетевого времени.

person bazza    schedule 17.02.2018

POSIX определяет взаимосвязь между значениями time_t «Секунды с начала эпохи» и временем в разбивке (struct tm) точно таким образом, который не допускает високосных секунд или TAI, поэтому по существу (до некоторой двусмысленности в отношении того, что должно происходить рядом с високосными секундами), Значения POSIX time_t — это UT1, а не UTC, и результаты gmtime отражают это. На самом деле нет способа адаптировать или изменить это, совместимое с существующими спецификациями и существующим программным обеспечением, основанным на них.

Правильный путь вперед почти наверняка представляет собой сочетание того, что сделал Google с размазыванием секунды и стандартизированная формула для преобразования туда и обратно между «размазанным временем UTC» и «фактическим временем UTC» (и, следовательно, также TAI) в 24-часовом окне вокруг секунды координации и API для выполнения этих преобразований.

person R.. GitHub STOP HELPING ICE    schedule 18.02.2018
comment
Это неправильный стандарт, и он восходит к тому времени, когда правильное решение проблемы было слишком сложным (без Интернета, без источников времени GPS и т. д.). Однако все изменилось, и в настоящее время это решаемая проблема (теперь в Linux есть точный CLOCK_TAI, как и в других ОС). Стандарт может быть обновлен, и компьютеры должны использовать CLOCK_TAI в качестве системных часов. Это означало бы изменение тонны программного обеспечения. Что у нас есть, так это инициатива США по отмене дополнительных секунд в UTC, а это означает, что UTC (то есть гражданское время) будет отличаться от UT1 на протяжении десятилетий и столетий. Великобритания против этого! - person bazza; 18.02.2018
comment
Что касается CLOCK_TAI, являющегося стандартом, сам TAI был стандартизирован почти 50 лет. Так что это не недавняя инновация. По сути, необходимые ухищрения, используемые индустрией программного обеспечения, когда поддерживать TAI было слишком сложно, стали общепринятыми стандартами, и ни один человек с достаточным авторитетом не счел нужным подвергнуть сомнению стандарт. Вздох. - person bazza; 18.02.2018
comment
Если вас не волнуют високосные секунды (а большинству людей и большинству программ они не нужны), то да, размазывание — это то, что вам нужно. Но если вы действительно заботитесь о секундах координации, попытка отменить размытие, вероятно, не будет достаточно хорошей, потому что невозможно полностью обратить размытие вспять. (Это обсуждалось в списке рассылки LEAPSECS; извините, у меня нет точной ссылки на сообщение, которым это было сделано.) - person Steve Summit; 18.02.2018
comment
@SteveSummit: можно полностью изменить значение, если у вас есть достаточная точность в значениях, с которыми вы работаете. Размазывающее преобразование, которое использует Google, явно обратимо; это просто вопрос потерь квантования, которые теряют не более пары бит наносекунд, если вы используете timespec с наносекундами. Если вы используете double для времени, вам действительно нечего жаловаться на что-либо из этого, потому что вы уже выбросили так много точности. - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
@bazza: TAI не интересен и не полезен для гражданского использования. Значения time_t в TAI не имеют фиксированной связи с календарным временем без просмотра таблиц дополнительных секунд, и TAI естественным образом будет отличаться от солнечного года (и, следовательно, календарного времени). Что полезно, так это иметь четко определенный способ преобразования между TAI и календарным временем (независимо от того, какую форму календарного времени вы используете), чтобы метки времени были сопоставимы в специальных полях, где они нужны. быть. [продолжение] - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
... UTC дает нам это, но за счет календарного времени, которое необходимо учитывать и учитывать високосные секунды, что нарушает все виды инвариантов, которые ожидают нормальные люди. UT1 дает нам это, но с постоянной потребностью в данных перенастройки, если вы заботитесь о высоком уровне точности (если нет, не проблема). Всемирное координированное время со смещением секунд координации дает вам все свойства, которые желательны для календарного времени, его так же легко преобразовать в/из TAI, как и обычное время UTC, и требуется только знание данных дополнительных секунд для преобразования (ни для какого-либо другого использования). ). - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
@R, дело в том, что большинство компьютерных систем не дают нам 100% точного гражданского времени, несмотря на то, что они используют название UTC. Их неточное представление о времени — это постоянно движущаяся величина; эффект заключается в том, что эпоха перемещается на одну секунду UTC каждый раз, когда есть дополнительная секунда. Различные выдумки вокруг високосных секунд (включая размытие) делают расчеты времени ненадежными в этот момент и постоянно неточными, если они охватывают високосную секунду. Работа Стива Саммита является прекрасным началом для создания системного времени TAI с точными и обновленными преобразованиями в гражданское время. - person bazza; 20.02.2018
comment
@bazza: эффект заключается в том, что эпоха перемещается на одну секунду UTC каждый раз, когда есть дополнительная секунда, верно только в том случае, если вы интерпретируете time_t как секунды SI, что не так. Эпоха не движется. time_t просто не секунды SI, это единицы в календаре, примерно эквивалентные UT1. - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
Синхронизация системных часов с внешним эталонным временем с точностью до 1 микросекунды требует огромных инвестиций в аппаратное обеспечение часов и телекоммуникационное оборудование, что требует гораздо больше усилий, чем взлом системы для использования обходного пути для обработки дополнительных секунд в формате UTC. Чтобы заставить международные регулирующие органы переопределить календарный день, приняв UTC без дополнительных секунд, требуется гораздо больше усилий, чем взломать систему, чтобы использовать шкалу времени без скачков. Для достижения общего согласия по этим вопросам требуется гораздо больше усилий, чем создание новых шкал времени для удовлетворения систем, которым не требуется точное время и частота. - person Steve Allen; 20.02.2018
comment
Для систем, которые нуждаются в точном времени и частоте, регулирующие органы и органы по стандартизации не могут помочь, и пока это не произойдет, они должны взломать свое собственное решение. - person Steve Allen; 20.02.2018
comment
@R, частота тиков time_t - это секунда UTC, а не секунда UT1. Он определен как таковой в POSIX. Эпоха движется; если вы попросите почти любую библиотеку сказать вам, сколько секунд между этим моментом и 01.01.1970 00:00:00 UTC, они ошибутся, на 30 с лишним секунд. Представление компьютера о том, когда (т.е. как давно) произошла дата 01.01.1970 00:00:00 UTC, отличается от того, когда UTC говорит, что это произошло. Хуже того, это становится все более неправильным каждый раз, когда появляется еще одна дополнительная секунда. Такие библиотеки, как SOFA, понимают это правильно. - person bazza; 20.02.2018
comment
@bazza, фактически нет. В течение длительных периодов времени POSIX решил считать календарные дни, и в настоящее время это средние солнечные дни UT1, поэтому в течение длительных периодов секунды POSIX являются средними солнечными секундами. - person Steve Allen; 20.02.2018
comment
@SteveAllen, это относительно легко и дешево сделать с большинством GPS-приемников. Вам нужен настоящий последовательный порт, чтобы сигнал 1PPS можно было использовать для регулирования системной тактовой частоты. Правильное использование gpsd и ntpd означает, что Linux может поддерживать точный CLOCK_TAI. CLOCK_REALTIME все еще не работает... - person bazza; 20.02.2018
comment
@bazza, укажите публикацию, которая демонстрирует синхронизацию часов с точностью до 1 микросекунды с использованием GPS. - person Steve Allen; 20.02.2018
comment
@SteveAllen, действительно можно считать, что разница во времени, возвращаемая подпрограммами POSIX, находится в секундах UT1, но это не совсем разумно, учитывая, что системные часы отсчитываются в секундах UTC. Сбивает с толку! - person bazza; 20.02.2018
comment
@SteveAllen: 1us легко с GPS-приемником, который обеспечивает PPS. Все, что вам нужно, это аппаратное обеспечение для записи метки времени (на основе локального TCXO) на границе PPS и надежный контур управления. Уменьшение до 10 нс или лучше возможно, но достичь этого намного сложнее. - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
@SteveAllen, извиняюсь, мы, кажется, приближаемся к нам таким образом. GPS 1PPS, как правило, хорош для 1 мкс, к тому времени, когда мы прыгаем вверх и вниз по стеку программного обеспечения, мы генерируем выходные сигналы с дрожанием 6 мкс по сравнению с 1PPS GPS. Вполне доволен этим. - person bazza; 20.02.2018
comment
@bazza: локально во времени и пространстве секунды UT1 и UTC по существу одинаковы (то есть не отличаются точностью, которую вы можете измерить, по крайней мере, без экстремального оборудования). Поэтому в значительной степени бессмысленно говорить о том, течет ли время POSIX в UT1 или течет в UTC. - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
@R, да, но компьютеры не дают нам UT1. Они дают нам урезанную версию UTC, которая либо работает медленно, либо ступенчато (возможно, на час позже в Windows), когда появляется дополнительная секунда. Вам не нужно экстремальное оборудование, чтобы заметить, что время вашего ПК с Windows на целую секунду отличается от времени ПК с Linux. И вам не нужна сверхъестественная наука, чтобы задаться вопросом, почему два последовательных раза — это задом наперед. - person bazza; 20.02.2018
comment
@bazza: С размазыванием они UT1 с максимальной ошибкой менее 12 мкс, возможно, менее 6 мкс, если мне захочется посчитать. Они также являются UTC с максимальной ошибкой 6 мкс (в течение 24 часов, окружающих дополнительную секунду) и 0 во все остальное время. - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
@bazza: Мой комментарий об экстремальном оборудовании был очень ясным, поскольку он имел в виду измерение разницы в скорости потока UT1 и UTC, а не разницу в текущем времени, сообщаемом разными системами часов. Секунды UT1 немного длиннее, чем секунды UTC (== секунды SI), но разница чрезвычайно мала. - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
@R, да, но близость все равно не UTC. Ничего из этого не имеет значения для повседневных вещей, но если вы используете, скажем, радиопротокол, это имеет большое значение. - person bazza; 20.02.2018
comment
@bazza: В этом случае все, что вам нужно, это формула для преобразования из любой системы времени, в которой часы сообщаются, в TAI. Который у вас есть. - person R.. GitHub STOP HELPING ICE; 20.02.2018
comment
@R, измеримая разница между секундами UT1 и UTC, да, я понимаю, что вы имеете в виду. - person bazza; 20.02.2018
comment
@R, да, у нас есть, и это здорово, что некоторые добрые души в мире Linux приложили усилия, чтобы проделать отличную работу, и идея Стива Саммита о таблице секунд координации в ядре выглядит великолепно. Я просто хочу, чтобы другие операционные системы догнали их, и чтобы библиотеки начали исправляться, чтобы воспользоваться преимуществами и позволить разработчикам программного обеспечения не беспокоиться о том, что время снова пойдет назад / замедлится. От времени, проведенного за компьютером, у меня болит живот. - person bazza; 20.02.2018
comment
@R, будет интересно посмотреть, будет ли принято решение об изменении формального определения UTC, чтобы больше не было високосных секунд, до или после того, как мир программного обеспечения начнет решать проблемы, возникающие сегодня. Я не собираюсь вкладывать в это деньги в любом случае! - person bazza; 20.02.2018

Я прочитал это на 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, включая високосные секунды, с точными секундами. Чтобы перевести «секунды с эпохи» в год, месяц, день, часы, минуты, секунды, требуется знание всех високосных секунд с эпохи (или до эпохи, если вы обрабатываете время до этого). И часы, которые будут возвращать гарантированно точное время по Гринвичу без високосных секунд и секунд, которые являются почти, но не совсем постоянным временем.

person gnasher729    schedule 18.02.2018
comment
Если я правильно помню, UTC - это стандарт времени в часовом поясе GMT. Таким образом, gmtime() не может одновременно работать в UTC и GMT. , похоже, что gmtime() работает одновременно в UTC в часовом поясе GMT. - person Yuki; 18.02.2018
comment
@Yuki Часовой пояс GMT (Лондон, Дублин, Лиссабон) на компьютере почти совпадает с UTC, за исключением того, что большинство реализаций ошибаются во время дополнительной секунды и при расчете количества секунд UTC между моментами по обе стороны от дополнительной секунды. Использование букв GMT для описания этого часового пояса на компьютере, строго говоря, неточное; GMT больше похож на UT1, а не на UTC. Выбор, который они сделали много лет назад, чтобы вызвать функцию gmtime, является неудачным, учитывая ее спецификацию... Гражданское время Великобритании зимой - это UTC, а не GMT. - person bazza; 18.02.2018
comment
В подобном обсуждении нет никакой полезной разницы между терминами UTC и GMT. UTC — это очень точно определенный термин. GMT может означать одно из двух: (2) точно такое же, как UTC. (2) Часовой пояс, который они используют в Великобритании зимой, точно так же, как EST — это часовой пояс, который они используют в Нью-Йорке зимой. Функцию C gmtime действительно правильнее было бы назвать utctime. - person Steve Summit; 18.02.2018
comment
@gnasher729 Если вам нужны другие часы, которые будут возвращать точное значение UTC, включая дополнительные секунды, с точными секундами, вы можете получить их, но вы не можете использовать time_t для представления их значения! - person Steve Summit; 18.02.2018
comment
Кроме того, если вы используете счетчик секунд, начиная с эпохи (то есть, если вы используете что-то вроде time_t), и если вы хотите сделать это правильно, с дополнительными секундами, пожалуйста, не делайте этого представьте, что вы делаете UTC! Если вы делаете строгий подсчет секунд с начала эпохи, вы, вероятно, делаете TAI. (И затем, да, если вы хотите преобразовать год, месяц, день, часы, минуты, секунды из TAI в UTC, вам понадобится эта таблица високосных секунд.) - person Steve Summit; 18.02.2018

Другой аспект их проблемы заключается в наличии библиотеки, которая «знает так» о високосных секундах. Большинство библиотек этого не делают, поэтому ответы, которые вы получаете от таких функций, как gmtime, строго говоря, неточны в течение високосной секунды. Кроме того, расчеты разницы во времени часто дают неточные результаты, охватывающие дополнительную секунду. Например, значение time_t, данное вам вчера в то же самое время UTC, ровно на 86400 секунд меньше сегодняшнего значения, даже если на самом деле была дополнительная секунда.

Астрономическое сообщество решило эту проблему. Вот библиотека SOFA, в которой есть правильные распорядки времени. См. их руководство (PDF), раздел о сроках. Если он является частью вашего программного обеспечения и поддерживается в актуальном состоянии (новая версия требуется для каждой новой дополнительной секунды), у вас есть точные расчеты времени, преобразования и отображение.

person bazza    schedule 18.02.2018
comment
Наличие хорошей библиотеки (такой как SOFA, которую вы цитируете), конечно, важно, но этого не обязательно достаточно, если временные метки, с которыми вы имеете дело, исходили из вашей операционной системы, а ваша ОС не поддерживает должным образом дополнительные секунды. Если gmtime дает вам неточное время в течение дополнительной секунды, это отчасти потому, что ОС не может дать вам точную отметку времени в течение этой дополнительной секунды, а отчасти потому, что значение time_t, которое вводится в gmtime, не может представлять дополнительную секунду. SOFA и другие библиотеки с поддержкой дополнительных секунд обязательно используют представления времени, отличные от time_t. - person Steve Summit; 18.02.2018
comment
@SteveSummit, это все правда, но ситуация лучше, чем была раньше. Linux + GPSD + NTPD + clock_gettime(CLOCK_TAI) + SOFA — это один из способов обойти все проблемы со стандартной библиотекой POSIX и «традиционными» функциями часов/времени в *nix. Эта комбинация дает вам правильное время, правильные локализованные представления времени, а также правильные расчеты времени. Это хорошее решение, если кто-то разрабатывает новую программу на C/C++ на современных ядрах Linux с подключенным правильным оборудованием GPS и избегает подпрограмм glibc. Он не может исправить существующее программное обеспечение, другие языки и т. д. - person bazza; 18.02.2018
comment
Ах, SOFA использует clock_gettime(CLOCK_TAI)? Вы правы, это хороший путь. (CLOCK_TAI еще не совсем пуленепробиваемый - см., например, головоломки в этот вопрос -- но это определенно произойдет.) - person Steve Summit; 18.02.2018
comment
@SteveSummit, я не уверен; Я не думаю, что у него есть какие-либо средства для получения времени, он просто способен правильно обрабатывать, преобразовывать и вычислять во всех основных временных масштабах. Хотя я считаю, что значения, получаемые из clock_gettime(CLOCK_TAI), можно использовать для создания объекта времени SOFA TAI, после чего все остальное несложно. Мы успешно использовали GPS + gpsd + ntpd, чтобы получить правдоподобный результат от clock_gettime(CLOCK_TAI), хотя нужно дождаться прихода альманаха GPS (около 12 минут после включения!). - person bazza; 18.02.2018
comment
@SteveSummit, однако создание приложения вокруг SOFA имеет проблему. Вы должны обновлять SOFA и перекомпилировать свое приложение каждый раз, когда объявляется новая дополнительная секунда; нет автоматического способа ввода данных о секунде координации в SOFA, все это запрограммировано. - person bazza; 18.02.2018
comment
Да, все эти обновления - боль. (1) Лично я думаю, что clock_gettime(CLOCK_TAI) должен возвращать -1, если он не знает taioffset. (Еще хуже, если ядро ​​не знает taioffset до тех пор, пока NTP не сообщит ему, что есть дополнительная секунда, после чего оно думает, что taioffset равно 1.) (2) У меня есть экспериментальное ядро ​​с жестко скомпилированной таблицей дополнительных секунд, но открыт -- для чтения и обновления -- через специальный файл в /proc. Но есть еще куча деталей, которые нужно проработать. - person Steve Summit; 19.02.2018
comment
@SteveSummit, Вау, звучит неплохо! Итак, какой-то демон (ntpd?) будет поддерживать его в актуальном состоянии, программные библиотеки будут использовать его, когда они выполняют преобразования, вычисления и т. д.? Звучит довольно круто. С этим у другого программного обеспечения больше не было бы оправдания для неправильного расчета времени. Потребуется некоторое время, чтобы это отфильтровалось для таких языков, как Java, и было воспроизведено в других ОС. Я полагаю, что если бы в других ОС была похожая вещь, это сделало бы принятие более вероятным. Интересно, сделали бы ребята из FreeBSD что-то подобное, а MS/Apple... - person bazza; 19.02.2018
comment
@SteveSummit, к вашему сведению, мы перешли на использование хронии - кажется, так легче начать работу. Просто проверяю, что он поглощает данные секунды координации из gpsd. - person bazza; 20.02.2018