5

我有一个 32 位 Linux 系统,在该系统中,我必须记录从 1901-01-01 00:00:00 开始的 UINT32 秒偏移量时间戳的数据。

计算时间戳对我来说没问题,因为我可以使用 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 值(无论如何也不会超过很多年)。

我遇到的问题是我的应用程序可以接收包含 UINT32 值的 modbus 消息,我必须通过ioctl调用来设置硬件和系统时钟RTC_SET_TIME。这个 UINT32 再次是自我的时代 1901-01-01 00:00:00 以来的偏移量(以秒为单位)。

我现在的问题是我无法使用 64 位整数创建对象 - 对象的一部分是私有的,我被限制在我的 32 位系统上使用它只是一个 4 字节有符号整数,不足以存储从我的时代偏移的秒数。ptimetickstime_durationlong

我无法控制 epoch 的价值,所以我真的很难boost::posix_time::ptime从我拥有的数据中创建我需要的对象。我可能可以通过计算特定时间间隔的硬秒计数并使用额外的时期来建立一个桥梁来获得一个肮脏的解决方案,但我想知道boost代码中是否有一些东西可以让我完全使用提升日期时间库。我已经阅读了我能找到的所有文档,但我看不到任何明显的方法来做到这一点。

编辑:我发现了这个相关的问题Convert int64_t to time_duration但那里接受的答案不适用于我的时代

4

2 回答 2

3

虽然如果秒表示大于 32 位的数字(截至 2014 年 10 月),则无法使用,但事实证明boost::posix_time::seconds 可以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;
于 2014-10-06T07:09:57.543 回答
2

您可以以最大允许增量(即std::numeric_limits<long>::max())应用 time_durations,因为该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

在 Coliru 上看到它

于 2013-10-15T13:08:33.883 回答