Boost库 对时间和日期的处理 date_timer库
4e48
10年前
/*Boost 对时间和日期的处理 提供了timer和data_time 库*/ //有关timer库提供了简易的度量时间和进度显示的功能可以用于性能测试等需要计时的任务 /* timer 的三个组件 计时器类timer progress_timer和进度指示类progress_display timer 可测量时间的流逝,提供毫秒级的计时精确度 #include<boost\timer.hpp> #include<iostream> using namespace boost; using namespace std; 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;//已经流逝的时间 }*/ /* 使用建议:不适合高精度高的计时,window下精度1/1000,linux 下为1/1000000 难以做到跨平台 */ /*--------------------progress_timer------------------- 继承自timer 会在析构时自动输出时间 需包含头文件<> 可以在构造函数指定I/O流那么在析构时会写到指定到I/O流 扩展计时精度: 使用模板技术仿造progress_timer 编写新类 new_progress_timer 实现任意精度的输出 同样继承自timer类 只是变成了模板类N指定精确度默认为2 #include<boost\progress.hpp> #include<boost\static_assert.hpp> template<int N=2> class new_progress_timer :public boost::timer { public: //构造函数初始化输出流m_os 在window平台下n>3无意义/ new_progress_timer(std::ostream& os = std::cout) :m_os(os) { BOOST_STATIC_ASSERT(N >= 0 && N <= 10); } ~new_progress_timer() { try{ //保存流的状态 std::istream::fmtflags old_flags = m_os.setf(std::istream::fixed, std::istream::floatfield); std::streamsize old_prec = m_os.precision(N); m_os << elapsed() << "s\n"<< std::endl; //恢复流的状态 m_os.flags(old_flags); m_os.precision(old_prec); } catch (...){}//析构函数绝对不能抛出异常 } private: std::ostream& m_os; }; template<> class new_progress_timer<2>:public boost::progress_timer//对n=2的模板的化 { }; int main() { //{ //boost::progress_timer t; //std::cout << t.elapsed() << std::endl; //do something; //} //模板的使用 new_progress_timer<10> t; //do someting; } */ //----------------------progress_display /* 可以在控制台上显示程序的执行很耗时那么她能够提供一个友好的用户界面 是一个独立类和其它两个组件类没关系 其构造函数接受一个long型参数expected_count用于进度显示的基数 另一个构造函数progress_display(unsigned long expected_count,std::ostream&os,const std::string&s1="\n", const std::string& s2="",const std::string & s3="");三个字符串参数定义显示三行首字符串 !!注意事项: 无法把进度的显示输出和程序的输出分离这是因为progress_display和所有C++程序一样都向标准输出(cout)输出字符如果使用progress_display的程序也有输出操作那进度条将 一片混乱一个可能但远非完美的方法就是每次显示进度是调用restart()重新显示进度然后用operator+=来指定当前进度 #include<boost\progress.hpp> #include<string> #include<fstream> #include<vector> using namespace std; int main() { vector<string>v(100,"a"); ofstream fs("G:\\test.txt"); boost::progress_display pd(v.size(),std::cout,"\n","","*");//后三个参数提供默认参数 vector<string>::iterator itpos; for (itpos = v.begin(); itpos != v.end(); ++itpos) { fs << *itpos << endl; ++pd; _sleep(100); } } */ //---------------------------------date_time库的概述 /*非常全面的日期时间库 date_time 库使用枚举special_values定义特殊的时间概念位于命名空间: pos_infin ---表示正无限 neg_infin------表示负无限 not_a_date_time-------无效时间 min_data_time------表示的最小日期1400-01-01 max_data_time--------最大日期9999-12-31 日期的处理: date是date_time库处理的核心类使用32位整数作为内部存储,可拷贝传值,比较操作,流输入输出 使用: date d1;///一个无效的日期对象 date d2(2010,1,1)数字构造日期 date d3(2000,Jan,1)//英文指定月份 date d4=from_string("1999-12-31") date d4(from_string(2005/1/1))//支持拷贝构造工程函数通过/或-分割 date d3=from_undelimted_string("20011112")//支持无分割符的纯字符串 day_lock是无级别时钟他是一个工程类调用他的静态成员函数local_day()或universal_day()会返回当天日期对象分别是本地时期和utc日期 date 的5个is_xxx()函数用于检测日期是否是个特殊日期 is_infinity()是否是个无限日期 is_neg_infinity()是否是个负无限日期 is_pos_infinity().......正无限日期 is_not_a_date......无效日期 is_special()......特殊日期 date很方便的转化成字符串提供三个自由函数 to_simple_string(date d)转换成yyy-mmm-dd mmm三字符英语月份 to_iso_string(date d) YYYMMDD to_iso_extended_string(date d)转换成yyy-mm-dd ----------------------与tm结构的转换: to_tm(date) date_from_tm:tm 转化为date -----------------------日期长度 日期长度是以天为单位的时长,是度量时间长度的一个标量 基本的日期长度类是date_duration 支持全序比较操作(== != > >=)也支持递增和递减操作也支持除法运算但是不能除date_duration类型 乘法取余取模则不支持 date_time 库为date_duration 定义了一个常用的typedef:day 说明了其含义一个天数的计量 为了方便计算时间长度 date_time 库还提供了months years weeks 等另外三个时长类 */ //---------------------日期运算 /* date主要是与时长概念配合运算 #define BOOST_DATE_TIME_SOURCE #include<boost\date_time\gregorian\gregorian.hpp> using namespace boost::gregorian; int main() { date d1(2000, 1, 1); date d2(2008, 8, 8); std::cout << d2 - d1 << std::endl; d1 += days(10); d1 += months(2); d1 -= weeks(1); d2 -= years(2); } */ //-----------------------日期区间及其运算 /* date_time 库使用date_period类表示日期区间的概念是时间轴上的一个左闭右开的区间端点为两个date对象 构造: date_period pd1(date(2010,1,1),days(20)); 成员函数shift()和函数expand()可以变动区间:shift()将日期区间平移n天而长度不变expend()将日期向两端延长n天 */ //----------------------日期迭代器 /* date_iterator,week_iterator,month_iterator,和year_iterator,分别以天周月年单位递增和递减 date d(2006,1,1); day_iterator d_iter(d);//默认增减步长为1; ++diter; year_iterator y_iter(*d_iter,3);递增为3年 */ //--------------------------其它功能 /* 类boost::gregorian::gregorian_calendar 提供了格里高利利的一些操作函数基本上他被date类内部使用,他的几个静态函数 is_leap_year()可以判断是否是闰年end_of_month_day(),返回该月最后一天 */ //------------------------------------------------------处理时间 /* date_time 库在格里高利历的基础上提供了微秒级的时间系统对那如果需要它最高可达到纳秒级的精确度 date_time库的时间功能位于名字空间boos::posix_time 使用范方式:#include<boost/date_time/posix_time/posix_time.hpp> using namespace boost::posix_time ----------------------------------------------时间长度 date_time库使用time_duration度量时间的长度 精确到微秒,如果在头文件<boost/date_time/posix_time/posix_time.hpp>之前定义了宏 BOOST_DATE_TIME_STD_CONFIG 则可以精确到纳秒级 time_duration 也有几个子类可以度量不同的时间分辨率如 hour .................等 ---------------------------------------------操作时间长度 time_duration 可以再构造函数指定时分秒和微秒来构造 time_duration td(1,20,30,1000); 使用time_duration 的子类可以更直观的创建时间长度 hour h(1); minutes m(10); time_duration td=h+m; 使用工厂函数duration_from_string可以从一个字符串创建 time_duration td=duration_from_string("1:10:30:001"); 如果想要得到time_duration 对象字符串表示可以使用自由函数 to_simple_string(time_duration) */ //--------------------------------------------时间长度的精确度 /* date_time 库默认时间的精确度是微秒纳秒相关的类和函数如nanosec 和成员函数nanoseconds(),total_nanoseconds()都不可用,秒一下时间的度量都使用微秒 如使用了宏BOOST_DATE_TIME_POSIX_STD-CONFIG时time_duration 的一些行为将发生变化时间分辨率将到达纳秒,构造函数中秒以下的时间独狼都是用微秒 BOOST_DATE_TIME_POSIX_STD-CONFIG//定义纳秒级宏 #define BOOST_DATE_TIME_SOURCE #include<boost\date_time\posix_time/posix_time.hpp> time_duration td(1,10,30,1000);//1000纳秒 cout<<td; assert(td.total_milliseconds()==td.total_seconds()*1000); time_duration 提供静态成员函数resolution()和num_fractional_digits()来检测当前的精确度 ----------------------------------------------时间点 ptime是date_time库处理时间的核心类用64位或96位的整数字内部存储时间数据 --------------------------------------创建时间点对象 using namespace boost::gregorian; ptime p(date(2010,3,5),hours(1)); ptime p1=time_from_string("2010-3-5 01:00:00")//使用工厂函数创建 ptime p2=from_iso_string("20100305T010000") ptime有时钟类可以从时钟产生当前时间,时间具有不同的分辨率有两个类second_time()和microsec_clock分别提供秒级和微秒级的分辨率 local_time 获取当地时间 univeral_time()获取utc当前时间 ptime p1=second_clock::local_time();//秒级精度 microsec_clock::universal_time()//微秒级精度 ptime使用 date()和time_of_day()两个成员函数获取时间点中的日期和时间长度 time提供三个自由函数转化为字符串 to_simple_string(ptime):yyyy-mmm-dd hh:mm:ss.fffffff格式 to_iso_string(ptime):转化为yyyymmddthhmmss,fffff格式 to_sio_extended_string(ptime):yyyy-mm-ddthh:mm:ss,ffffff ----------------tm,time_t等结构的转换 to_tm(),ptime可以单向转化为tm结构,转化规则是:date和time_duration的组合 ptime p(date(2010,2,14),hours(20)); tm t=to_tm(p); !!!不存在从tm转化为ptime的函数 如果要转化需先转化为date对象(date_from_tm()函数)得到date对象 然后手工操作tm结构得到time_duration对象,然后创建ptime from_time_t(time_t)和from_ftime<ptime>(FILETIME),他们可以从time_t和FILETIME结构创建出ptime对象,这种转化也是单向的 ----------------时间区间 与日期区间date_period 对应,date_time库也有时间区间的概念,使用类:time_period 其用法基本上和date_period 基本相同 ---------------时间迭代器 不同于日期迭代器,时间迭代器只有一个time_iterator.它的构造时传入一个起始时间点ptime对象和一个不长time_duration对象 time_iterator也可日期时间以直接与ptime比较无需再使用解引用操作符 --------------格式化时间 date_time库默认的日期时间格式简单标准且是英文,但并不是不可改变的date_time库提供专门的格式化对象date_facet,time_facet等来搭配io流定制 日期时间的表现形式 ------------------本地时间 date_time库使用time_zone_base,posix_time_zone,custom_time_zone,local_date_time 等类和一个文本格式好的时区数据库解决本地时间 -------------------序列化 date_time库可以使用boost.serialization库的能力是信啊数据序列化把日期时间数据存入某个文件,之后在任意的时刻读取恢复