Boost库学习随记二 date_time、time_duration、date_facet、time_facet、timer库示例等:

//"Boost_data_Timer.h"头文件

#ifndef BOOST_TEST 
#define BOOST_DATE_TIME_SOURCE
#include <libs/date_time/src/gregorian/greg_names.hpp>
#include <libs/date_time/src/gregorian/date_generators.cpp>
#include <libs/date_time/src/gregorian/greg_month.cpp>
#include <libs/date_time/src/gregorian/greg_weekday.cpp>
#include <libs/date_time/src/gregorian/gregorian_types.cpp>

//#include "boost/date_time/gregorian/conversion.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"
//date_time库的时间功能位于名字空间boost::posix_time,为了使用时间组件,需要
//包含头文件<boost/date_time/posix_time/posix_time.hpp>即
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;


#endif // !BOOST_TEST 


//"Boost_data_Timer.cpp"

#include <iostream>
#include <cassert>
//#include <Windows.h>
//#include <windef.h>
#include "Boost_data_Timer.h"
using namespace boost;
using namespace std;



//使用date_time日期功能需要包含gregorian.hpp,并声明命名空间。
using namespace boost::gregorian; 

//日期处理测试示例
bool test_date_time()
{
	//date赋值的几种方式
	
		date d1;
		date d2(2010, 1, 1);
		date d3(2000, Jan, 1);
		date d4(d2);
	


	//从字符串产生赋值
	{
	date dd1 = from_string("1999-12-31");
	date dd2 = from_string("2005/1/1");
	date dd3 = from_undelimited_string("20000101");
	//枚举类型特殊时间,超出范围值会报异常。
	date ddd1(neg_infin);  //负无限日期
	date ddd2(pos_infin);  //正无限日期
	date ddd3(not_a_date_time);	//无效日期
	date ddd4(max_date_time);//最大可能日期9999-12031 :)万年虫有没有?
	date ddd5(min_date_time);//最小可能日期1400-01-01

	assert(d1 == date(not_a_date_time));
	assert(d2 == d4);
	assert(d3 < d4);

	}
	
	//auto类型转换时的测试
	if (d2.is_infinity()) //是否为一个无限日期
	{
		auto y = d2.year();
		auto m = d2.month();
		auto d = d2.day();
		cout << y << endl;
		cout << m << endl;
		cout << d << endl;
		cout << d2.year() << endl;
	}
	
	date::ymd_type ymd = d2.year_month_day();
	if (ymd.day)
	{
		auto y = ymd.year;
		auto m = ymd.month;
		auto d = ymd.day;
		cout << y << endl;
		cout << m << endl;
		cout << d << endl;
		//测试auto类型转换
		int a = y;
		cout << a << endl;
		//直接输出ymd
		cout << ymd.year << ymd.month << ymd.day << endl;
	}

	{
		//day_of_week星期数
		date dd2(2010, 01, 01), dd3(2011, 12, 12);
		auto a = dd2.day_of_week();
		cout << "dd2.day_of_week: " << dd2.day_of_week() << endl;
		//day_of_year当年的第几天
		cout << "dd2.day_of_year:" << dd2.day_of_year() << endl;
		//end_of_month返回当月最后一天date对象
		auto b = dd2.end_of_month();
		cout << b.year() << b.month() << b.day() << endl;
		cout << "dd2.end_of_month:" << b.day() << endl;

		//week_number 返回date所在的周是当年的第几周范围0-53
		cout << "week_number: " << dd3.week_number() << endl;
	}

	//is_xxxx相关函数测试
	{
		//is_infinity()			是否是一个无限日期
		//is_neg_infinity()     是否是一个负无限日期
		//is_pos_infinity()     是否是一个正无限日期
		//is_not_a_date()       是否是一个无效日期
		//is_special()          是否是任意一个特殊日期
		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(2010, 10, 1).is_special());
	}

	//date输出相关示例
	{
		date d(2008, 11, 20);
		//YYYY-MMM-DD
		cout << to_simple_string(d) << endl;
		//YYYYMMDD
		cout << to_iso_string(d) << endl;
		//YYYY-MM-DD
		cout << to_iso_extended_string(d) << endl;
		//直接出输d
		cout << d << endl;
	}

	//date与tm的相互转换
	{
		date d(2010, 2, 1);
		//to_tm需要引入"  #include "boost/date_time/gregorian/gregorian.hpp"
		//date转tm
		tm t = to_tm(d);
		assert(t.tm_hour == 0 && t.tm_min == 0);
		assert(t.tm_year == 110 && t.tm_mday == 1);
		//tm转date
		date d2 = date_from_tm(t);
		assert(d == d2);
	}

	//days(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));
	}
	//months,years,weeks时长类
	{
		//三个星期
		weeks w(3);
		assert(w.days() == 21);
		//5个月
		months m(5);
		//2年
		years y(2);
		//加法运算m2=2年零5个月
		months m2 = y + m;
		assert(m2.number_of_months() == 29);
		assert((y * 2).number_of_years() == 4);
		cout << m2.number_of_months() << endl;
		cout << y.number_of_years() << endl;
		cout << w << endl;
	}

	//计算2000年1月1日到2008年8月8日的天数等。
	{
		date d1(2000, 1, 1), d2(2008, 8, 8);
		cout << d2 - d1 << endl;       //3142天
		assert(d1 + (d2 - d1) == d2);

		d1 += days(10);               //2000-1-11
		assert(d1.day() == 11);
		d1 += months(2);              //2000-3-11
		assert(d1.month() == 3 && d1.day() == 11);
		d1 -= weeks(1);               //2000-3-4
		assert(d1.day() == 4);
		assert(d1.year() == 2000);
		cout << d1 << endl;


		d2 -= years(7);              //2001-8-8
		assert(d2.year() == d1.year() + 1);
	}

