Существует ли какая-либо реализация на С++ 64-битных преобразований временных меток Unix для 32-битных систем? Мне нужно преобразовать struct tm
в 64-битное целое число и наоборот, включая високосные годы, часовые пояса, UTC. Также нужна переносимость, по крайней мере, для GNU/Linux и Windows.
Преобразование 64-битной временной метки Unix
Ответы (5)
Тебе нужно:
typedef long long time64_t;
time64_t mktime64(struct tm *t);
struct tm* localtime64_r(const time64_t* t, struct tm* p);
Первоначально (в 2011 году) этот ответ содержал ссылки на 2038bug.com, где можно было скачать небольшую pivotal_gmtime_r
библиотеку, содержащую упомянутые функции. Библиотека тогда была удалена с 2038bug.com, ссылки стали битыми и были удалены из ответа модератором. Похоже, этот код pivotal_gmtime_r
теперь можно найти здесь:
https://github.com/franklin373/mortage/tree/master/time_pivotal
Кроме того, я нашел другую, более новую библиотеку под названием y2038
, которая также реализует mktime64
и localtime64_r
:
https://github.com/evalEmpire/y2038
localtime
так много упоминалось в этой ветке, что я перепутал. :) Конечно нужен gmtime64_r
.
- person Alexei Khlebnikov; 16.11.2011
mktime
ожидает местное время и предположительно получит часовой пояс из ваших локальных настроек и преобразует его в UTC
. Но этот mktime64
не зависит от часового пояса. т.е. он даст вам вывод time64_t
в UTC
, если вы подадите ввод struct tm
в UTC
, вывод в UTC+10
, если вы подадите ввод в UTC+10
и т. д.
- person Alexei Khlebnikov; 22.11.2011
ack mktime64 /usr/include/
возвращается пустым в последних версиях Linux
- person dargaud; 18.12.2019
Функция, преобразующая struct tm*
в time_t
, называется mktime
. Вы можете найти множество его реализаций, например. в Glibc и в файле mktime.c
libvxc. Вы можете взять код (при условии, что он является законным для вас, поэтому, пожалуйста, уважайте лицензии) и изменить time_t
на какое-то 64-битное целое число, например int64_t
.
Функции, выполняющие другие преобразования из time_t
в struct tm*
, — это localtime
или gmtime
, и вы можете сделать то же самое.
Однако у вас может быть более фундаментальная проблема: ваша 32-битная машина, работающая в 2040 году, должна каким-то образом сообщать вам текущее время (как это делает системный вызов time
) соответствующим образом в 64-битном варианте time_t
, а это намного больше. сложнее (это зависит от ядра и железа).
localtime
переносимым способом?
- person Adam Trhon; 05.11.2011
time_t
может быть 32-битным или 64-битным целым числом (поэтому машинный код должен быть другим).
- person Basile Starynkevitch; 05.11.2011
mktime
они не корректируют диапазоны в struct tm
.
- person Adam Trhon; 05.11.2011
mktime()
от minix.
- person jfs; 06.11.2011
libvxc
неплохо. И, кстати, для исправления ситуации с преобразованием локального UTC достаточно одной строки кода, так что на самом деле это не проблема.
- person Agnius Vasiliauskas; 21.11.2012
Кажется, вы делаете предположение, что time_t
является 32-битным в 32-битных системах, и это может быть правдой, а может и не быть.
В Windows, начиная с Visual Studio 2005, размер time_t
составляет 64 бита, даже при компиляции для 32-битной Windows.
К сожалению, glibc определяет его как long int
, что в 32-битных системах является 32-битным целым числом. Это означает, что 32-битный Linux и другие 32-битные платформы, основанные на gcc/glibc (например, Cygwin), не смогут работать с 64-битными метками времени.
Если ваше приложение должно работать на 32-битной glibc, вы должны использовать свои собственные функции преобразования, которые могут быть теми же функциями в библиотеке C, перекомпилированные для использования 64-битных временных меток.
Если вам нужен исходный код с разрешающей лицензией (BSD), то вы можете посмотреть эти функции в minix3. Здесь указано местное время. Источник имеет гиперссылку, так что вы можете легко найти остальные.
Поддержка 64-битного времени в 32-битной версии Linux была впервые представлена в ядре 5.1< /a> с добавлением новых *time64
системных вызовов a> (поскольку изменение возвращаемого типа старых системных вызовов ломает старые приложения). Проверьте эту таблицу, и вы увидите, что эти системные вызовы доступны только на 32-разрядных платформы.
Но это только поддержка со стороны ядра. Вы можете вызвать clock_gettime64
напрямую (из встроенного ассемблера или из C с помощью syscall()
< /a>), чтобы получить текущее время, но вам понадобится код, специфичный для Linux, потому что пока нет поддержки glibc. Для полной поддержки userspace у вас должна быть Linux 5.6 или выше, а также musl 1.2+ или glibc 2.32+. Просто перестройте свой код, и time_t
станет 64-битным. Теперь код, использующий time_t
, станет полностью переносимым.
Все пользовательское пространство должно быть скомпилировано с 64-битной
time_t
, которая будет поддерживаться в следующих выпусках musl-1.2 и glibc-2.32 вместе с установленными заголовками ядра от linux-5.6 или выше.Приложения, которые напрямую используют интерфейсы системных вызовов, необходимо портировать для использования системных вызовов
time64
, добавленных в linux-5.1, вместо существующих системных вызовов. Это влияет на большинство пользователейfutex()
иseccomp()
, а также на языки программирования, которые имеют собственную среду выполнения, не основанную на libc.
Для получения дополнительной информации прочитайте
- Приближается конец игры ядра - 2038 год
- Обсуждение решения проблемы Y2038: 2038 год ближе, чем кажется
- обработка 64-битных символов времени в GNU C Библиотека
- дизайн glibc Y2038 Proofness
- Изменить time_t и clock_t на 64-битные
Да, используйте stuct tm *_localtime64 ( const __time64_t *timer);
Это если у вас вентилятор на окнах.
_localtime64_s
безопаснее кстати
- person Guy L; 10.01.2014
time_t
уже не 64-битный на большинстве систем? Windows имеет большинство функций и в 64-битном варианте. Просто погуглите. - person RedX   schedule 27.10.2011struct
. Также никто не «представляет» високосные годы; как бы они? Держите бессмысленный счет или что-то в этом роде? - person trojanfoe   schedule 27.10.2011struct tm
- person Adam Trhon   schedule 27.10.2011