[Boost]boost的時間和日期處理日期的操作和時間的操作

參考 

http://www.cnblogs.com/lidabo/p/3938978.html 

http://www.cnblogs.com/lidabo/p/3938969.html



Boost.DateTime庫提供了時間日期相關的計算、格式化、轉換、輸入輸出等等功能,爲C++的編程提供了便利。不過它有如下特點:

1. Boost.DateTime 只支持1400年以後的任何Gregorian日曆日期。如果你需要計算再早的日期,則需要尋求其他庫來支持。

日期和時間是編程過程中常用的操作。在C標準庫中,<time.h>提供了time_t類型、和tm結構類型的時間日期相關函數。Windows API也提供了FILETIME類型的相關函數。由於這裏是介紹boost,就不比較這幾種之間的優劣了,感興趣的朋友可以深究一下,相信你會根據自己的需要進行選擇。那麼,下面我將根據不同情形大概介紹一下Boost.DateTime中的主要功能。如果你需要嚴格的時間精度計算,請參看Boost.DateTime穩定度和精度的討論

*基本概念:

時間點(Time Point)- 某一個時間,例如上午11點鐘。

時間段(Time Duration)- 一段時間,不特指起止時間,例如1小時。

時間窗口(Time Interval、Time Period)- 一段時間,從某個時間點到另一時間點,例如下午2點到3點。

時間系統(Time System)- 特定的時間表示、計算規則的體系。

日曆系統(Calendar System)- 以一天爲基礎的時間系統。Gregorian Calender是一個標準的日曆系統。

UTC時間(Coordinated Universal Time),支持閏秒的標準時間系統。類似的有格林威治時間GMT。

DST時間(Daylight Savings Time - 夏令時冬令時)很多國家地區在夏天會調整本地時間。

時區(Time Zone) - 使用特定DST規則和與標準時之間時間偏差規則的地區或國家。

Epoch - 日期系統和時鐘系統的起點。不同的時間系統起點不一樣,通常UTC起點爲1970年1月1號0點。

TAI Time - 高精度的時間系統,使用原子時,這個太深奧了,沒有具體研究過。

注:下列關於Boost.DateTime輸入輸出的操作,請參看另一篇介紹:Boost.DateTime的IO操作。

頭文件:

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

例1. 日期計算:打印今天日期;今年感恩節(11月的第4個星期四)的日期;如果還沒有到今年感恩節,打印今天到感恩節還有多少天。

using namespace boost::gregorian;
typedef nth_day_of_the_week_in_month nth_dow;
date today = day_clock::local_day(); //today
std::cout << "today is: " << today << std::endl;
nth_dow fourth_thur_in_nov(nth_dow::fourth,Thursday,Nov); // 4th thursday in Nov
date thanksgiving = fourth_thur_in_nov.get_date(today.year()); // get the date this year
std::cout << "Thanksgiving day this year is: " << thanksgiving << std::endl;

if(today < thanksgiving)
{
date_duration dd = thanksgiving - today; //date duration
std::cout << "has " << dd.days() << " days to thanksgiving."<< std::endl;
}

A. 對於date對象

>> 要獲取一個date對象,可以通過date的4種構造函數:

1:  date d(2013,Jan,10);//constructor from grep y/m/d
2:  date d1(d);//copy constructor
3:  /*special date values*/
4:  date d2(neg_infin);
5:  date d3(pos_infin);
6:  date d4(not_a_date_time);
7:  date d5(max_date_time);
8:  date d6(min_date_time);
9:  date d7; //default constructor

 >> 也可以通過string字符串獲得:

1:      using namespace boost::gregorian;
2:  date d(from_string("2002/1/25"));
3:  date d1(from_string("2002-1-25"));
4:  date d2(from_undelimited_string("20020125"));
5:  

 >> 還可以從時鐘獲得:

1:      using namespace boost::gregorian;
2:  date d(day_clock::local_day()); //獲取本地日期
3:  date d1(day_clock::universal_day());//獲取GMT日期
4:  

 >>要訪問date對象,或進行一些日期判斷,請參考下面代碼:

 1:      using namespace boost::gregorian;
 2:  date today = day_clock::local_day();
 3:  std::cout << today.year() << std::endl; //打印年
 4:  std::cout << today.month() << std::endl; //打印月
 5:  std::cout << today.day() << std::endl; //打印日
 6:  std::cout << today.week_number() << std::endl;//今年的第幾周
 7:  std::cout << today.day_of_week() << std::endl; //打印星期幾
 8:  std::cout << today.day_of_year() << std::endl; //打印一年中的第幾天
 9:  std::cout << today.end_of_month() << std::endl; //打印本月的最後一天是,閏月的2月,可以試試
