学习笔记:BOOST日期时间库

明确有三个时间有关的概念。1)时间点。类似直线上的一个点的坐标。2)时间间隔。类似在直线上一个与位置无关的具有一定长度的线段。3)时间区间。两个时间点之间的区间(与时间点有关)
与其它库不同的是,日期有独立的模块date类。其它的例如struct tm是年月日时分秒放到一个结构体的。
时间具有不同分辨率的需求。比如我要计算这个月的天数,以及下个月的第二个星期五是几号,只需要date(日)级分辨率。
计算3个小时零4分后时刻值,或者20毫秒之后时刻值,就需要秒级(second)和更高分辨率的类。
对于秒级(和毫秒,微妙,纳秒),使用一个叫做time_duration的类,这个类的作用是[时间间隔]这个概念。这是个基本概念,要先理解。
与time_duration类相关的概念是:小时,分,秒,神秘的fractional_seconds。例如:2:32:59.123456这个时长代表2小时32分59秒又0.123456秒。
123456就是那个神秘的fractional_seconds。为什么比较神秘呢?因为这里面有个坑。

//这是一个马拉松比赛成绩:
time_duration td3(duration_from_string("02:59:38.12")); 
ASSERT_TRUE(td3.fractional_seconds() == 123000); //提取秒的小数部分。实际就是0.12秒

time_duration td(23, 59, 59, 1000); 
//善意提醒一下:1000不是fractional_seconds,而是tick值。
//tick值的单位可能是微妙,也可能是纳秒,由BOOST_DATE_TIME_HAS_NANOSECONDS
//这个宏在编译时决定。一般来说,这个1000可能是0.001000秒,也可能是0.000001000秒。
//这样就很不方便和具有坑人的地方。

//与BOOST_DATE_TIME_HAS_NANOSECONDS有关
ASSERT_TRUE(time_duration::ticks_per_second() == 1000000);   //最低分辨率1微妙。

解决办法是,将用户需要的tick值,用公式转化为系统tick值。例如我的马拉松时长的秒后,精确到0.01秒。也就是0.01秒为一个我自己的tick单位。那么转化到系统tick是多少呢?
在1000000个tick每秒的系统里,0.01秒需要耗用10000个tick。

int usertick = 12;
int systicks = usertick * boost::posix_time::time_duration::ticks_per_second() / 100;

time_duration td(2, 59, 38, systicks);
ASSERT_TRUE(to_simple_string(td) == "02:59:38.120000");

date类是一个时间点。用法比较简单。
 

date d(2020, 10, 10);
d += days(1);  //时间点 + 时间间隔 = 另一个时间点
d += months(1);
d += years(1);

date dA(2000, 1, 1), dB(2000, 1, 3);
days aa = dB - dA;  //两个时间点相减,得到一个时间间隔(可为负)

一个完整的日期时间类ptime,可以认为是由date和time_duration构成的。这个一个时间点。

    date d(2020, 10, 10);
    time_duration td(1, 2, 3, 1000);

    ptime pp(d, td);

日期间隔:date_duration类。日期区间是date_period。时间区间是time_period。这里不展开。需要说明的是日期迭代器的概念。
例如:我要遍历每个月的29号,按照常规思维,构造一个是29号的日期类,依次累加一个月的时间间隔(+=month(1)),实际上有个坑的。例如下个月没有29号,则被迫取到月底的最后一天(28号),再加一个月就会丢失定位在29号的初衷。
因为每个月有28,29,30,31这多种情况。如果用date_iterator类,则会比较好的处理这个问题。

// using months duration type
date d(2005, Nov, 29);
d += months(1); // "2005-Dec-29"
d += months(1); // "2006-Jan-29"
d += months(1); // "2006-Feb-28" --> snap-to-end-of-month behavior kicks in
d += months(1); // "2006-Mar-31" --> unexpected result
d -= months(4); // "2005-Nov-30" --> unexpected result, not where we started

// using month_iterator
month_iterator itr(date(2005, Dec, 30));
++itr; // "2006-Jan-30" --> ok
++itr; // "2006-Feb-28" --> snap-to DOES NOT kick in 
++itr; // "2006-Mar-30" --> ok
--itr; // "2006-Feb-28" --> ok
--itr; // "2006-Jan-30" --> ok
--itr; // "2005-Dec-30" --> ok, back where we started

日期迭代器是个辅助计算日期的类,无需要求容器类date的生存期,它实际是拷贝了date类的数据给自己用。而stl容器就不允许,vector<int>::iterator ite(  std::vector<int>(10).begin() ) ; 上述是错误的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值