C++ boost——时间与日期

news/2024/9/22 19:28:19/

文章目录

    • timer
    • progress_timer
    • date_time
        • 创建日期
        • 访问日期
        • 日期输出
        • 转换C结构
        • 日期长度
        • 日期运算
        • 日期区间
        • 日期区间运算
        • 日期迭代器
        • 其他功能
        • 综合运用

timer

是一个小型计时器,提供毫秒级的精度
适用于要求不高的程序计时任务

class timer
{
public :timer()(_start_time = std::clock();}void restart(){_start_time = std::clock();}double elapsed() const { return double(std::clock() - _start_time)/ CLOCKS _PER_SEC; }double elapsed_min() const{return double(1)/double(CLOCKS_PER_SEC);)double elapsed_max() const{return (double((std::numeric_limits<std::clock_t>::max)())- double(_start_time))/double(CLOCKS _PER_SEC);}private :std::clockt _start_time;
};
#include <boost/timer.hpp>
using namespace boost; int main()
{timer t;cout<<"max timespan:"<<t.elapsed_max() /3600 << "h" <<endl;cout<<"min timespan:"<<t.elapsed_min()<< "s" << endl;cout << "now time elapsed:"<< t.elapsed()<<"s"<< endl;
}

progress_timer

派生自timer,自动计时的小工具

class progress_timer : public timer, noncopyable
{
public:explicit progress_timer();progress_timer(std::ostream& os);~progress_timer();
};
#include<boost/progress.hpp>int main()
{// 第一个计时器{boost::progress_timer t;// do sth}std::stringstream ss;{boost::progress_timer t(ss);// do sth}std::cout<<ss.str();
}

date_time

date_time库基于格里高利历,支持从“1400-01-01”到“9999-12-31”

处理日期的组件

#include<boost/date_time/gregorian/gregorian.hpp>

处理时间组件

#include <boost/date_time/posix_time/posix_time.hpp>
template<typename T, typename calendar, typename duration_type>
class date
{
public:date(year_type, month_type, day_type);date(const ymd 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 date type &) const;bool operator==(const date type &) const;// 有效验证bool is_special() const;bool is_not_a_date() const;bool is_infinity() const;bool is_pos_infinity() const;bool is_neg_infinity() const;special_values as_special() const;duration_type  operator-(const date type &)const;...
};
创建日期
date d1;  // 无效日期
date d2(2010, 1, 1);
date d3(2010, Jan, 1);
date d4(d2);assert(d1 == date(not_a_date_time));
assert(d2 == d4);
assert(d3 < d4);date d1 = from_string("2010-12-20");
date d2(from_string("2010-12-20"));
date d3 = from_undelimited_string("20100502");
访问日期
date d(2017, 6, 1);
date::ymd_type ymd = d.year_month_day();
assert(ymd.year == 2013);
assert(ymd.month == 2);
assert(ymd.day == 2);cout << d.day_of_week()<< endl;  // Thu   周四
cout << d.day of year()<< endl;  //  152  当年第152天//  week_number()返回 date所在的周是当年的第几周
cout << date(2015,1,10).week_number()<< endl;  // 2
日期输出
date d(2017,1,23);
cout<< to_simple_string(d)<< endl;         // 2017-Jan-23
cout <<to_iso_string(d)<< endl;            // 20170123
cout << to_iso_extended_string(d)<< endl;  // 2017-01-23
cout << d<< endl;                          // 2017-Jan-23
转换C结构
date d(2017,5,20);
tmt = to_tm(d);
assert(t.tmyear == 117 && t.tmmday == 20);date d2 = date_from_tm(t);
assert(d == d2);
日期长度

日期长度是以天为单位的时长
是任意整数,可正可负
基本的日期长度类是date_duration

class date_duration
{
public:date_duration(long);date_duration(special_values);long day() const;bool is_special() const;bool operator==(const date duration &) const;...static date duration unit(); // 时长单位
};

date_time 库为 date_duration 定义了一个常用的typedef: days,这个新名字更好地说明了 date_duration的含义–它可以用来计量天数。

