boost之日期 时间(date_time)

基础知识:

如果把时间想象成一个向前和向后都无限延伸的实数轴,那么时间点就是数轴上的一个点,时间段就是两个时间点之间确定的一个区间,时长(时间长度)则是一个有正负号的标量,它是两个时间点之差,不属于数轴。

时间点、时间段和时长三者之间可以进行运算,例如“时间点+时长=时间点”,“时长+时长=时长”“时间段∩时间段=时间段”、“时间点∈时间段”,等等,但有的运算也是无意义的,如“时间点+时间点”、“时长+时间段”,等等。这些运算都基于生活常识,很容易理解,但在编写时间处理程序时必须注意。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值