Boost 時間處理
//部分來自
//https://www.cnblogs.com/yegoufromchongqing/archive/2013/01/11/2856168.html
{
自己進行了一定的補充
}
//https://www.cnblogs.com/yegoufromchongqing/archive/2013/01/11/2856168.html
{
[Boost]boost的時間和日期處理-(1)日期的操作
<開篇>
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,之類。
關於時間的處理,和日期非常類似,我也會在續篇中介紹,在此結貼鳥。
<完結>
}
my
{
#include <iostream> //extern "C" //{ //#include <libavutil/des.h> //} #include <openssl/des.h> #include <boost/timer.hpp> #include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/posix_time/ptime.hpp> #include <boost/date_time/time.hpp> #include <boost/date_time/posix_time/posix_time.hpp> //int en(void *datas, int size) //{ // unsigned char key[] = "FDS5F46F5631DSV61DS11F1DAF16FDS5F46S1DFDS541F5631DSV61DS1F1DAF16"; // int keylen = strlen((char*)key); // unsigned char data[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // int datalen = strlen((char*)data); // // // unsigned char buf_e[1024] = { 0 }; // unsigned char buf_d[1024] = { 0 }; // // auto des = av_des_alloc(); // auto ret = av_des_init(des, key, keylen, 0); // // av_des_crypt(des, buf_e, (unsigned char*)data, datalen, nullptr, 0); // ret = av_des_init(des, key, keylen, 1); // av_des_crypt(des, buf_d, buf_e, 1, nullptr, 1); // // // // return -1; //} // //int de(void *data, void *out) //{ // const char *keystring = "this is my key"; // DES_cblock key; // DES_key_schedule key_schedule; // // //生成一個 key // DES_string_to_key(keystring, &key); // if (DES_set_key_checked(&key, &key_schedule) != 0) { // printf("convert to key_schedule failed.\n"); // return -1; // } // // //需要加密的字串 // unsigned char input[] = "this is a text being encrypted by openssl"; // size_t len = (sizeof(input) + 7) / 8 * 8; // unsigned char *output = (unsigned char *)malloc(len + 1); // //IV // DES_cblock ivec; // // //IV設定為0x0000000000000000 // memset((char*)&ivec, 0, sizeof(ivec)); // // //加密 // DES_ncbc_encrypt(input, output, sizeof(input), &key_schedule, &ivec, DES_ENCRYPT); // // //輸出加密以後的內容 // for (int i = 0; i < len; ++i) // printf("%02x", output[i]); // printf("\n"); // // memset((char*)&ivec, 0, sizeof(ivec)); // unsigned char ii[256] = { 0 }; // //解密 // DES_ncbc_encrypt(output, ii, len, &key_schedule, &ivec, 0); // // printf("%s\n", ii); // // free(output); // return -1; //} using namespace boost::gregorian; using namespace std; using namespace boost::posix_time; int main(int argc, char *argv[]) { printf("=============\n"); date d(day_clock::local_day()); auto d_0 = boost::gregorian::day_clock::local_day_ymd(); auto d_1 = boost::gregorian::to_iso_extended_string(d); std::cout << d_1 << std::endl; std::string strDateTime = boost::posix_time::to_simple_string(boost::posix_time::microsec_clock::local_time()); std::cout << strDateTime << std::endl; std::string strTime = boost::posix_time::to_iso_string(boost::posix_time::microsec_clock::local_time()); strTime.insert(4, "-"); strTime.insert(7, "-"); int pos = strTime.find('T'); strTime.replace(pos, 1, std::string(" ")); strTime.insert(13, ":"); strTime.insert(16, ":"); std::cout << strTime << std::endl; auto t = boost::posix_time::microsec_clock::local_time(); date leap_year_date(day_clock::local_day()); date norm_year_date(2020, Jan, 31); date_duration dd(3); years yy(2); months mm(1); days dd1(10); weeks ww(2); //爽歪歪 std::cout << (leap_year_date - days(365)) << std::endl; //爽歪歪 std::cout << boost::gregorian::to_iso_extended_string((leap_year_date - days(365))) << std::endl; std::cout << (leap_year_date + dd) << std::endl; std::cout << (leap_year_date + dd1) << std::endl; std::cout << (leap_year_date + ww) << std::endl; std::cout << (leap_year_date + mm) << std::endl; std::cout << (leap_year_date + yy) << std::endl; std::cout << (norm_year_date + dd) << std::endl; std::cout << (norm_year_date + dd1) << std::endl; std::cout << (norm_year_date + ww) << std::endl; std::cout << (norm_year_date + mm) << std::endl; std::cout << (norm_year_date + yy) << std::endl; return 0; }
}
執行結果
{
}