days dd1(10), dd2(-100), dd3(255);
assert( ddl > dd2 && ddl < dd3);
assert(ddl + dd2 == days(-90));
assert((dd1 + dd3).days() == 265);
assert(dd3/5 == days(51));

为了方便计算时间长度,date_time库还提供了months、years、weeks3 个时长类,分别用来表示月、年和星期,它们的含义与days 类似,但其行为不太相同。

weeks w(3);   //3个星期
assert(w.days() == 21);months m(5);
years y(2);months m2 = y + m;  //2年零5个月
assert(m2.number_of_months() == 29);
assert((y*2).number_of_years()== 4);
日期运算
date dl(2000, 1, 1), d2(2017, 11, 18);
cout<<d2 - d1<< endl;  // 6531天
assert(d1 + (d2 - d1) == d2);d1 += days(10);  //2000-1-11
assert(d1.day() == 11);
dl += months(2);  //2000-3-11
assert(dl.month() == 3 && d1.day() == 11);
d1 -= weeks(l);  //2000-3-04
assert(dl.day() == 4);d2 -= years(10);  //2007-11-18
assert(d2.year() == d1.year() + 7);

日期与特殊日期长度、特殊日期与日期长度进行运算的结果也是特殊日期:

date d1(2017,1,1);date d2 = d1 + days(pos_infin);
assert(d2.is_pos_infinity());d2 = d1 + days(not_a_date_time);
assert(d2.is_not_a_date());
d2 = date(neg_infin);
days dd = d1 - d2;
assert(dd.is_special() && !dd.is_negative());

如果日期是月末的最后一天,那么加减月或年会得到同样的月末时间
但当天数是月末的28或29时,如果加减月份到2月份,那么随后的运算就总是月末操作,原来的天数信息就会丢失

date d(2017, 3, 30);
d -= months(1);     //2017-2-28,变为月末,原30的日期信息丢失
d -= months(l);     //2017-1-31
d += months(2);     //2017-3-31
assert(d.day() == 31);   //与原来日期不相等

使用 days 则不会出现这样的问题

如果担心 weeks、months、years 这些时长类的使用进而扰乱了代码
可以 undef 宏 BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES
这将使date_time库不包含它们的定义头文件<boost/date time/gregorian/greg_duration types .hpp>

日期区间
  • date_time 库使用 date_period 来表示日期区间的概念
  • 它是时间轴上的一个左闭右开的区间,其端点是两个date对象
  • 日期区间的左边界必须小于右边界,否则date period将表示一个无效的日期区间。

date_period 的类摘要如下:

class date period
{
public:period(date, date);   period(date, days); date begin() const;date end() const;date last() const;date length() const;boo1 is_null()const;bool operator==(const period &) const;bool operator<(const period &) const;void shift(const days&);   //平移void expand(const days &); //扩展boo1 contains(const date &) const;  //区间运算boo1 contains(const period &)const;boo1 intersects(const period &)const;boo1 is_adjacent(const period &)const;bool is_before(const date &)const;boo1 is_after(const date &)const;period intersection(const period &)const;period merge(const period &)const;period span(const period &)const;
}

date_period可以指定区间的两个端点构造区间,也可以指定左端点再加上时长构造区间,通常后一种方法比较常用,这相当于在生活中从某天开始的一个周期。例如:

date_period dpl(date(2017, 1, 1), days(20));
date period dp2(date(2017, 1, 1), date(2016, 1, 1)); // 无效
date_period dpl(date(2017, 5, 1), days(-20)); // 无效
  • begin()和last()返回日期区间的两个端点,
  • end()返回last()后面第一天,与标准容器中end()含义相同,这是一个“逾尾位置”。
  • length()返回日期区间的长度,以天为单位。如果日期区间左大右小或长度为0,那么is_null()将返回true

date period 还支持输入输出操作符,默认的输入输出格式是一个[YYYY-mmm-DD/YYYY-mmm-DD]