10:  std::cout << today.modjulian_day() << std::endl;
11:  std::cout << today.julian_day() << std::endl;
12:  
13:      if(today.is_infinity())
14:  // today.is_neg_infinity();today.is_pos_infinity();today.is_not_a_date();
15:      // today.is_special();
16:      // today.as_special();
17:  {
18:  std::cout << "True" << std::endl;
19:  }
20:  else
21:  {
22:  std::cout << "False" << std::endl;
23:  }
24:  

>>我們經常還需要將時間轉換爲string類型,請參考:

1:  using namespace boost::gregorian;
2:  date today = day_clock::local_day();
3:  std::string str1(to_simple_string(today));//YYYY-MMM-DD, 2013-Jan-11
4:  std::string str2(to_iso_string(today));//YYYYMMDD, 20130111
5:  std::string str3(to_iso_extended_string(today));//YYYY-MM-DD, 2013-01-11
6:  std::cout << str1 << std::endl << str2 << std::endl << str3 << std::endl;

>>date對象還能夠和tm互相轉換: 

1:  using namespace boost::gregorian;
2:  date today = day_clock::local_day();
3:  tm d_tm = to_tm(today); // tm struct, year start from 1900, and Jan is 0, Sunday is 0
4:  std::cout << d_tm.tm_year << std::endl << d_tm.tm_mon << std::endl << d_tm.tm_mday << std::endl;
5:  std::cout << d_tm.tm_wday << std::endl;

 B. 對於date_duration對象

 

 

 

date_duration可以由多種方式構造,操作符+/-可以計算date,date_duration等,具體如下。

 1:      using namespace boost::gregorian;
 2:  date leap_year_date(2004,Jan,31);
 3:  date norm_year_date(2005,Jan,31);
 4:  date_duration dd(3);
 5:  days dd1(10);
 6:  weeks ww(2);
 7:  months mm(1);
 8:  years yy(2);
 9:  
10:  std::cout << (leap_year_date + dd) << std::endl;
11:  std::cout << (leap_year_date + dd1) << std::endl;
12:  std::cout << (leap_year_date + ww) << std::endl;
13:  std::cout << (leap_year_date + mm) << std::endl;
14:  std::cout << (leap_year_date + yy) << std::endl;
15:  
16:  std::cout << (norm_year_date + dd) << std::endl;
17:  std::cout << (norm_year_date + dd1) << std::endl;
18:  std::cout << (norm_year_date + ww) << std::endl;
19:  std::cout << (norm_year_date + mm) << std::endl;
20:  std::cout << (norm_year_date + yy) << std::endl;
21:  

另外,迭代器day_iterator,month_iterator,year_iterator也可以看做定長的date_duration工具,在此不細究。

  C. 對於date_period對象

date_peroid作爲一個日期窗口,可用於判斷一個日期是否落在這個窗口之間。

用兩個date或一個date加上一個days可以創建date_period。改變一個date_period可以用平移shift、也可以用加寬expand,可以合併merge,還可以取一個包含這兩個period的最小period,方法爲span。不過使用的時候大家得注意約束條件,比如merge的時候,兩個period應該相交,不然怎麼合呢?

 1:  using namespace boost::gregorian;
 2:  date d_begin(2013,Jan,22);
 3:  date d_end(2013,Apr,1);
 4:  date_period dp(d_begin,d_end);//constructor
 5:  date_period dp1(d_begin,days(20));//constructor 2
 6:  
 7:  std::cout << dp << std::endl;
 8:  dp.shift(days(10));
 9:  std::cout << dp << std::endl;
10:  dp.expand(days(10));
11:  std::cout << dp << std::endl;

到這裏,關於boost的date基本方法都有介紹。不過細心的可能發現,11月的第4個星期四問題還沒有細說。其實在boost::date_time裏面,有多種方法可以得到答案。例子中使用的是nth_day_of_the_week_in_month。大家不妨試試從11月1號開始,用next_weekday找第1個星期四,然後再加3個weeks,之類。

關於時間的處理,和日期非常類似,我也會在續篇中介紹,在此結貼鳥。

<完結>


<開篇>

本篇緊接着boost上篇敘述Boost::DateTime的時間處理。在C++中,常見的時間有time_t, FILETIME和tm,而boost中用ptime。