//特殊日期的运算
	{
		date d1(2010, 1, 1);
		date d2(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());
	}

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

	// 日期区间date_period
	{
		date_period dp(date(2010, 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输出形式
		date_period dp1(date(2010, 1, 1), days(20));
		date_period dp2(date(2010, 2, 19), days(10));
		cout << dp1 << endl;
		cout << dp2 << endl; 
		assert(dp1 < dp2);
	}
	//date_period日期区间的运算
	{
		date_period dp(date(2010, 1, 1), days(20));

		dp.shift(days(3));
		assert(dp.begin().day() == 4);
		assert(dp.length().days() == 20);
		cout << dp << endl;
		dp.expand(days(3));
		assert(dp.begin().day() == 1);
		assert(dp.length().days() == 26);
		cout << dp << endl;
	}
	//date_period成员函数判断某个日期是否在区间内,或者计算日期区间的交集
	{
		//is_before()、is_after(); 日期区间是否在日期前或后;
		//contains() ;日期区间是否包含另一个区间或者日期;
		//intersects();两个日期区间是否存在交集;
		//intersection() ;返回两个区间的交集,如果无交集返回一个无效区间;
		//is_adjacent();两个日期区间是否相邻;
		date_period dp(date(2010, 1, 1), days(20));  //1-1至1-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)); //1-21至1-26
		assert(!dp3.intersects(dp2));
		assert(dp3.intersection(dp2).is_null());

		assert(dp.is_adjacent(dp3));
		assert(!dp.intersects(dp3));

	}

	//date_period 提供了两种并集操作
	{
		//merge() 返回两个区间的并集,如果区间无交集或者不相邻则返回无效区
		//span() 合并两日期区间及两者间的间隔,相当于广义的merge().
		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());
	}

	//date_time库的迭代器
	{
		//主要包括date_iterator,week_iterator,month_iterator,year_iterator,年,周,月,天,
		//重载++,-- 只提供前置重载操作。
		date d(2006, 11, 26);
		day_iterator d_iter(d);

		assert(d_iter == d);
		++d_iter;                         //递增1天
		assert(d_iter == date(2006, 11, 27));

		year_iterator y_iter(*d_iter, 3);      //增减步长为3年
		assert(y_iter == d + days(1));
		++y_iter;                             //递增3年
		assert(y_iter->year() == 2009);
	}

	//is_leap_year()判断年份是否是闰年,end_of_month_day() 给定年份和月份,返回该月的最后一天。
	{
		typedef gregorian_calendar gre_cal;
		cout << "y2010 is"
			<< (gre_cal::is_leap_year(2010) ? "" : "not")
			<< "a leap year." << endl;
		assert(gre_cal::end_of_month_day(2010, 2) == 28);
	}
	return false;
}

//实现一个打印月历的功能,指定一个日期,可以得到该月的起始和结束日期。
bool show_date_time()
{
	date d(2008, 11, 20);  //实际远行时日期可以从CIN获得
	date d_start(d.year(), d.month(), 1); //当月第一天
	date d_end = d.end_of_month();    //当月最后一天

	//构造日期迭代器;d_iter!=d_end;循环结束条件
	for (day_iterator d_iter(d_start); d_iter != d_end; ++d_iter) 
	{
		cout << *d_iter << " " << d_iter->day_of_week() << endl;
	}
	return false;
}