date_period dpl(date(2017, 1, 1), days(20));
date_period dp2(date(2017, 2, 19), days(10));
cout << dpl;  //[2017-Jan-01/2017-Jan-20]
日期区间运算

shift()和expand()可以变动区间:shift()将日期区间平移n天而长度不变
expand()将日期区间向两端延伸n天,相当于区间长度增加2n天

date_period dp(date(2017, 1, 1), days(20));dp.shift(days(3));
assert(dp.begin().day() == 4);
assert(dp.length().days() == 20);dp.expand(days(3));
assert(dp.begin().day() == 1);
assert(dp.length().days() == 26);

date_period可以使用成员函数判断某个日期是否在区间内,还可以计算日期区间的交集。

  • is_before()/is_after(): 日期区间是否在日期前或后。
  • contains(): 日期区间是否包含另一个区间或日期。
  • intersects(): 两个日期区间是否存在交集。
  • intersection(): 返回两个区间的交集,如果无交集,则返回一个无效区间。
  • is_adjacent(): 两个日期区间是否相邻。
date_period dp(date(2010,1,1),days(20)); //1-1至1-20assert(dp.is_after(date(2009, 12, 1)));
assert(dp.is_before(date(2010, 2, 1)));
assert(dp.contains(date(2010, 1, 10)));date_period dp2(date(2010, 1, 5), days(10)); //1-5至1-15
assert(dp.contains(dp2));assert(dp.intersects(dp2));
assert(dp.intersection(dp2) == dp2);date_period dp3(date(2010, 1, 21), days(5)); //1-21至1-26
assert(!dp3.intersects(dp2));
assert(dp3.intersection(dp2).is_null());assert(dp.is adjacent(dp3));
assert(!dp.intersects(dp3));
  • merge(): 返回两个日期区间的并集,如果日期区间无交集或不相邻,则返回无效区间。
  • span(): 合并两个日期区间及两者间的间隔,相当于广义的merge()。
date_period dpl(date(2010, 1, 1), days(20));
date_period dp2(date(2010, 1, 5), days(10));
date_period dp3(date(2010, 2, 1), days(5));
date_period dp4(date(2010, 1, 15), days(10));assert(dpl.contains(dp2) && dpl.merge(dp2) == dpl);
assert(!dpl.intersects(dp3) && dpl.merge(dp3).is_null());
assert(dp1.intersects(dp2) && dp1.merge(dp4).end() == dp4.end());
assert( dpl.span(dp3).end() == dp3.end());
日期迭代器

日期迷代器的用法基本类似,都需要在构造时传入一个起始日期和增减步长(可以是天、两周或N个月等,默认是1个单位)

date d(2007, 9, 28);
day_iterator d_iter(d);  //增减步长默认为1天assert(d_iter == d);
++ d_iter;   //递增1天
assert(d_iter == date(2007, 9, 28));year_iterator y_iter(*d_iter, 10);  //增减步长为10年
assert(y_iter == d + days(l));
++y_iter;                           //递增10年
assert(y_iter->year() == 2017);

day_iterator、week iterator并不符合标准迭代器的定义,如果没有aifferenceype、pointer、reference, 等内部类型的定义,就不能使用std::advance()或 operator+=来前进或后退。

day_iterator iter(day_clock::local_day());  //声明一个日期迭代器
++iter;                                     //使用operator++,正确iter += 5;                // 错误,编译失败   
std::advance(iter,5);     // 错误,编译失败                                       
其他功能

成员函数is_leap_year()可以判断年份是否是闰年
end_of_month_day()可以给定年份和月份,并返回该月的最后一天

typedef gregorian_calendar gre_cal;cout << "Y2017 is "<<(gre_cal::is_leap_year(2017)? "" : "not")<< " a leap year."<< endl;assert(gre_cal::end_of_month_day(2017, 2) == 28);
综合运用

计算信用卡的免息期
使用信用卡的当天称为消费日,信用卡每月有一个记账日,在记账日之后有一个固定的免息还款期限,通常为20天,因此每笔信用卡交易的免息期就是消费日到下一个记账日的时间再加上还款期限,最长可以达到50天。

