1. 程式人生 > >Boost之日期時間處理(date_time庫)

Boost之日期時間處理(date_time庫)

概述

使用date_time庫需要在編譯時加上"-lboost_date_time",而且需要包含以下標頭檔案: 處理日期的元件:#include <boost/date_time/gregorian/gregorian.hpp> 處理時間的元件:#include <boost/date_time/posix_time/posix_time.hpp>

date類

date是date_time庫處理日期的核心類,使用一個32位的整數作為內部儲存,以天為單位表示時間點概念。date也全面支援比較操作和輸入輸入出,我們可以完全把它當成一個像int、string那樣的基本型別來使用。
#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>

using namespace std;
using namespace boost::gregorian;
int main()
{
    date d1(2001, 1, 1);
    date d2(2002, Feb, 2);
    date d3 = from_string("2003-3-3");
    date d4 = from_string("2004/4/4");
    date d5 = from_undelimited_string("20050505");

    cout << "本地日期:" << day_clock::local_day() << endl
         << "UTC日期:" << day_clock::universal_day() << endl << endl;

    cout << "負無限日期:" << neg_infin << endl
         << "正無限日期:" << pos_infin << endl
         << "無效日期:" << not_a_date_time << endl
         << "最大可能日期:" << max_date_time << endl
         << "最小可能日期:" << min_date_time << endl << endl;

    cout << "對於2001-01-01:" << endl
         << "年:" << d1.year() << endl
         << "月:" << d1.month() << endl
         << "日:" << d1.day() << endl << endl;

    cout << "對於2002-02-02:" << endl
         << "星期數:(0表示星期天)" << d2.day_of_week() << endl
         << "當年的第幾天:" << d2.day_of_year() << endl
         << "當年的第幾周:" << d2.week_number() << endl
         << "當月的最後一天:" << d2.end_of_month() << endl << endl;

    cout << "對於2003-03-03:" << endl
         << "直接列印日期:" << d3 << endl
         << "使用to_simple_string列印日期:" << to_simple_string(d3) << endl
         << "使用to_iso_string列印日期:" << to_iso_string(d3) << endl
         << "使用to_iso_extended_string列印日期:" << to_iso_extended_string(d3) << endl << endl;

    return 0;
}

輸出: 本地日期:2016-Jun-24
UTC日期:2016-Jun-24

負無限日期:1
正無限日期:2
無效日期:0
最大可能日期:4
最小可能日期:3

對於2001-01-01:
年:2001
月:Jan
日:1

對於2002-02-02:
星期數:(0表示星期天)Sat
當年的第幾天:33
當年的第幾周:5
當月的最後一天:2002-Feb-28

對於2003-03-03:
直接列印日期:2003-Mar-03
使用to_simple_string列印日期:2003-Mar-03
使用to_iso_string列印日期:20030303
使用to_iso_extended_string列印日期:2003-03-03

date_duration類

date_duration表示日期長度,是以天為單位的時長,值可以是任意的整數,可正可負。date_time庫為date_duration定義了一個常用的typedef: days。此外,date_time庫還提供了months、years、weeks等另外三個時長類,分別用來表示月,年和星期,它們的含義與days型別,但行為不太相同。
<span style="font-family:SimSun;">#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>

using namespace std;
using namespace boost::gregorian;

int main()
{
    days dd1(10), dd2(-5);
    cout << "dd1 + dd2 = " << (dd1 + dd2).days() << endl;
    weeks w(3);
    cout << "3個星期的天數:" << w.days() << endl;
    months m(5);
    years y(3);
    months m2 = y + m;
    cout << "3年5個月的月數:" << m2.number_of_months() << endl << endl;

    date d1(2001, 1, 1);
    date d2(2002, 1, 1);
    cout << "d2 - d1 = " << d2 - d1 << endl;
    d1 += days(10);
    cout << "d1 + days(10)後:" << d1 << endl;
    d1 += months(2);
    cout << "d1 + months(2)後:" << d1 << endl;
    d1 -= weeks(1);
    cout << "d1 - weeks(1)後:" << d1 << endl;
    d1 -= years(10);
    cout << "d1 - years(10)後:" << d1 << endl;

    return 0;
}</span>
輸出: dd1 + dd2 = 5
3個星期的天數:21
3年5個月的月數:41

d2 - d1 = 365
d1 + days(10)後:2001-Jan-11
d1 + months(2)後:2001-Mar-11
d1 - weeks(1)後:2001-Mar-04
d1 - years(10)後:1991-Mar-04

