2013-10-15 82 views
5

我有一个32位的Linux系统,在这个系统中,我必须记录时间戳为UINT32秒偏移量的数据,从1901-01- 01 00:00:00。从64位整数秒数创建boost :: posix_time :: ptime对象

计算时间戳是确定对我来说,我可以使用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消息,我必须使用RTC_SET_TIME调用ioctl调用来设置硬件和系统时钟。这个UINT32再次是自1901-01-01 00:00:00以来的偏移量。现在

我的问题是,我没有办法创建一个ptime对象使用64个整数 - 该time_duration对象的ticks一部分是私人的,我只能使用long其中我的32位系统上只是一个4字节的有符号整数不够大,不足以存储从我的时代开始的秒偏移量。

我无法控制时代的价值,所以我非常难以理解我如何从我拥有的数据中创建我所需的对象boost::posix_time::ptime。 我大概可以通过计算特定时间间隔内的第二次计数并使用额外的时期来创建一个桥来允许这个问题,但我想知道boost代码中是否有某些东西可以让我完全解决问题使用boost日期时间库。 我已经阅读了所有我能找到的文档,但我看不到任何明显的方法来做到这一点。

编辑:我发现此相关的问题Convert int64_t to time_duration但接受的答案有没有为我的划时代工作

回答

2

你可以在允许的最大增量适用TIME_DURATION秒(这是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 

查看它Live on Coliru

+0

感谢您的答案。我自己也做了类似的事情,我只是希望有一个解决方案,而不是解决问题。我猜这里没有答复表明没有答复。如果没有别的东西在几天后出现,我会接受你的回答。 – mathematician1975

+0

令人惊讶的是,这必须在2014年10月以C++(甚至是Boost)完成。为什么这些类型不是早就切换到64位的? –

+0

@DanNissenbaum我用你的答案进行了测试,确实,它更优雅! ** [Coliru](http://coliru.stacked-crooked.com/a/a0be0c728be95b1f)** – sehe

2

虽然boost::posix_time::seconds不能使用如果秒表示大于32的数位(截至2014年10月),它tu RNS指出,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位)毫秒,你是好去!


注意铍/与builting整数类型的能力非常/意识到自己不同的行为:

uint64_t offset = 113ul*365ul*24ul*60ul*60ul*1000ul; // 113 years give or take some leap seconds/days etc.? 

将在GCC或铛工作,但它只会溢出MSVC2013计算。你需要明确强制调用64位:

uint64_t offset = uint64_t(113ul)*365*24*60*60*1000; 
相关问题