class credit_card
{
public:credit card(const char*bname,int no) : bank name(bname),bill day no(no){}string bank_name;              //银行名int bill_day_no;               //记账日int calc_free_days(date consume_day = day_clock::local_day()) const{date bill_day(consume_day.year(), consume day.month(), bill_day_no); //得到记账日if(consume_day > bill_day)bill_day += months(l);  //如果过了记账日,则是下个月的记账日return (bill_day - consume_day).days() + 20;}// 为了支持比较操作,我们还需要为creditcard增加小于比较操作符重载friend bool operator < (const credit_card& l, const credit_card& r){return (l.calc_free days() < r.calc free days());//比较免息期}
};credit_card a("A bank", 25);
credit_card b("B bank", 12);credit_card tmp = std::max(a, b);

http://www.ppmy.cn/news/1528977.html

相关文章

2024年9月16日--9月22日,(工作日源码抄写+周末ue5肉鸽独立游戏)

继续进行&#xff0c;按照周一到周五每天晚上在公司抄3小时源码gpu精粹催眠&#xff0c;周末独立游戏的方式&#xff0c;也就是说&#xff0c;要把独立游戏在周末做下去较长的一段时间&#xff0c;看看这条路能不能走通。 具体执行情况&#xff1a; 周一&#xff1a; 15&#…

SQL优化之深度分页优化

深度分页是指在分页查询场景下&#xff0c;当数量很大时&#xff0c;随着页数的增大&#xff0c;查询会变得越慢&#xff0c;数据库在梳理分页查询时需要跳过大量的数据&#xff0c;降低查询效率。 //查询第 1 到第 20 条商品 select * from products limit 20 offset 0; sele…

Python 二级考试

易错点 电脑基础知识 定义学生关系模式如下&#xff1a;Student &#xff08;S#&#xff0c; Sn&#xff0c; Ssex&#xff0c;class&#xff0c;monitorS#&#xff09;&#xff08;其属性分别为学号、学生名、性别、班级和班长学号&#xff09; 在关系模式中&#xff0c;如果…

Spring Boot-定时任务问题

Spring Boot 定时任务问题及其解决方案 1. 引言 在企业级应用中&#xff0c;定时任务是一项常见需求&#xff0c;通常用于自动化执行某些操作&#xff0c;如数据备份、日志清理、系统监控等。Spring Boot 提供了简洁易用的定时任务机制&#xff0c;允许开发者通过简单的配置来…

Python计算机视觉第十章-OpenCV

目录 10.1 OpenCV的Python接口 10.2 OpenCV基础知识 10.2.1 读取和写入图像 10.2.2 颜色空间 10.2.3 显示图像及结果 10.3 处理视频 10.3.1 视频输入 10.3.2 将视频读取到NumPy数组中 10.4 跟踪 10.4.1 光流 10.4.2 Lucas-Kanade算法 10.1 OpenCV的Python接口 O…

【算法业务】互联网风控业务中的拒绝推断场景算法应用分享(涉及半监督算法、异常检测、变分自编码、样本权重自适应调整、迁移学习等)

1. 业务目标和任务描述 该项目是很早期的一个工作&#xff0c;属于互联网信贷风控场景&#xff0c;研究并应用信贷中的拒绝推断任务&#xff0c;处理方式也许对于目前的一些业务还有参考意义&#xff0c;因此这里做下分享。拒绝推断是指在信贷业务中&#xff0c;利用已知的接受…

Vue2学习笔记(02条件渲染 、监视数据的原理)

1、v-if和v-show的区别 2、Vue监视数据的原理

SystemVerilog中的Semaphores

SystemVerilog中Semaphore&#xff08;旗语&#xff09;是一个多个进程之间同步的机制之一&#xff0c;这里需要同步的原因是这多个进程共享某些资源。 举一个场景&#xff1a;SoC中的,CPU和DMA都希望去访问相同地址的内存空间。实际的情况可能是CPU的访问覆盖DMA的访问&#x…