本文章所有内容源于《BOOST程序库完全开发指南:深入C++“准”标准库(第3版)》第二章
1. timer
1.1 elapsed_max
头文件:
#include <boost/timer.hpp>
using namespace boost;
功能:度量最大时间
1.2 elapsed_min
头文件:
#include <boost/timer.hpp>
using namespace boost;
功能:度量最小时间
1.3 elapsed
头文件:
#include <boost/timer.hpp>
using namespace boost;
功能:度量从程序运行到现在的时间
#include <boost/timer.hpp>
#include <iostream>
using namespace boost;
using namespace std;
int main()
{
timer t;
cout << "可度量最大时间,以小时为单位"<< t.elapsed_max()/3600 << "h"<<endl;
cout << "可度量最小时间,以秒为单位" << t.elapsed_min() << "s" << endl;
cout << "输出已经流逝的时间" << t.elapsed()<< endl;;
}
2. progress_timer
头文件:
#include <boost/progress.hpp>
using namespace boost;
功能:显示程序运行时间
3. progress_display
头文件:
#include <boost/progress.hpp>
using namespace boost;
using namespace boost::gregorian;
功能:显示运行进度条百分比
4. date_time
4.1 gregorian日期
头文件:
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
using namespace boost;
#define DATE_TIME_NO_DEFAULT_CONSTRUCTOR
功能:处理日期
using namespace std;
#include <iostream>
// #define DATE_TIME_NO_DEFAULT_CONSTRUCTOR
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
//
void case1()
{
date d1;
date d2(2010,1,1);
date d3(2000, Jan , 1);
date d4(d2);
assert(d1 == date(not_a_date_time));
assert(d2 == d4);
assert(d3 < d4);
}
//
void case2()
{
date d1 = from_string("1999-12-31");
date d2 ( from_string("2015/1/1") );
date d3 = from_undelimited_string("20011118") ;
cout << d1 << d2 << d3 << endl;
cout << day_clock::local_day() << endl; //当地时间
cout << day_clock::universal_day() << endl; //世界日
}
//
void case3()
{
date d1(neg_infin); //负无限日期
date d2(pos_infin);//正无限日期
date d3(not_a_date_time);//无效日期
date d4(max_date_time);//最大可能日期
date d5(min_date_time);//最小可能日期
cout << d1<<" " << d2<<" " << d3<<" " << d4<<" " << d5<<" " << endl;
try
{
//下面的例子都超过了要求
//date d1(1399,12,1);
//date d2(10000,1,1);
date d3(2017,2,29);
}
catch(std::exception& e)
{
cout << e.what() << endl;
}
}
//
void case4()
{
date d(2017,6,1);
assert(d.year() == 2017);
assert(d.month() == 6);
assert(d.day() == 1);
date::ymd_type ymd = d.year_month_day(); //ymd可以直接访问年月日
assert(ymd.year == 2017);
assert(ymd.month == 6);
assert(ymd.day == 1);
cout << d.day_of_week() << endl; //返回date的星期数
cout << d.day_of_year() << endl; //返回当年的第几天
assert(d.end_of_month() == date(2017,6,30));
cout << date(2015,1,10).week_number() << endl; //返回date所在的周是当年的第几周
cout << date(2016,1,10).week_number() << endl;
cout << date(2017,1,10).week_number() << endl;
assert(date(pos_infin).is_infinity() ); //是否是一个无限日期
assert(date(pos_infin).is_pos_infinity() ); //是否是一个负无限日期
assert(date(neg_infin).is_neg_infinity() ); //是否是一个正无限日期
assert(date(not_a_date_time).is_not_a_date() ); //是否是一个无效日期
assert(date(not_a_date_time).is_special() ); //是否是任意一个特殊日期
assert(!date(2017,5,31).is_special() );
}
// //
void case5()
{
date d(2017,1,23);
cout << to_simple_string(d) << endl; //转换格式为YYY-MMM-DD格式的字符串
cout << to_iso_string(d) << endl; //转换为YYYYMMDD格式的数字字符串
cout << to_iso_extended_string(d) << endl; //转换格式为YYYY-MM-DD格式的数字字符串
cout << d << endl;
//cout << "input date:";
//cin >>d;
//cout << d;
}
//
void case6()
{
//tm和dtm相互转换
date d(2017,5,20);
tm t = to_tm(d); //date转换到tm,tm的时分秒成员
assert(t.tm_hour == 0 && t.tm_min == 0);
assert(t.tm_year == 117 && t.tm_mday == 20);
date d2 = date_from_tm(t); //tm转换到date
assert(d == d2);
}
//
void case7()
{
//时间长度date_duration,返回时长的天数
days dd1(10), dd2(-100), dd3(255);
assert( dd1 > dd2 && dd1 < dd3);
assert( dd1 + dd2 == days(-90));
assert((dd1 + dd3).days() == 265);
assert( dd3 / 5 == days(51));
weeks w(3); //三个星期
assert(w.days() == 21);
months m(5); //无个月
years y(2); //两年
months m2 = y + m; //两年零五个月
assert(m2.number_of_months() == 29);
assert((y * 2).number_of_years() == 4);
}
//
void case8()
{
date d1(2000,1,1),d2(2014,11,18);
cout << d2 - d1 << endl; //5435天
assert(d1 + (d2 - d1) == d2);
d1 += days(10); //2000-1-11
assert(d1.day() == 11);
d1 += months(2);
assert(d1.month() == 3 && d1.day() == 11); //2000-3-11
d1 -= weeks(1);//2000-3-04
assert(d1.day() == 4);
d2 -= years(10); //2004-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());
}
{
//由于经常会被months years weeks扰乱,因此建议带上宏#define DATE_TIME_NO_DEFAULT_CONSTRUCTOR
date d(2014,3,30); //原20的日期丢失
d -= months(1); //201401031
d -= months(1);//2014331
d += months(2);//与原来日期不相等
assert(d.day() == 31);
}
}
//
void case9()
{
//可以从左端开始构造,也可以用区间的两端来构造
date_period dp1(date(2017,1,1), days(20));//从1.1向后平移20天
// date_period dp2(date(2017,1,1), date(2016,1,1)); //无效
// date_period dp3(date(2017,3,1), days(-20)); //无效
date_period dp(date(2017,1,1), days(20));
assert(!dp.is_null());
assert(dp.begin().day() == 1);
assert(dp.last().day() == 20);
assert(dp.end().day() == 21);
assert(dp.length().days() == 20);
{
date_period dp1(date(2017,1,1), days(20));
date_period dp2(date(2017,2,19), days(10));
cout << dp1; //[2010-Jan-01/2010-Jan-20]
assert(dp1 < dp2);
}
}
//
int main()
{
case1();
case2();
case3();
case4();
case5();
case6();
case7();
case8();
case9();
}
using namespace std;
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
//
void case1()
{
date_period dp(date(2017,1,1), days(20));
dp.shift(days(3)); //将日期区间平移n天而长度不变
assert(dp.begin().day() == 4);
assert(dp.length().days() == 20);
dp.expand(days(3)); //将日期区间向两端延伸n天,相当于区间长度加2n天
assert(dp.begin().day() == 1);
assert(dp.length().days() == 26);
}
//
void case2()
{
date_period dp(date(2010,1,1), days(20));
assert(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));
assert(dp.contains(dp2));///日期区间是否包含另一个区间或者日期
assert(dp.intersects(dp2)); //两个日期是否有交际
assert(dp.intersection(dp2) == dp2); //返回两个区间的交际,如果无交际返回一个无效区间
date_period dp3(date(2010,1,21), days(5));
assert(!dp3.intersects(dp2));
assert(dp3.intersection(dp2).is_null());
assert(dp.is_adjacent(dp3)); //两个日期区间是否相邻
assert(!dp.intersects(dp3));
}
//
void case3()
{
date_period dp1(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( dp1.contains(dp2) && dp1.merge(dp2) == dp1);
assert(!dp1.intersects(dp3) && dp1.merge(dp3).is_null());
assert( dp1.intersects(dp2) && dp1.merge(dp4).end() == dp4.end());
assert( dp1.span(dp3).end() == dp3.end());
}
//
void case4()
{
//日期迭代器
date d(2007,9,28);
day_iterator d_iter(d); //增减补偿默认为1天
cout << d << endl;
assert(d_iter == d); //递增1天
++d_iter;
assert(d_iter == date(2007,9,29));
cout << *d_iter << endl;
year_iterator y_iter(*d_iter, 10); //递增步长默认为10年
assert(y_iter == d + days(1));
++y_iter; //递增10年
assert(y_iter->year() == 2017);
cout << *y_iter <<endl;
day_iterator iter(day_clock::local_day()); //声明一个日期迭代器
++iter;
cout << *iter << endl;
//iter += 5;
//std::advance(iter, 5);
}
//
//定义gregorian_calendar,用于判断是否是润年或者最后一个月
void case5()
{
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);
}
//
//日期迭代器,使用for循环遍历
void case6()
{
date d(2017,1,23);
date d_start(d.year(), d.month(), 1);
date d_end = d.end_of_month();
for(day_iterator d_iter(d_start);
d_iter <= d_end; ++d_iter)
{
cout << *d_iter << " " <<
d_iter->day_of_week()<< endl;
}
}
//
//简单日期计算
void case7()
{
date d(2017,1,23); //声明日期对象
date d18years = d + years(18); //加上18年
cout << d18years << " is "
<< d18years.day_of_week()<< endl;
int count = 0; //星期天的计数器
for (day_iterator d_iter(date(d18years.year(),1,1));
d_iter <= d18years.end_of_month(); ++d_iter)
{
if (d_iter->day_of_week() == Sunday) //如果是星期天就计数增加
{
++count;
}
}
cout << "total " << count << " Sundays." << endl;
count = 0; //计数器归0
for (month_iterator m_iter(date(d18years.year(),1,1));
m_iter < date(d18years.year() + 1 ,1, 1); ++m_iter)
{
count += m_iter->end_of_month().day(); //累加月份的天书
}
cout << "total " << count << " days of year." << endl;
}
//
//计算信用卡的免息期
class credit_card
{
public:
string bank_name; //银行名
int bill_day_no; //记账日
credit_card(const char* bname, int no):
bank_name(bname), bill_day_no(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(1); //如果过了则是下个月的记账日
}
return (bill_day - consume_day).days() + 20; //计算免息期
}
friend bool operator<(const credit_card& l, const credit_card& r)
{
return l.calc_free_days() < r.calc_free_days();
}
};
void case8()
{
credit_card a("A bank", 25);
credit_card b("B bank", 12);
credit_card tmp = std::max(a, b);
cout << "You should use " << tmp.bank_name
<< ", free days = " << tmp.calc_free_days() << endl;
}
//
int main()
{
case1();
case2();
case3();
case4();
case5();
case6();
case7();
case8();
}
4.2 posix_time时间
头文件:
#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
功能:处理时间
using namespace std;
//#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
//
void case1()
{
{
//时分秒可自动进位
time_duration td = duration_from_string("1:10:30:001");
cout << td << endl;
time_duration td1(1,10,30,1000);
time_duration td2(1,60,60,1000*1000* 6 + 1000);
}
hours h(1);
minutes m(10);
seconds s(30);
millisec ms(1);
time_duration td = h + m + s + ms;
time_duration td2 = hours(2) + seconds(10);
cout << td << td2 << endl;
}
//
void case2()
{
time_duration td(1,10,30,1000);
assert(td.hours() == 1 && td.minutes() == 10 && td.seconds() == 30);
assert(td.total_seconds() == 1*3600+ 10*60 + 30);
#ifndef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
assert(td.total_milliseconds() == td.total_seconds()*1000 + 1);
assert(td.fractional_seconds() == 1000);
#endif
hours h(-10); //可以取负
assert(h.is_negative());
time_duration h2 = h.invert_sign();
assert(!h2.is_negative() && h2.hours() == 10);
time_duration td1(not_a_date_time);
assert(td1.is_special() && td1.is_not_a_date_time());
time_duration td2(neg_infin);
assert(td2.is_negative() && td2.is_neg_infinity());
}
//
void case3()
{
time_duration td1 = hours(1);
time_duration td2 = hours(2) + minutes(30);
assert(td1 < td2);
assert((td1+td2).hours() == 3);
assert((td1-td2).is_negative());
assert(td1 * 5 == td2 * 2);
assert((td1/2).minutes() == td2.minutes());
time_duration td(1,10,30,1000);
cout << to_simple_string(td) << endl; //返回HH:MM:SS.FFFFFFFF
cout << to_iso_string(td) << endl; //返回KKMMSS,FFFFFFFFF
}
//
//正常的精确长度是微秒,加入宏以后变成纳秒
void case4()
{
#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
time_duration td(1,10,30,1000);
cout << td;
assert(td.total_milliseconds() ==
td.total_seconds()*1000);
assert(td.fractional_seconds() ==1000);
assert(time_duration::unit()*1000*1000*1000 == seconds(1));
assert(td.resolution() == boost::date_time::nano);
assert(td.num_fractional_digits() == 9);
#endif
}
//
//最基本的创建ptime的方式是在构造函数中,同时指定date和time_duration对象,令ptime等于一个日期加当天的时间偏移量
void case5()
{
ptime p(date(2017,7,7), hours(1));
ptime p1 = time_from_string("2017-7-7 01:00:00");
ptime p2 = from_iso_string("20170707T010000");
cout << p1 << endl << p2;
{
ptime p1 = second_clock::local_time();
ptime p2 = microsec_clock::universal_time();
cout << p1 << endl << p2;
}
}
//
void case6()
{
ptime p(date(2010,3,20), hours(12)+minutes(30));
date d = p.date(); //date获得时间点中日期的长度
time_duration td = p.time_of_day(); //time_of_day获得时间点中时间的长度
assert(d.month() == 3 && d.day() == 20);
assert(td.total_seconds() == 12*3600 + 30*60);
ptime p1(date(2010,3,20), hours(12)+minutes(30));
ptime p2 = p1 + hours(3);
assert(p1 < p2);
assert(p2 - p1 == hours(3));
p2 += months(1);
assert(p2.date().month() == 4);
cout << endl;
{
ptime p(date(2017,2,14), hours(20)); //2017年2月14日20点
cout << to_simple_string(p) << endl;
cout << to_iso_string(p) << endl;
cout << to_iso_extended_string(p) << endl;
}
}
//
//使用to_tm,ptime可以单向转换到tm结构,转换规则是date和time_duration组合
void case7()
{
ptime p(date(2017,5,20), hours(14));
tm t = to_tm(p);
assert(t.tm_year == 117 && t.tm_hour == 14);
assert(ptime_from_tm(t) == p);
ptime p2 = from_time_t(std::time(0));
assert(p2.date() == day_clock::local_day());
cout << to_time_t(p2) << endl;
}
//
//区间为两端或者一个端点+长度
void case8()
{
ptime p(date(2017,1,1),hours(12)) ;
time_period tp1(p, hours(8));
time_period tp2(p + hours(8), hours(1));
assert(tp1.end() == tp2.begin() && tp1.is_adjacent(tp2));
assert(!tp1.intersects(tp2));
tp1.shift(hours(1));
assert(tp1.is_after(p));
assert(tp1.intersects(tp2));
tp2.expand(hours(10));
assert(tp2.contains(p) && tp2.contains(tp1));
}
//
//时间迭代器,以10分钟为一个步长
void case9()
{
ptime p(date(2017,5,31),hours(10)) ;
for (time_iterator t_iter(p, minutes(10));
t_iter < p + hours(1); ++ t_iter)
{
cout << *t_iter << endl;
}
}
//
int main()
{
case1();
case2();
case3();
case4();
case5();
case6();
case7();
case8();
case9();
}
综合测试
using namespace std;
//#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
//运用ptime相关的所有类,给出综合的例子
//高精度计时器
//第一步:将ptimer实现为模板类basic_ptimer,通过定制时钟类,实现秒和微秒级计时器
template<typename Clock = microsec_clock>
class basic_ptimer
{
public:
basic_ptimer() //构造函数初始化其实时间
{ restart() ; };
void restart() //重新开始计时
{ _start_time = Clock::local_time(); }
void elapsed() const //度量流逝时间
{ cout << Clock::local_time() - _start_time; }
~basic_ptimer() //析构函数自动输出时间
{ elapsed(); }
private:
ptime _start_time;
};
typedef basic_ptimer<microsec_clock> ptimer;
typedef basic_ptimer<second_clock> stimer;
//第二步:计算工作时间,使用time_period类表示工作日的工作时间,根据当前时间给用户提示
class work_time
{
public:
typedef map<time_period, string> map_t;
private:
map_t map_ts;
void init()
{
ptime p (day_clock::local_day()); //获得现在的时间
map_ts[time_period(p, hours(9))] = "It's too early, just relax.\n";
p += hours(9); //到早上9点
map_ts[time_period(p, hours(3)+ minutes(30))] = "It's AM, please work hard.\n";
p += hours(3)+ minutes(30);
map_ts[time_period(p, hours(1))] = "It's lunch time, are you hungry?\n";
p += hours(1);
map_ts[time_period(p, hours(4)+minutes(30))] = "It's PM, ready to go home.\n";
p += hours(4)+ minutes(30); //到13:30
map_ts[time_period(p, hours(6))] = "Are you still working? you do need a rest.\n";
} //到下午5点
public:
work_time()
{ init(); }
//该函数遍历整个容器,判断时间点是否在某个区间内
void greeting( const ptime& t )
{
for(auto& x : map_ts)
{
if(x.first.contains(t)) //pair的first成员是时间段
{
cout << x.second <<endl;
break;
}
}
}
};
void test()
{
ptimer t;
work_time wt;
wt.greeting(second_clock::local_time());
}
int main()
{
test();
return 0;
}
4.3 local_time时区
头文件:
#include <boost/date_time/local_time/local_time.hpp>
using namespace boost::local_time;
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
功能:计算跨时区时间
using namespace std;
//#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
//
void case1()
{
date d(2014,11,3);
date_facet* dfacet = new date_facet("%Y年%m月%d日");
cout.imbue(locale(cout.getloc(), dfacet));
cout << d << endl;
time_facet *tfacet = new time_facet("%Y年%m月%d日%H点%M分%S%F秒");
cout.imbue(locale(cout.getloc(), tfacet));
cout << ptime(d , hours(21) + minutes(50) + millisec(100)) << endl;
}
//
days operator"" _D(unsigned long long n)
{
return days(n);
}
weeks operator"" _W(unsigned long long n)
{
return weeks(n);
}
date operator"" _YMD(const char* s, std::size_t )
{
return from_string(s);
}
void case2()
{
auto d = 100_D;
auto w = 1_W;
assert(d.days() == 100);
assert(w.days() == (7_D).days());
auto today = "2014/11/3"_YMD;
cout << today << endl;
}
//
/*飞机跨境飞行,计算落地时间*/
#include <boost/date_time/local_time/local_time.hpp>
using namespace boost::local_time;
void case3()
{
tz_database tz_db;
tz_db.load_from_file("./date_time_zonespec.csv");
//该数据库包括了世界上几乎所有国家和地区的时区信息
//time_zone_ptr,通过时区名就可以访问时区信息
time_zone_ptr shz = tz_db.time_zone_from_region("Asia/Shanghai");
time_zone_ptr sfz = tz_db.time_zone_from_region("America/Los_Angeles");
cout << shz->has_dst() << endl; //上海时区无夏令时
cout << shz->std_zone_name() << endl; //上海时区的名称是CST
local_date_time dt_bj(date(2014,3,6), //北京时间
hours(16), //下午16点
shz, //上海时间区
false); //无夏令时
cout << dt_bj << endl;
time_duration flight_time = hours(12); //飞机飞12小时
dt_bj += flight_time; //到达北京的时间
cout << dt_bj << endl;
local_date_time dt_sf = dt_bj.local_time_in(sfz);//旧金山当地时间
cout << dt_sf;
}
//
int main()
{
case1();
case2();
case3(); //重要
}
5. 总结
学习了Boost里面timer和date_time两个库(时间和日期),继承了clock的用法,读取系统时间和程序运行时间,通过时间迭代可以计算判断日期和时间是否在某个区间。时钟类可以进行时区转换,定制输出日期和时间的格式。