Существует ли какая-либо реализация на С++ 64-битных преобразований временных меток Unix для 32-битных систем? Мне нужно преобразовать struct tm в 64-битное целое число и наоборот, включая високосные годы, часовые пояса, UTC. Также нужна переносимость, по крайней мере, для GNU/Linux и Windows.
Вопрос
Преобразование 64-битной временной метки Unix
- Что должна представлять эта отметка времени? Если это всего лишь секунды с начала эпохи, вы можете просто использовать 32-битную функцию преобразования и скопировать результат в 64-битное целое число (до 2038 года) PlasmaHH 27.10.2011
- Разве time_t уже не 64-битный на большинстве систем? Windows имеет большинство функций и в 64-битном варианте. Просто погуглите. RedX 27.10.2011
- Целое число не может представлять часовые пояса, так как это относительное смещение от произвольной эпохи (в UNIX это 01 января 1970 года), но часовой пояс не определен. Если вы хотите представить эти элементы, вам все равно придется разбить их на struct. Также никто не "представляет" високосные годы; как бы они? Держите бессмысленный счет или что-то в этом роде? trojanfoe 27.10.2011
- PlasmaHH: Точно, только не раньше 2038 года. Adam Trhon 27.10.2011
- RedX: Я полагаю, что только на 64-битных системах. Пожалуйста, поправьте меня, если я ошибаюсь. Adam Trhon 27.10.2011
- trojanfoe: Вы правы, целое число не может представлять ни одно из них. Но вы должны учитывать их при конвертации в struct tm Adam Trhon 27.10.2011
Ответы
Ответ 1 · рейтинг 13 · Alexei Khlebnikov
Тебе нужно:
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:
Ответ 2 · рейтинг 7 · Basile Starynkevitch
Функция, преобразующая 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, а это намного больше. сложнее (это зависит от ядра и железа).
Ответ 3 · рейтинг 6 · Miguel
Кажется, вы делаете предположение, что 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. Здесь указано местное время. Источник имеет гиперссылку, так что вы можете легко найти остальные.
Ответ 4 · phuclv
Поддержка 64-битного времени в 32-битной версии Linux была впервые представлена в ядре 5.1 с добавлением новых *time64 системных вызовов a> (поскольку изменение возвращаемого типа старых системных вызовов ломает старые приложения). Проверьте эту таблицу, и вы увидите, что эти системные вызовы доступны только на 32-разрядных платформы.
Но это только поддержка со стороны ядра. Вы можете вызвать clock_gettime64 напрямую (из встроенного ассемблера или из C с помощью syscall()), чтобы получить текущее время, но вам понадобится код, специфичный для 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.
Для получения дополнительной информации прочитайте
Ответ 5 · рейтинг -1 · Alex Force
Да, используйте stuct tm *_localtime64 ( const __time64_t *timer);
Это если у вас вентилятор на окнах.
Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.
Похожие материалы
- Если первый операнд аддитивного выражения может быть преобразован как в указатель, так и в целое число, какое
- EOF в boost::async_read с thread_pull и boost 1.54
- Следовать макету, кроме контента
- Qt5: почему 2 процесса и использование памяти?
- Ограничение длины имени файла в bash
- Проблема установки Solr: я не могу войти на страницу администратора http://xx.xx.xx.xx:8983/solr/admin