構造ptime

1.ptime的構造函數有四種:

1:      using namespace boost::posix_time;
2:      using namespace boost::gregorian;
3:  ptime pt(date(2013,Jan,24),time_duration(1,2,3)); //由date和time_duration構造
4:  ptime pt1(date(2013,Jan,24),hours()+nanosec(5));//改變形式的time_duration也能使用
5:  ptime pt2(p1);//拷貝構造函數
6:  ptime pt3(neg_infin);//特殊值構造
7:  ptime p;//默認構造函數,這裏p等於not_a_date_time

2.用string構造ptime:

1:      std::string ts1("2013-01-30 23:32:22.000");//固定格式,小數點後支持6位
2:  ptime pt1(time_from_string(ts1));
3:  std::string ts2("20130130T233222");//沒有分隔符的date和time
4:  ptime pt2(from_iso_string(ts2));
5:  

3.通過時鐘構造ptime:

1:      ptime ct1(second_clock::local_time());
2:  ptime ct2(second_clock::universal_time());
3:  ptime ct3(microsec_clock::local_time());
4:  ptime ct4(microsec_clock::universal_time());
5:  

4.time_t和FILETIME構造ptime:

1:      ptime t = from_time_t(tt); // 其中tt爲time_t
2:  ptime t1 = from_ftime<ptime>(ft); //其中ft爲FILETIME

ptime訪問日期時間

1:      using namespace boost::posix_time;
2:      using namespace boost::gregorian;
3:  ptime now(second_clock::local_time());
4:  std::cout << "today is: " << now.date() << std::endl;
5:  std::cout << "time is: " << now.time_of_day() << std::endl;
6:  

ptime轉換爲string

1:      std::string now_str(to_simple_string(now));
2:  std::string now_iso_str(to_iso_string(now));
3:  std::string now_iso_ext_str(to_iso_extended_string(now));
4:  std::cout << now_str << std::endl;
5:  std::cout << now_iso_str << std::endl;
6:  std::cout << now_iso_ext_str << std::endl;

ptime與tm,time_t,FILETIME互轉

1.tm

 1:     using namespace boost::posix_time;
 2:     using namespace boost::gregorian;
 3:     tm pt_tm;
 4:     pt_tm.tm_year = 113;
 5:     pt_tm.tm_mon = 11;
 6:     pt_tm.tm_mday = 25;
 7:     pt_tm.tm_hour = 2;
 8:     pt_tm.tm_min = 23;
 9:     pt_tm.tm_sec = 40;
10:  
11:     ptime pt = data_from_tm(pt_tm);
12:     std::cout << pt << std::endl;
13:  
14:     pt = pt + hours(2);
15:     tm pt_tm1 = to_tm(pt);

2. time_t

 1:      using namespace boost::posix_time;
 2:      using namespace boost::gregorian;
 3:  
 4:  time_t now = time(NULL);
 5:  std::cout << "time_t : " << now << std::endl;
 6:  ptime now_pt = from_time_t(now);
 7:  std::cout << "ptime from time_t : " << now_pt.time_of_day() << std::endl;
 8:  tm* now_tm = gmtime(&now);
 9:  std::cout << "tm struct: hour : " << now_tm->tm_hour << std::endl;
10:  

3.FILETIME

1:      FILETIME ft;
2:  ft.dwHighDateTime = 29715317;
3:  ft.dwLowDateTime = 3865122988UL
4:      ptime pt = from_ftime<ptime>(ft);
5:  // pt ===> 2005-Jun-07 15:30:57.03958200
6:  

time_duration和time_period

 1:      using namespace boost::posix_time;
 2:      using namespace boost::gregorian;
 3:  
 4:  time_duration td(100,200,3,9);
 5:  std::cout << td << std::endl;
 6:  date d(2013,Feb,5);
 7:  ptime pt(d,minutes(10));
 8:  ptime pt1(d,hours(10));
 9:  time_period tp(pt,pt1);
10:  std::cout << tp << std::endl;
11:  

對於這兩者的區別,一個是時間間隔,一個是時間起止的一個窗口。time_duration用於ptime的時間偏移計算爲主。而time_period可以計算一個ptime時間點是否在這個時間區間內(參考contains函數)。time_period在創建之後可以擴展,可以平移,函數分別爲expand和shift。請大家自己細究。

下一篇將介紹關於boost.datetime的格式化輸入輸出。

<完結>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章