У меня есть 32-битная система Linux, в которой я должен записывать данные с меткой времени с секундным смещением UINT32 от эпохи 1901-01-01 00:00:00.
расчета временная метка мне подходит, так как я могу использовать 64 бит ticks()
счетчик и ticks_per_second()
функции для генерации секунд, начиная с эпохи, следующим образом (мне требуется только разрешение второго уровня)
const ptime ptime_origin(time_from_string("1901-01-01 00:00:00"));
time_duration my_utc = microsec_clock::universal_time() - ptime_origin;
boost::int64_t tick_per_sec = my_utc.ticks_per_second();
boost::int64_t tick_count = my_utc.ticks();
boost::int64_t sec_since_epoch = tick_count/tick_per_sec;
Это работает для меня, так как я знаю, что как целое число без знака, количество секунд не будет превышать максимальное значение UINT32 (ну, во всяком случае, не на много лет).
У меня проблема в том, что мое приложение может получить сообщение Modbus, содержащее значение UINT32, для которого я должен установить аппаратные и системные часы с помощью ioctl
звоните используя RTC_SET_TIME
, Этот UINT32 снова является смещением в секундах с моей эпохи 1901-01-01 00:00:00.
Моя проблема сейчас в том, что у меня нет возможности Создайте ptime
объект, использующий 64-битные целые числа — ticks
часть time_duration
объекты являются частными, и я ограничен в использовании long
которая в моей 32-битной системе представляет собой 4-байтовое целое число со знаком, недостаточно большое для хранения смещения секунд от моей эпохи.
Я не имею никакого контроля над ценностью эпохи, и поэтому я действительно озадачен тем, как я могу создать свой требуемый boost::posix_time::ptime
объект из данных у меня есть.
Вероятно, я могу получить грязное решение, рассчитав счетчик жестких секунд для определенных временных интервалов и используя дополнительную эпоху, чтобы сделать мост, чтобы позволить это, но мне было интересно, есть ли что-то в boost
код, который позволит мне полностью решить проблему с помощью библиотеки datetime boost.
Я прочитал всю документацию, которую могу найти, но не вижу никакого очевидного способа сделать это.
РЕДАКТИРОВАТЬ: я нашел этот связанный вопрос Конвертировать int64_t в time_duration но принятый ответ там не работает для моей эпохи
Вы могли бы применить time_durations в максимально допустимых приращениях (что std::numeric_limits<long>::max()
) так как total_seconds
поле ограничено long
(Подпись).
Заметка: Я сформулировал это как int32_t
ниже, чтобы он все равно работал правильно, если скомпилирован на 64-битной платформе.
Вот небольшая демонстрация:
#include "boost/date_time.hpp"#include <iostream>
using namespace boost::gregorian;
using namespace boost::posix_time;
int main()
{
uint64_t offset = 113ul*365ul*24ul*60ul*60ul; // 113 years give or take some leap seconds/days etc.?
static const ptime time_t_epoch(date(1901,1,1));
static const uint32_t max_long = std::numeric_limits<int32_t>::max();
std::cout << "epoch: " << time_t_epoch << "\n";
ptime accum = time_t_epoch;
while (offset > max_long)
{
accum += seconds(max_long);
offset -= max_long;
std::cout << "accumulating: " << accum << "\n";
}
accum += seconds(offset);
std::cout << "final: " << accum << "\n";
}
Печать:
epoch: 1901-Jan-01 00:00:00
accumulating: 1969-Jan-19 03:14:07
final: 2013-Dec-04 00:00:00
Видеть это Жить на Колиру
Хотя boost::posix_time::seconds
не могу использоваться, если секунды представляют число больше 32 бит (по состоянию на октябрь 2014 г.), получается, что boost::posix_time::milliseconds
Можно легко использовать (без обходных путей), а именно:
inline std::string convertMsSinceEpochToString(std::int64_t const ms)
{
boost::posix_time::ptime time_epoch(boost::gregorian::date(1970, 1, 1));
boost::posix_time::ptime t = time_epoch + boost::posix_time::milliseconds(ms);
return boost::posix_time::to_simple_string(t);
}
Итак, просто преобразуйте свои 64-битные секунды в (64-битные) миллисекунды, и все готово!
Заметка Быть / очень / знать о зависимом от компилятора поведении с возможностью создания целочисленных типов:
uint64_t offset = 113ul*365ul*24ul*60ul*60ul*1000ul; // 113 years give or take some leap seconds/days etc.?
будет работать на GCC или Clang, но это просто переполнит вычисления в MSVC2013. Вам нужно было бы явно привести вычисление к 64 битам:
uint64_t offset = uint64_t(113ul)*365*24*60*60*1000;