date_period類

date_period類用來表示日期區間的概念,它是時間軸上一個左閉右開區間,端點是兩個date物件
#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>

using namespace std;
using namespace boost::gregorian;

int main()
{
    /* 兩種構造方式 */
    date_period dp1(date(2000, 1, 1), days(20));
    date_period dp2(date(2000, 1, 5), date(2000, 1, 15));

    /*
     * 成員函式begin()和last()返回日期區間的兩個端點
     * end()返回last()後的第一天,與標準容器中的end()含義相同
     * length()返回日期區間的長度
     */
    cout << "dp1.begin() = " << dp1.begin() << endl
         << "dp1.last() = " << dp1.last() << endl
         << "dp1.end() = " << dp1.end() << endl
         << "dp1.length() = " << dp1.length() << endl << endl;
    /*
     * shift()將日期區間平移n天而長度不變
     * expand()將日期區間向兩端延伸n天,相當於區間長度加2n天
     */
    dp1.shift(days(3));
    cout << "shitf(): " << dp1 << endl;
    dp1.expand(days(3));
    cout << "expand(): " << dp1 << endl << endl;

    /* 判斷某個日期是否在區間內或者計算日期區間的交集 */
    if (dp1.is_after(date(1999, 12, 12)))
        cout << "dp1在1999-12-12後\n";
    if (dp1.is_before(date(2000, 1, 27)))
        cout << "dp1在2000-01-20前\n";
    if (dp1.contains(date(2000, 1, 10)))
        cout << "2000-01-10在dp1中\n";
    if (dp1.contains(dp2))
        cout << "dp1包含dp2\n";
    if (dp1.intersects(dp2))
        cout << "dp1和dp2存在交集,交集為:"
             << dp1.intersection(dp2) << endl;
    if (!dp1.is_adjacent(dp2))
        cout << "dp1和dp2不相鄰\n\n";

    /*
     * merge()返回兩個區間的並集,如果區間無交集或者不相鄰則返回無效區間
     * span()合併兩日期區間及兩者的間隔,相當於廣義的merge()
     */
    date_period dp3(date(2000, 2, 1), days(10));
    cout << "dp1.merge(dp3): " << dp1.merge(dp3) << endl
         << "dp1.span(dp3): " << dp1.span(dp3) << endl;

    return 0;
}
輸出: dp1.begin() = 2000-Jan-01
dp1.last() = 2000-Jan-20
dp1.end() = 2000-Jan-21
dp1.length() = 20

shitf(): [2000-Jan-04/2000-Jan-23]
expand(): [2000-Jan-01/2000-Jan-26]

dp1在1999-12-12後
dp1在2000-01-20前
2000-01-10在dp1中
dp1包含dp2
dp1和dp2存在交集,交集為:[2000-Jan-05/2000-Jan-14]
dp1和dp2不相鄰

dp1.merge(dp3): [2000-Jan-01/1999-Dec-31]
dp1.span(dp3): [2000-Jan-01/2000-Feb-10]


日期迭代器

通過日期迭代器可以用簡單的遞增遞減操作符連續訪問日期,這些迭代器包括:day_iterator、week_iterator、month_iterator和year_iterator。需要注意的是它們並不符合標準迭代器的定義,沒有difference_type、pointer、reference等內部型別定義,不能使用std::advance()或者operator+=來前進或者後退。
#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>

using namespace std;
using namespace boost::gregorian;

int main()
{
    date d(2000, 1, 1);
    day_iterator d_iter(d);     //增減步長預設為1天
    ++d_iter;
    if (d_iter == date(2000, 1, 2))     //這裡不需要解引用就可以直接比較
        cout << "d_iter == date(2000, 1, 2)\n";

    year_iterator y_iter(*d_iter, 8);   //增減步長為8年
    ++y_iter;
    if (y_iter->year() == 2008)
        cout << "增長了8年\n";

    return 0;
}

輸出: d_iter == date(2000, 1, 2)
增長了8年


time_duration類

與date_duration類似,date_time庫使用time_duration度量時間長度。time_duration有幾個子類,可以度量不同的時間解析度,它們分別是:hours、minutes、seconds、millisec/millisecnods、microsec/microseconds和nanosec/nanoseconds。
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace std;
using namespace boost::posix_time;