//下面的程序计算一个人十八岁的生日是星期几,当月有几个星期天,当年有多少天。
bool count_age()
{
	date d(2008, 11, 16);  //声明日期对象

	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(), d18years.month(), 1));
		d_iter != d18years.end_of_month(); ++d_iter)
	{
		if (d_iter->day_of_week() == Sunday)  // 是星期天则计数增加
		{
			++count;
		}
	}
	cout << "total " << count << " Sundays." << endl;

	count = 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;
	//计算当年的天数没有必要累加每月的天数,可以简单地只判断该年是否是闰年就可以了。如下所示:
	typedef gregorian_calendar gre_cal;
	cout<<(gre_cal::is_leap_year(d18years.year())?365:366);
	cout << endl;
	return false;
}

//信用卡计算示例:
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; //计算免息期
	}
	
	//为了支持比较操作,还需要为credit_card 增加小于比较操作符重载
	friend bool operator<(const credit_card& l, const credit_card& r)
	{
		//比较免息期
		return l.calc_free_days() < r.calc_free_days();
	}

};

//时间测试示例
//如果在头文件posix_time.hpp之前定义宏BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG,哪么它可以精确到纳秒级。
bool test_time_duration()
{
	//time_duration也有几个子类,可以度量不同的时间分辨率。分别是:
	//hours,minutes,seconds,millisec/milliseconds,microsec/microseconds,nanosec/nanoseconds.
	//操作时间长度
	
	{//创建一个1小时10分钟30秒1毫秒(1000微秒)的时间长度
		time_duration td(1, 10, 30, 1000);
		//2小时01分06.001秒
		time_duration tdd(1, 60, 60, 1000 * 1000 * 6 + 1000);
	}

	{//time_duration的子类可以更直观地创建时间长度
	hours h(1);   //1小时
	minutes m(1); //10分钟
	seconds s(30);//30秒钟
	millisec ms(1); //1毫秒

	time_duration td = h + m + s + ms;  //可以赋值给time_duration
	time_duration td2 = hours(2) + seconds(10);  //可以直接赋值
    }

	{//使用工厂函数duration_from_string(),time_duration可以从一个字符串创建字符串中的时间需要冒号隔开
		time_duration td = duration_from_string("1:10:30:001");
	}

	{	//可以用hours(),minutes(),seconds() 成员函数访问
		//total_seconds(),total_milliseconds(),total_microseconds()分别返回时间长度的总秒,毫,微数。
		//fractional_seconds()以long返回微秒数
		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);
		assert(td.total_milliseconds() == td.total_seconds() * 1000 + 1);
		assert(td.fractional_seconds() == 1000);
	}

	{
		//time_duration 可以取负值,专门有一个成员函数is_negative() 来判断它的正负号。
		//成员函数invert_sign()可以将时间长度改变符号后生成一个新的时间长度。
		hours h(-10);
		assert(h.is_negative());
		time_duration h2 = h.invert_sign();
		assert(!h2.is_negative() && h2.hours() == 10);
	}

	{
		//time_druation也可以赋值为特殊时间值,包括not_a_date_time、pos_infin 等等,同样也有类似的
		//is_xxx()函数用于检测它是否为特殊时间,用法与date、date_duration类似。
		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());

	}

	{
		//time_duation支持完整的四则运算。
		time_duration td1 = hours(1);
		time_duration td2 = hours(2) + minutes(30);
		assert(td1 < td2);
		assert((td1 + td2).hours() == 3);
		assert(td1 * 5 == td2 * 2);
		assert((td1 / 2).minutes() == td2.minutes());

	}

	{
		//time_duation转换字符串
		time_duration td(1, 10, 30, 1000);
		cout << to_simple_string(td) << endl;
		cout << to_iso_string(td) << endl;

		//输出结果:01:10:30.001000   011030.001000
		//另外timer_duration也可以转换到 tm结构to_tm()函数
	}

	//时间点
	{
		{
			//ptime 是在date_time库处理时间的核心类
			//using namespace boost::gregorian;   posix_time名字空间不包含gregorian名字空间,因此需要加上对它的引用
			ptime p(date(2010, 3, 5), hours(1)); //2010年3月5日凌晨1时
		}

		{
		//ptime可以从字符串构造,使用工厂函数time_from_string()和from_iso_string()前者使用分隔符分隔日期时间成分,
		//后者则是连结续的数字,日期与时间用字母T隔开
		ptime p1 = time_from_string("2010-3-5 01:00:00");
		ptime p2 = from_iso_string("20100305T010000");
		}

		{
			//date_time库为ptime也提供了时钟类,可以从时钟产生当前时间,有两个类second_clock和microsec_clock分别提供秒级和微秒级的分辨率,
			//它们的接口是相同的,local_time()获得本地当前时间,universal_time()获得UTC当前时间。
			ptime p1 = second_clock::local_time();  //秒精度
			ptime p2 = microsec_clock::universal_time(); //微秒精度
			cout << p1 << endl << p2;
		}

		{
			//ptime构造为特殊时间值,如无效时间,无限时间,也同样有is_xxx()来检验特殊值。
			ptime p1(not_a_date_time);     //无效时间
			assert(p1.is_not_a_date_time());
			ptime p2(pos_infin);           //正无限时间
			assert(p2.is_special() && p2.is_pos_infinity());
		}

		{
			//操作时间点对象
			//ptime使用date()和time_of_day() 两个成员函数获得时间点的日期和时间长度,然后就可以分别处理。
			//2010年3月20日中午 12:30
			ptime p(date(2010, 3, 20), hours(12) + minutes(30));
			date d = p.date();
			time_duration td = p.time_of_day();
			assert(d.month() == 3 && d.day() == 20);
			assert(td.total_seconds() == 12 * 3600 + 30 * 60);

			//ptime支持比较操作与加减运算,运算规则与日期类似
			ptime p1(date(2010, 3, 20), hours(12) + minutes(30));
			ptime p2 = p1 + hours(3);    //2010年3月20日15:30
			assert(p1 < p2);
			assert(p2 - p1 == hours(3));
			p2 += months(1);
			assert(p2.date().month() == 4);
		}

		{
			//ptime提供了三个自由函数转换为字符串,分别是 
			//to_simple_string(ptime): 转换为YYYY-MMM-DD HH:MM:SS.FFFFFFFFF格式
			//to_iso_string(ptime):  转换为YYYYMMDDTHHMMSS,FFFFFFFFF格式
			//to_iso_extended_string(ptime):转换为YYYY-MM-DDTHH:MM:SS,FFFFFFFFF格式
			//FFFFFFF是秒的小数部分,如果为0则不显示,T是日期与时间的分融符。

			ptime p(date(2010, 2, 14), hours(20));
			cout << to_simple_string(p) << endl;
			cout << to_iso_string(p) << endl;
			cout << to_iso_extended_string(p) << endl;
		}

		{
			//与tm、time_t等结构的转换
			//使用自由函数to_tm(),ptime可以单向转换到tm结构,转换规则是date 和 time_duration的组合
			ptime p(date(2010, 2, 14), hours(20));
			tm t = to_tm(p);
			assert(t.tm_year == 110 && t.tm_hour == 20);
		}

		{
			//从time_t和FILETIME结构创建出ptime对象,这种转换也是单向的,不存在逆向的转换。
			ptime p = from_time_t(std::time(0));
			assert(p.date() == day_clock::local_day());

			/*
		FILETIME ft;
		ft.dwHighDateTime = 29715317;
		ft.dwLowDateTime = 3865122988UL;
		p = from_ftime<ptime>(ft);
		*/
		}

		{
			//time_period一些用法的代码
			ptime p(date(2010, 1, 1), hours(12));    //2010年元旦中午
			time_period tp1(p, hours(8));            //一个8小时的区间
			time_period tp2(p + hours(8), hours(1)); //1小时的区间
			assert(tp1.end() == tp2.begin() && tp1.is_adjacent(tp2));
			assert(!tp1.intersects(tp2));   //两个区间相邻但不相交

			tp1.shift(hours(1));   //tp1平移1小时
			assert(tp1.is_after(p));   //两个区间现在相交
			assert(tp1.intersects(tp2));

			tp2.expand(hours(10));       //tp2向两端扩展10小时
			assert(tp2.contains(p) && tp2.contains(tp1));
		}

		{
			//时间迭代器,只有一个time_iterator
			//使用时间迭代器以10分钟为步长打印时间
			ptime p(date(2010, 2, 27), hours(10));
			for (time_iterator t_iter(p, minutes(10));
				t_iter < p + hours(1); ++t_iter)
			{
				cout << *t_iter << endl;
			}

		}

		{
			//date_facet、time_facet格工化对象,定制日期时间。
			date d(2010, 3, 6);
			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;
		}


	}

	return false;
}


int main()
{
	//date_time测试示例
	test_date_time();
	//显示打印月历
	show_date_time();

	//计算一个人十八岁的生日是星期几,当月有几个星期天,当年有多少天。
	count_age();

	//信用卡免息期
	credit_card a("A bank",25); //A银行记账日是每月的25号
	credit_card b("B bank", 12); //B银行记账日是每月的12号

	credit_card tmp = std::max(a, b);
	cout << "You should use " << tmp.bank_name
		<< ", free days = " << tmp.calc_free_days() << endl;

	//时间测试示例函数调用
	test_time_duration();


	system("pause");
	return 0;
}



你可能感兴趣的:(库,boost)