基础知识:
如果把时间想象成一个向前和向后都无限延伸的实数轴,那么时间点就是数轴上的一个点,时间段就是两个时间点之间确定的一个区间,时长(时间长度)则是一个有正负号的标量,它是两个时间点之差,不属于数轴。
时间点、时间段和时长三者之间可以进行运算,例如“时间点+时长=时间点”,“时长+时长=时长”“时间段∩时间段=时间段”、“时间点∈时间段”,等等,但有的运算也是无意义的,如“时间点+时间点”、“时长+时间段”,等等。这些运算都基于生活常识,很容易理解,但在编写时间处理程序时必须注意。
date_time库支持无限时间和无效时间(NADT,Not Available Date Time)这样特殊的时间概念,类似于数学中极限的含义。时间点和时长都有无限的值,它们的运算规则比较特别,例如“+ oo时间点+时长=+o时间点”,“时间点+ oo时长=+oo时间点”。如果正无限值与负无限值一起运算将有可能是无效时间,如“+ oo时长- oo时长=NADT”。
data_time
特殊值 | 含义 |
pos_infin | 表示正无限 |
neg_infin | 表示负无限 |
not_a_date_time |
无效时间 |
min_date_time | 可表示的最小日期或时间 |
max_date_time | 可表示的最大日期或时间 |
处理日期
template<typename T,typename calendar,typename duration_type_>
class date
{
public:
data(year_type,month_type,day_type);
year_type year() const;
month_type month() const;
day_type day() const;
day_of_week_type day_of_week() const;
ymd_type year_month_day() const;
bool operator<(const day_type&)const;
bool operator==(const day_type&)const;
......
};
date是一个轻量级的对象,很小,处理效率很高,可以被拷贝传值。date也全面支持比较操作和流输入输出,因此我们完全可以把它当成一个像int、string那样的基本类型来使用。
创建日期对象
date d1; //无效
date d2(2010,1,1); //数字
date d3(2000,Jan,1); //英文
date d4(d2); //拷贝
date 也允许从一个字符串产生,这需要使用工厂函数from_string ()或from_undelimited_string ()。前者使用分隔符(斜杠或者连字符)分隔年月日格式的字符串,后者则是无分隔符的纯字符串格式。例如:
date dl = from_string ( “1999-12-31”);
date d2( from_string(“2015/1/1”));
date d3 = from_undelimited_string ( “20011118”” );
day_clock 是一个天级别的时钟,它也是一个工厂类,调用它的静态成员函数local_day( )或universal_day()会返回一个当天的日期对象,分别是本地日期和 UTC日期。day_clock内部使用了c标准库的1ocaltime ( )和 gmtime ()函数,因此local_day ()的行为依赖于操作系统的时区设置。例如;
cout<<day_clock::local_day();
cout<<day_clock::universal_day();
我们也可以使用特殊时间概念枚举special_values创建一些特殊的日期,在处理如无限期的某些情形下会很有用:
#include<boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
int main()
{
std::cout<<date(neg_infin)<<std::endl;
std::cout<<date(pos_infin)<<std::endl;
std::cout<<date(not_a_date_time)<<std::endl;
std::cout<<date(max_date_time)<<std::endl;
std::cout<<date(min_date_time)<<std::endl;
}
//
-infinity
+infinity
not-a-date-time
9999-Dec-31
1400-Jan-0
访问日期
成员函数:
成员函数year ( ).month ()和day()分别返回日期的年、月、日:
date(2017,6,1);
assert(d.year()==2017);
assert(d.month()==6);
assert(d.day()==1);
成员函数year_month_day ()返回一个date : : ymd_type结构,可以一次性地获取年月日数据:
date::ymd_type ymd=d1.year_month_day();
assert(ymd.year==2022);
assert(ymd.month==1);
assert(ymd.day==10)
成员函数day _of_week ()返回date 的星期数,0表示星期天。day_of_year()返回date是当年的第几天(最多是366)。end_of_month ( )返回当月的最后一天的date对象:
date d1(2022,1,10);
std::cout<<d1.day_of_week()<<std::endl;
std::cout<<d1.day_of_year()<<std::endl;
//Mon
//10
成员函数week number()返回date所在的周是当年的第几周,范围是0至53;
date d1(2022,1,10);
std::cout<<d1.week_number()<<std::endl;
//2
日期的输出
三个自由函数:
date d1(2022,1,10);
to_simple_string(d1);
to_iso_string(d1);
to_iso_extended_string(d1);
//2022 -Jan-10
20220110
2022-01-10
转化c结构
to_tm(date) : date转换到tm。tm的时分秒成员(tm_hour/tm_min/tm_sec)均置为0,夏令时标志tm_isdst置为-1(表示未知)。
date_from_tm(tm datetm) : tm 转换到date。只使用年、月、日三个成员(tm_year/tm_mon/tm_mday),其他成员均被忽略。
#include<boost/date_time/gregorian/gregorian.hpp>
#include<time.h>
#include<iostream>
using namespace boost::gregorian;
int main()
{
date d1(2022,9,11);
tm t=to_tm(d1);
assert(t.tm_hour==0&&t.tm_min==0);
assert(t.tm_year==122&&t.tm_mday==11);
date d2=date_from_tm(t);
if(d1==d2)
{
std::cout<<"ture"<<std::endl;
}
}
//ture
日期长度
日期长度是以天为单位的时长,是度量时间长度的一个标量。它与日期不同,值可以是任意的整数,可正可负。基本的口期长度类是date_duration
date_duration可以使用构造函数创建一个日期长度,
成员函数days ()返回时长的天数,
如果传入特殊时间枚举值则构造出一个特殊时长对象。is_special ()和is_negative ()可以判断date duration对象是否为特殊值、是否是负值。
unit ( )返回时长的最小单位,即date duration(1)
date_duration支持全序比较操作(==、!=、<、<=等),也支持完全的加减法和递增递减操作,用起来很像一个整数。此外 date_duration还支持除法运算,可以除以一个整数,但不能除以另一个date_duration,其他的数学运算如乘法、取模、取余则不支持。
date_time库为date_duration定义了一个常用的typedef: days,这个新名字更好地说明了date duration的含义——它是一个天数的计量。
用法:
#include<boost/date_time/gregorian/gregorian.hpp>
#include<time.h>
#include<iostream>
using namespace boost::gregorian;
int main()
{
days dd1(10),dd2(-100),dd3(255);
if(dd1>dd2&&dd1<dd3)
{
std::cout<<"yes"<<std::endl;
}
if(dd1+dd2==days(-90))
{
std::cout<<"yes"<<std::endl;
}
std::cout<<(dd1+dd3).days()<<std::endl;
}
为了方便计算时间长度,date_time库还提供了months、years、weeks 等另外三个时长类,分别用来表示月、年和星期,它们的含义与days类似,但行为不太相同。
months 和 years 全面支持加减乘除运算,使用成员函数number_of_months ()和number_of_years ()可获得表示的月数和年数。weeks是date_duration的子类,除了构造函数以7为单位外其他的行为与days完全相同,可以说是一个days的近义词。
week w(3);
assert(w.days()==21);
months m(3);
years y(2) ;
months m2=y+m;
assert(m2.number_of_months()==29);
assert((y*2).number_of_years()==4);
日期运算
date d1(2000,1,1) d1(2017,11,18)
cout<<d2-d1<<endl;//6531
d1+=days(10)
等。。。。
日期区间
date_period来表示日期区间概念
左闭右开
常用
date_period dp(date(2017,1,1),datys(20));
成员函数:
成员函数 begin ()和 last ()返回日期区间的两个端点,而end ()返回last()后的第天,与标准容器中的 end ()含义相同,是一个“逾尾的位置”。length ()返回日期区间的度,以天为单位。如果日期区间在构造时使用了左大右小的端点或者日期长度是 0
date_period可以进行全序比较运算,但比较不是依据日期区间的长度,而是依据区间的端点,即第一个区间的end ()和第二个区间的 begin ( ),判断两个区间在时间轴上的位置大小。如果两个日期区间相交或者包含,那么比较操作无意义。
日期区间的运算:
成员函数shift ( )和 expand ()可以变动区间:
shift()将日期区间平移n天而长度不变,expand ()将日期区间向两端延伸n天,相当于区间长度加2n天。
成员函数shift ( )和 expand ()可以变动区间: shift()将日期区间平移n天而长度不变,expand ()将日期区间向两端延伸n天,相当于区间长度加2n天。例如:
date_period还可以使用成员函数判断某个日期是否在区间内,或者计算日期区间的交集:
is_before/is_after | 日期区间是否在日期前或后; |
contains() | 日期区间是否包含另一个区间或者日期; |
intersects() | 两个日期区间是否存在交集; |
intersections |
返回两个区间的交集, |
is_adjacent() | 如果无交集返回一个无效区间;两个日期区间是否相邻。 |
date_period提供啦两种并集操作
merge ( ) :返回两个区间的并集,如果区间无交集或者不相邻则返回无效区间;
span () :合并两日期区间及两者间的间隔,相当于广义的merge ().
日期迭代器
date_time库为日期处理提供了迭代器的概念,可以用简单的递增或者递减操作符连续访问日期,这些迭代器包括day_iterator.week_iterator.month_iterator和 year_iterator,它们分别以天、周、月和年为单位增减。
日期迭代器的用法基本类似,都需要在构造时传入一个起始日期和增减步长(可以是一天、两周或者N个月,等等,默认是1个单位),然后就可以用operator++、operator–变化
日期。迭代器相当于一个date对象的指针,可以用解引用操作符*获得迭代器当前的日期对象,也可以用->直接调用日期对象的成员函数。
#include<boost/date_time/gregorian/gregorian.hpp>
#include<time.h>
#include<iostream>
using namespace boost::gregorian;
int main()
{
date d1(2022,9,11);
day_iterator d_iter(d1);
assert(d_iter==d1);
++d_iter;
assert(d_iter==date(2022,9,12));
year_iterator y_iter(*d_iter,10);
assert(y_iter==d1+days(1));
++y_iter;
std::cout<<y_iter->year()<<std::endl;
}
处理时间
#include<boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
#include<iostream>
int main()
{
//hour minute second millisec
time_duration td(1,10,30,1000);
//自动借位
//2 01 06 1ms
time_duration td1(1,60,60,1000*1000*6+1000);
hours h(1);
minutes m(10);
seconds s(30);
millisec ms(1);
time_duration td2=h+m+s+ms;
std::cout<<td2.hours()<<std::endl;
}
时间精确度:
date_time 库默认时间的精确度是微秒,纳秒相关的类和函数如nanosec和成员函数nanoseconds ( ) 、total_nanoseconds()都不可用,秒以下的时间度量都使用微秒。
当定义了宏BOOST_DATE_TIME_POSIx_TIME_STD_CONFIG时,time_duration的一些行为将发生变化,它的时间分辨率将精确到纳秒,构造函数中秒以下的时间度量单位也会变成纳秒。
time_duration td(1,10,30,1000)//1000 ns 1us
cout<<td;
成员函数:
成员函数fractional_seconds ()仍然返回秒的小数部分,但单位是纳秒,这也是它的名称不叫milli_seconds ()或者nano_seconds ()的原因:
静态成员函数unit()返回一个time_duration对象,它是time_duration计量的最小单位,相当于time_duration(0,0,0,1),默认情况下是微秒,如果定义了BOOST_DATE_TIME_POSIX_TIME_STD CONFTG则是纳秒:
time_duration提供静态成员函数resolution ()和 num_fractional_digits ()来检测当前的精度:
纳秒
td.resolution()==date_time::nano
td.num_frrractional_digits()==9;
时间点:
在熟悉了时间长度类time_duration后,理解时间点概念就容易多了,它相当于一个日期再加上一个小于24小时的时间长度。如果时间轴的基本单位是天,那么日期就相当于整数,时间点则是实数,定义了天之间的小数部分。
ptime是date_time库处理时间的核心类,它使用64位(微秒级别)或者96位(纳秒级别)的整数在内部存储时间数据,依赖于date和time_duration,因此接口很小。
ptime p1=time_from_string(“2017-7-7 01:00:00”)
ptime p(date(2017,7,7),hour(1));
操作时间点对象
#include<boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
#include<boost/date_time/gregorian/gregorian.hpp>
#include<iostream>
using namespace boost::gregorian;
int main()
{
time_duration td(11,35,50,1000);
ptime p(date(2022,9,11),td);
std::cout<<p<<std::endl;
date d=p.date();
time_duration td2=p.time_of_day();
std::cout<<td2<<std::endl;
p+=minutes(20);
std::cout<<p;
}
转化c结构
使用函数to_tm ( ) , ptime可以转换到tm结构,转换规则是date和time_duration的组合,而ptime_from_tm ( )则可以把 tm结构转换成ptime。
#include<boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
#include<boost/date_time/gregorian/gregorian.hpp>
#include<iostream>
#include<time.h>
using namespace boost::gregorian;
int main()
{
time_duration td(11,35,50,1000);
ptime p(date(2022,9,11),td);
tm t=to_tm(p);
std::cout<<t.tm_year;
if(ptime_from_tm(t)==p)
{
std::cout<<"yes"<<std::endl;
}
}
//122
时间区间
类似于日期区间
时间迭代器
不同于日期迭代器,时间迭代器只有一个time_iterator。它在构造时传入一个起始时间点 ptime对象和一个步长 time_duration对象,然后就同日期迭代器一样使用前置式operator++、operator–来递增或递减时间,解引用操作符返回一个ptime对象。
#include<boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
#include<boost/date_time/gregorian/gregorian.hpp>
#include<iostream>
#include<time.h>
using namespace boost::gregorian;
int main()
{
time_duration td(11,35,50,1000);
ptime p(date(2022,9,11),td);
for(time_iterator t_iter(p,minutes(10));
t_iter<p+hours(1);++t_iter)
{
std::cout<<*t_iter<<std::endl;
}
}
//
2022-Sep-11 11:35:50.001000
2022-Sep-11 11:45:50.001000
2022-Sep-11 11:55:50.001000
2022-Sep-11 12:05:50.001000
2022-Sep-11 12:15:50.001000
2022-Sep-11 12:25:50.001000
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/129678.html