int main()
{
    /* 1小時10分鐘30秒1毫秒 */
    time_duration td1 = duration_from_string("1:10:30:001");
    cout << "td1: " << td1 << endl;

    /* 子類 */
    hours h(1);
    minutes m(10);
    seconds s(30);
    millisec ms(1);
    time_duration td2 = h + m + s + ms;
    cout << "td2: " << td2 << endl
         << "hours: " << td2.hours() << endl
         << "minutes: " << td2.minutes() << endl
         << "total_seconds: " << td2.total_seconds() << endl
         << "total_milliseconds: " << td2.total_milliseconds() << endl;

    /* 字串表示 */
    cout << "to_simple_string: " << to_simple_string(td2) << endl;    //01:10:30.001000
    cout << "to_iso_string: " << to_iso_string(td2) << endl;       //011030.001000

    return 0;
}
輸出: td1: 01:10:30.001000
td2: 01:10:30.001000
hours: 1
minutes: 10
total_seconds: 4230
total_milliseconds: 4230001
to_simple_string: 01:10:30.001000
to_iso_string: 011030.001000


 ptime類

ptime類表示時間點,它相當於一個日期再加上一個小於一天的時間長度。
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace std;
using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
    ptime p1(date(2001, 1, 1), hours(1));               //2001年1月1日凌晨1時
    ptime p2 = time_from_string("2002-2-2 02:00:00");
    ptime p3 = from_iso_string("20030303T030000");      //日期與時間用字母T隔開
    ptime p4 = second_clock::local_time();              //本地當前時間,秒精度
    ptime p5 = microsec_clock::universal_time();        //UTC當前時間,微秒精度
    cout << p1 << endl
         << p2 << endl
         << p3 << endl
         << p4 << endl
         << p5 << endl << endl;

    /*
     * date()獲得時間點中的日期
     * time_of_day()獲得時間長度
     */
    date d = p1.date();
    time_duration td = p1.time_of_day();
    cout << d << ", " << td << endl << endl;

    cout << to_simple_string(p2) << endl            //轉換為YYYY-mmm-DD HH:MM:SS.ffffff
         << to_iso_string(p2) << endl               //轉換為YYYYMMDDTHHMMSS,ffffff
         << to_iso_extended_string(p2) << endl;     //轉換為YYYY-MM-DDTHH:MM:SS,ffffff

    return 0;
}
輸出: 2001-Jan-01 01:00:00
2002-Feb-02 02:00:00
2003-Mar-03 03:00:00
2016-Jun-26 15:35:23
2016-Jun-26 07:35:23.240536

2001-Jan-01, 01:00:00

2002-Feb-02 02:00:00
20020202T020000
2002-02-02T02:00:00


time_period類

與日期區間date_period對應,date_time庫也有時間區間的概念,類time_period使用ptime作為區間的兩個端點,同樣是左閉右開區間,它與date_period用法基本相同。
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace std;
using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
    ptime p(date(2014,1,1),hours(12)) ;
    time_period tp1(p, hours(8));               //一個8小時的區間
    time_period tp2(p + hours(8), hours(1));    //1小時的區間
    if (tp1.end() == tp2.begin() && tp1.is_adjacent(tp2))
        cout << "兩個區間相鄰\n";
    if (!tp1.intersects(tp2))
        cout << "兩個區間不相交\n";

    tp1.shift(hours(1));                        //平移1小時
    if (tp1.is_after(p))
        cout << "tp1在中午之後\n";
    if (tp1.intersects(tp2))
        cout << "兩個區間現在相交\n";

    tp2.expand(hours(10));                      //向兩端擴充套件10小時
    if (tp2.contains(p) && tp2.contains(tp1))
        cout << "tp2包含p且包含tp1\n";

    return 0;
}
輸出: 兩個區間相鄰
兩個區間不相交
tp1在中午之後
兩個區間現在相交
tp2包含p且包含tp1


時間迭代器

不同於日期迭代器,時間迭代器只有一個time_iterator。它在構造時傳入一個起始時間點ptime物件和一個步長time_duration物件,然後就同日期迭代器一樣使用前置式operator++、operator--來遞增或遞減時間,解引用操作符返回一個ptime物件。
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace std;
using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
    ptime p(date(2014,11,3),hours(10)) ;
    for (time_iterator t_iter(p, minutes(10)); t_iter < p + hours(1); ++ t_iter)
        cout << *t_iter << endl;

    return 0;
}
輸出: 2014-Nov-03 10:00:00
2014-Nov-03 10:10:00
2014-Nov-03 10:20:00
2014-Nov-03 10:30:00
2014-Nov-03 10:40:00
2014-Nov-03 10:50:00