![]() |
Home | Libraries | People | FAQ | More |
格里曆日期系統提供了基於格里曆的日期編程系統。格里曆的第一次引入是在1582年,它修正了羅馬儒略歷的一個錯誤。不過,許多地區直到很後才採用這種修正。所以在歷史日期上可能存在一些混亂。
我們實現的日曆是一種"預想的格里曆",即將格里曆推廣至1582年首次採用格里曆之前的時間。當前的實現支持從 1400-Jan-01 到 9999-Dec-31 的日期。有很多被引用的1582年以前的日期是採用羅馬儒略歷的,所以如果要求對歷史日期進行準確的計算,就必須要小心。更多細節請參見 Reingold & Dershowitz 所寫的 日曆計算 一書。這本書中的日期信息常被用於對格里曆實現的正確性進行交叉測試。
格里曆系統的所有類型位於名字空間 boost::gregorian. 本庫提供一個方便的頭文件 boost/date_time/gregorian/gregorian_types.hpp,它包含了本庫所有類,但不帶輸入/輸出。另一個頭文件 boost/date_time/gregorian/gregorian.hpp 則包含所有類型以及輸入/輸出代碼。
類 boost::gregorian::date 是用戶使用的主要時間類型。如果你想學習編寫一個進行特定日期計算的程序,如查找"四月第一個星期天",請參見 日期生成器與算法。
| 例子 | 說明 |
|---|---|
| 簡單的日期算術。從時鐘取出當天日期。 | |
| 對日期字符串進行簡單分析,以及將日期格式化為字符串 | |
| 檢查某個日期是否在一組日期段中(如:某天是否假日/週末) | |
| 一個小工具程序,從命令行打印出某月的所有天。想知道 1999-Jan-1 是星期五還是星期六?這個程序可以示範怎麼做。 | |
| 使用日期生成器將抽像描述轉換為具體的日期集。 |
類 boost::gregorian::date 是日期編程的主要接口。通常 date 類一旦構造出來就是不可變的,不過它也允許從另一個 date 進行賦值。創建 date 的方法包括:從時鐘讀取當前日期,使用 日期迭代器,以及 日期算法或生成器。
在內部,boost::gregorian::date 是保存為一個32位整數類型的。該類特別被設計為不含虛函數。這樣的設計可以進行高效的運算,以及處理大量日期時具有高效的內存使用率。
構造一個 date 時將檢查所有的輸入,所以不可能構造一個無效的 date. 如 2001-Feb-29 就不可能被構造為一個 date. 多個派生自 std::out_of_range 的異常將被拋出以表示日期輸入的哪個方面有錯。注意,如果需要,可以用一個無效日期的特殊值來作為 '無效' 或 '空' 的 date.
#include "boost/date_time/gregorian/gregorian.hpp" //包含所有類型及 i/o
或
#include "boost/date_time/gregorian/gregorian_types.hpp" //只有類型不含 i/o
| 語法 | 說明 |
|---|---|
| 例子 | |
date(greg_year, greg_month, greg_day) |
從日期的各部分進行構造。如果年、月或日超出範圍,則拋出 bad_year, bad_day_of_month, 或 bad_day_month (均派生自 std::out_of_range)。 |
date d(2002,Jan,10); |
|
date(date d) |
複製構造函數 |
date d1(d); |
|
date(special_values sv) |
無限日期、無效日期、最大日期、最小日期的構造函函數 |
date d1(neg_infin); |
|
date() |
缺省構造函數。創建一個 date 對象,初始化為 not_a_date_time. 註:這個構造函數可以通過定義 DATE_TIME_NO_DEFAULT_CONSTRUCTOR 來禁止(請見 compiler_config.hpp)。 |
date d; // d => not_a_date_time |
| 語法 | 說明 |
|---|---|
| 例子 | |
date from_string(std::string) |
從日期字符串構造,字符串的順序應為年-月-日,如:2002-1-25 |
std::string ds("2002/1/25");
|
|
date from_undelimited_string(std::string) |
從 iso 類型的日期字符串構造,順序為年-月-日,如:20020125 |
std::string ds("20020125");
|
| 語法 | 說明 |
|---|---|
| 例子 | |
day_clock::local_day() |
取出本地日期,基於計算機的時區設置。 |
date d(day_clock::local_day()); |
|
day_clock::universal_day() |
取出UTC日期。 |
date d(day_clock::universal_day()); |
| 語法 | 說明 |
|---|---|
| 例子 | |
greg_year year() const |
取出日期中的年份。 |
date d(2002,Jan,10); |
|
greg_month month() const |
取出日期中的月份。 |
date d(2002,Jan,10); |
|
greg_day day() const |
取出日期中的日子。 |
date d(2002,Jan,10); |
|
greg_ymd year_month_day() const |
返回一個 year_month_day 結構。在需要日期的所有三個組成部分時,這一方法更高效。 |
date d(2002,Jan,10); |
|
greg_day_of_week day_of_week() const |
返回星期幾(如:星期天、星期一等等)。 |
date d(2002,Jan,10); |
|
greg_day_of_year day_of_year() const |
返回本年的第幾天。從 1 到 366 |
date d(2000,Jan,10); |
|
date end_of_month() const |
返回一個 date 對象,設置為傳入對像當月的最後一天。 |
date d(2000,Jan,10); |
|
bool is_infinity() const |
返回 true 如果 date 為正無限或負無限。 |
date d(pos_infin); |
|
bool is_neg_infinity() const |
返回 true 如果 date 為負無限。 |
date d(neg_infin); |
|
bool is_pos_infinity() const |
返回 true 如果 date 為正無限。 |
date d(neg_infin); |
|
bool is_not_a_date() const |
返回 true 如果 date 不是一個日期 。 |
date d(not_a_date_time); |
|
bool is_special() const |
返回 true 如果 date 為任意 special_value
|
date d(pos_infin); |
|
special_value as_special() const |
返回相應的 special_value,或者返回 not_special 如果 date 為正常日期。 |
long modjulian_day() const |
返回修正後的羅馬儒略歷日期。 |
long julian_day() const |
返回羅馬儒略歷日期。 |
int week_number() const |
返回 ISO 8601 的周數。 |
date end_of_month_day() const |
返回當月的最後一天。 |
date d(2000,Feb,1); |
| 語法 | 說明 |
|---|---|
| 例子 | |
std::string to_simple_string(date d) |
轉換為 YYYY-mmm-DD 字符串,其中 mmm 為3字符的月份名。 |
"2002-Jan-01" |
|
std::string to_iso_string(date d) |
轉換為 YYYYMMDD,所有部分均為整數。 |
"20020131" |
|
std::string to_iso_extended_string(date d) |
轉換為 YYYY-MM-DD,所有部分均為整數。 |
"2002-01-31" |
| 語法 | 說明 |
|---|---|
| 例子 | |
operator<< |
流輸出操作符 |
date d(2002,Jan,1); |
|
operator>> |
流輸入操作符。註:與版本1.33相比,流操作已進行了顯著改進。有關異常和錯誤條件的詳情請見 日期時間 IO 系統。 |
date d(not_a_date_time); |
|
operator==, operator!=, |
完整的比較操作符 |
d1 == d2, etc |
|
date operator+(date_duration) const |
返回加上一個日期偏移量後的 date |
date d(2002,Jan,1); |
|
date operator-(date_duration) const |
返回減去一個日期偏移量後的 date |
date d(2002,Jan,1); |
|
date_duration operator-(date) const |
對兩個 date 進行相減,返回一個 date_duration |
date d1(2002,Jan,1); |
以下函數用於 date 對象與 tm 結構的互轉。
| 語法 | 說明 |
|---|---|
| 例子 | |
tm to_tm(date) |
將 date 對像轉換為 tm 結構。字段 tm_hour, tm_min, 和 tm_sec 均設為零。tm_isdst 字段設為 -1. |
date d(2005,Jan,1); |
|
date date_from_tm(tm datetm) |
將 tm 結構轉換為 date 對象。字段 tm_wday , tm_yday , tm_hour, tm_min, tm_sec, 和 tm_isdst 均忽略。 |
tm d_tm; |
類 boost::gregorian::date_duration 是一個簡單的日子計數器,用於 gregorian::date 的運算。日期長度可正可負。
和版本1_32一樣,date_duration 類被 typedef 為 boost::gregorian 名字空間中的 days. 在以下所有例子中,你都能看到 days 被用於替代 date_duration.
#include "boost/date_time/gregorian/gregorian.hpp" //包含所有類型以及 i/o
或
#include "boost/date_time/gregorian/gregorian_types.hpp" //只有類型沒有 i/o
| 語法 | 說明 |
|---|---|
| 例子 | |
date_duration(long) |
創建一個日期長度計數。 |
date_duration dd(3); //3天 |
|
days(special_values sv) |
無限長度、非日期、最大日期、最小日期的構造函數 |
days dd1(neg_infin); |
| 語法 | 說明 |
|---|---|
| 例子 | |
long days() const |
返回 days 的計數。 |
date_duration dd(3); dd.days() --> 3 |
|
bool is_negative() const |
返回 true 如果 days 小於零。 |
date_duration dd(-1); dd.is_negative() --> true |
|
static date_duration unit() |
返回日期長度類型的最小可能單元。 |
date_duration::unit() --> date_duration(1) |
|
bool is_special() const |
返回 true 如果 days 為任意 special_value
|
days dd(pos_infin); |
| 語法 | 說明 |
|---|---|
| 例子 | |
operator<<, operator>> |
流操作符。註:從版本1.33起,流操作已經得到很大改進。詳情請見 日期時間 IO 系統 (包括異常和錯誤的情況)。 |
date d(not_a_date_time); |
|
operator==, operator!=, |
完整的比較操作符。 |
dd1 == dd2, etc |
|
date_duration operator+(date_duration) const |
加日期長度。 |
date_duration dd1(3); |
|
date_duration operator-(date_duration) const |
減日期長度。 |
date_duration dd1(3); |
以下這些類型是日期跨度的邏輯表示法。
| 語法 | 說明 |
|---|---|
| 例子 | |
months(int num_of_months) |
月份的邏輯表示法。根據不同的用法,months
對象可以表示28到31天的跨度。該對象與某月的最後一天一起使用時,其行為會保持為月末。警告:該行為可能導致非期望的結果。完整的細節和其它請參見:操作可逆性的缺陷。 |
months single(1); |
|
years(int num_of_years) |
年份的邏輯表示法。years 對像具有與 months 對象的月末特殊行為相同的行為。 |
years single(1); |
|
weeks(int num_of_weeks) |
表示 n * 7 天的日期長度類型。 |
weeks single(1); |
當向一個日期加上某個月份數,然後再減去相同的月份數時,我們自然期望可以準確得到原來的日期。多數情況下 date_time 庫可以提供這一結果,但是有一個重大的例外:即由 months 長度類型所帶來的月末效應。當開始日期為大月的28日、29日或30日時,months 長度類型會導致非預期的結果。而 month_iterator 則不會發生這個問題,所以我們在以下例子中將它作為解決該問題的一種方法。
如果開始的日期是在月中,那麼加上或減去任意月份數,都會得到某個月同一天的日期(例如,如果你從15日開始,你還會以15日結束)。但當開始的日 期是某月最後一天時,加上或減去任意月份數,所得結果將保持為某月的最後一天(例如,如果你從1月31日開始,則會得到:2月28日、3月31日,等 等)。
// 使用月份長度類型
date d(2005, Nov, 30); // 11月的最後一天
d + months(1); // 結果為12月最後一天 "2005-Dec-31"
d - months(1); // 結果為10月最後一天 "2005-Oct-31"
// 使用 month_iterator
month_iterator itr(d); // 11月最後一天
++itr; // 結果為12月最後一天 "2005-Dec-31"
--itr; // 回到原來的出發點 "2005-Nov-30"
--itr; // 10月最後一天 "2005-Oct-31"
如果開始日期為大月的28日,29日或 30日,則加上或減去一個月所得的結果可能變為月末,這可能不是所期望的。這樣會導致最終結果與開始日期不同。
// 使用月份長度類型
date d(2005, Nov, 29);
d += months(1); // "2005-Dec-29"
d += months(1); // "2006-Jan-29"
d += months(1); // "2006-Feb-28" --> 變成月末
d += months(1); // "2006-Mar-31" --> 非期望結果
d -= months(4); // "2005-Nov-30" --> 非期望結果,不是開始的日期
// 使用 month_iterator
month_iterator itr(date(2005, Dec, 30));
++itr; // "2006-Jan-30" --> ok
++itr; // "2006-Feb-28" --> 不會發生月末效應
++itr; // "2006-Mar-30" --> ok
--itr; // "2006-Feb-28" --> ok
--itr; // "2006-Jan-30" --> ok
--itr; // "2005-Dec-30" --> ok, 回到開始的日期
這些額外的日期長度類型(months, years, 和 weeks)是為了方便使用而提供的,它們可以很容易刪掉以確保不會出現以上缺陷。要刪除這些類型,只需要將宏
BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES 去定義即可。
類 boost::gregorian::date_period 提供了對兩個日期之間的範圍的直接表示。日期段可以通過簡化程序的條件判斷邏輯來簡化一些計算類型。例如,測試某個日期是否在某個沒有規律的時間表如週末 或假日中,就可以用一組日期段來實現。有多種方法來判斷一個 date_period 是否與另一個 date period 交叉,以及生成重疊的日期段。日期段計算例子 一節中提供了這個例子。
由相同的開始日期和結束日期所創建的日期段,稱為零長度日期段。零長度日期段被認為是無效的(構造一個無效的日期段是完全合法的)。對於這些日期段,last 點總是比 begin 小一個單元。
日期段與無限值結合使用可以表示象 '直至另行通知為止' 這樣的複雜概念。
#include "boost/date_time/gregorian/gregorian.hpp" //包含所有類型和 i/o
或
#include "boost/date_time/gregorian/gregorian_types.hpp" //只有類型沒有 i/o
| 語法 | 說明 |
|---|---|
| 例子 | |
date_period(date, date) |
創建一個 [begin, end) 日期段。如果 end <= begin 則日期段無效。 |
date_period dp(date(2002,Jan,10), |
|
date_period(date, days) |
創建一個 [begin, begin+len) 日期段,其中 end 點為 begin+len. 如果 len <= 0 則日期段定義為無效。 |
date_period dp(date(2002,Jan,10), |
|
date_period(date_period) |
複製構造函數 |
date_period dp1(dp); |
| 語法 | 說明 |
|---|---|
| 例子 | |
date_period shift(days) |
同時為 begin 和 end 加上偏移量。 |
date_period dp(date(2005,Jan,1), days(3)); |
|
date_period expand(days) |
從 begin 減去日期長度而為 end 加上日期長度。 |
| 語法 | 說明 |
|---|---|
| 例子 | |
date begin() |
返回日期段的第一天。 |
date_period dp(date(2002,Jan,1), |
|
date last() |
返回日期段最後一天。 |
date_period dp(date(2002,Jan,1), |
|
date end() |
返回日期段最後一天後的一天。 |
date_period dp(date(2002,Jan,1), |
|
days length() |
返回 date_period 的長度。 |
date_period dp(date(2002,Jan,1), |
|
bool is_null() |
返回 True 如果日期段是無效的。如:end 小於或等於 begin. |
date_period dp(date(2002,Jan,10), |
|
bool contains(date) |
返回 True 如果 date 包含在日期段中。零長度日期段不包含任何日期。 |
date d(2002,Jan,1); |
|
bool contains(date_period) |
返回 True 如果 date period 包含在日期段中。 |
date_period dp1(date(2002,Jan,1), |
|
bool intersects(date_period) |
返回 True 如果兩個日期段交叉。 |
date_period dp1(date(2002,Jan,1), |
|
date_period intersection(date_period) |
計算兩個日期段的交集。返回 Null 如果沒有交叉。 |
date_period dp1(date(2002,Jan,1), |
|
date_period is_adjacent(date_period) |
檢驗兩個日期段是否相鄰且不交叉。 |
date_period dp1(date(2002,Jan,1), |
|
date_period is_after(date) |
判斷日期段是否在給定的 date 之後。 |
date_period dp1(date(2002,Jan,10), |
|
date_period is_before(date) |
判斷日期段是否在給定的 date 之前。 |
date_period dp1(date(2002,Jan,1), |
|
date_period merge(date_period) |
返回兩個日期段的並集。返回 Null 如果交叉。 |
date_period dp1(date(2002,Jan,1), |
|
date_period span(date_period) |
合併兩個日期段及它們之間的間隔,相當於 begin = min(p1.begin, p2.begin) 且 end = max(p1.end , p2.end) |
date_period dp1(date(2002,Jan,1), |
|
date_period shift(days) |
同時為 begin 和 end 加上偏移量。 |
date_period dp1(date(2002,Jan,1), |
|
date_period expand(days) |
從 begin 減去日期長度而為 end 加上日期長度。 |
date_period dp1(date(2002,Jan,4), |
| 語法 | 說明 |
|---|---|
| 例子 | |
std::string to_simple_string(date_period dp) |
轉換為 [YYYY-mmm-DD/YYYY-mmm-DD] 字符串,其中 mmm 為3字符的月份名。 |
[2002-Jan-01/2002-Jan-31] |
| 語法 | 說明 |
|---|---|
| 例子 | |
operator<< |
date_period 的流輸出操作符。使用 facet 來格式化時間點。典型的輸出:[2002-Jan-01/2002-Jan-31]. |
std::cout << dp << std::endl; |
|
operator>> |
date_period 的流輸入操作符。使用 facet 來分析時間點。 |
"[2002-Jan-01/2002-Jan-31]" |
|
operator==, operator!=, |
完整的比較操作符。 |
dp1 == dp2, etc |
|
operator< |
返回 True 如果 dp1.end() 小於 dp2.begin() |
dp1 < dp2, etc |
|
operator> |
返回 True 如果 dp1.begin() 大於 dp2.end() |
dp1 > dp2, etc |
日期迭代器為對日期進行迭代提供了一個標準機制。日期迭代器是一種 雙向迭代器 並可用於大多日期集合以及其它日期生成任務。例如,打印月份 的例子對一個月中的所有日子進行迭代並打印出它們。
這裡的所有迭代器均派生自 boost::gregorian::date_iterator.
#include "boost/date_time/gregorian/gregorian.hpp" //包含所有類型和 i/o
或
#include "boost/date_time/gregorian/gregorian_types.hpp" //只有類型沒有 i/o
| 語法 | 說明 |
|---|---|
| 例子 | |
date_iterator |
所有日期級迭代器的公共(抽像)基類。 |
day_iterator(date start_date, int day_count=1) |
每次迭代 day_count 個日子。該迭代器不提供後綴式的遞增/遞減操作符。只提供前綴式的遞增/遞減操作符。 |
day_iterator day_itr(date(2005,Jan,1)); |
|
week_iterator(...) |
每次迭代 week_offset 個星期。該迭代器不提供後綴式的遞增/遞減操作符。只提供前綴式的遞增/遞減操作符。 |
week_iterator wk_itr(date(2005,Jan,1)); |
|
month_iterator(...) |
迭代 month_offset
個月份。在處理月末時有特殊規則。即:如果開始的日期是某月的最後一天,則總是將結果調整為月末。如果結果日期超出月末(如 Jan
31 + 1 month)則往回調整至月末(有關細節和例子,請參見 操作可逆性的缺陷。註:month_iterator
不會產生這一缺陷)。該迭代器不提供後綴式的遞增/遞減操作符。只提供前綴式的遞增/遞減操作符。 |
month_iterator m_itr(date(2005,Jan,1)); |
|
year_iterator(...) |
迭代 year_offset 個年份。year_iterator 總是得到同一天的結果,除了當日期為非閏年的 Feb 28 時。在這種情況下,迭代器將在結果為閏年時返回 Feb 29 (如:2003-Feb-28, 2004-Feb-29, 2005-Feb-28)。該迭代器不提供後綴式的遞增/遞減操作符。只提供前綴式的遞增/遞減操作符。 |
year_iterator y_itr(date(2005,Jan,1)); |
日期算法或生成器是一些生成其它日期或日期時間表的工具。生成器函數以日期的某些部分如月份和日子開始,並通過提供其它部分以生成一個具體的日期。這使得程序員可以表示象"二月的第一個星期天"這樣的概念,並在提供一個或多個年份後創建一組具體的日期。註:從 boost 的 1_31_0 版本起,日期生成器的名字已被改變。舊的名字現在還可以使用,但是不再提供文檔,並可能在某個時候取消。
同時還提供了生成一個日期或計算一段日期長度的獨立函數。這些函數以一個 date 對像和一個 weekday 對像為參數。
所有日期生成器類和函數均位於 boost::gregorian 名字空間中。
例子 打印假日 示範了詳細的用法。
#include "boost/date_time/gregorian/gregorian.hpp"
| 類和 get_date 參數 | 說明 |
|---|---|
| 例子 | |
year_based_generator |
以下類型的統一(抽像)的日期生成器基類:partial_date, nth_day_of_the_week_in_month, first_day_of_the_week_in_month, 和 last_day_of_the_week_in_month. |
| 例子 打印假日 示範了詳細的用法。 | |
last_day_of_the_week_in_month(greg_weekday, |
計算像一月的最後一個星期天這樣的日期。 |
last_day_of_the_week_in_month lwdm(Monday,Jan); |
|
first_day_of_the_week_in_month(greg_weekday, |
計算像一月的第一個星期一這樣的日期。 |
first_day_of_the_week_in_month fdm(Monday,Jan); |
|
nth_day_of_the_week_in_month(week_num, |
week_num 是 nth_day_of_the_week_in_month 的一個公有枚舉成員。計算像一月的第一個星期一、三月的第二個星期二、十二月的第三個星期日等這樣的日期。(支持第一到第五個,第五個相當於最後一個) |
typedef nth_day_of_the_week_in_month nth_dow; |
|
partial_date(greg_day, greg_month) |
為給定的月份和日子提供一個年份以生成日期。 |
partial_date pd(1,Jan); |
|
first_day_of_the_week_after(greg_weekday) |
計算象 Jan 1,2002 後的第一個星期天這樣的日期。 |
first_day_of_the_week_after fdaf(Monday); |
|
first_day_of_the_week_before(greg_weekday) |
計算象 Feb 1,2002 之前的第一個星期一這樣的日期。 |
first_day_of_the_week_before fdbf(Monday); |
| 函數原型 | 說明 |
|---|---|
| 例子 | |
days days_until_weekday date, greg_weekday) |
計算從給定日期到給定週日的天數。 |
date d(2004,Jun,1); // 星期二 |
|
days days_before_weekday(date, greg_weekday) |
計算從給定日期到前一個給定週日的天數。 |
date d(2004,Jun,1); // 星期二 |
|
date next_weekday(date, greg_weekday) |
生成一個 date 對象,表示給定日期之後的某個週日的日期。 |
date d(2004,Jun,1); // 星期二 |
|
date previous_weekday(date, greg_weekday) |
生成一個 date 對象,表示給定日期之前的某個週日的日期。 |
date d(2004,Jun,1); // 星期二 |
類 boost::gregorian::gregorian_calendar 實現了創建格里曆日期系統所需的函數。包括將日期的年-月-日格式轉換為天數表示法以及相反的轉換。
對於多數用途,這個類只是被 gregorian::date 訪問而不是由用戶直接使用。不過,也有一些有用的函數可能被象 end_of_month_day 這樣的函數使用。
例子 打印月份 示範了以上功能。
#include "boost/date_time/gregorian/gregorian.hpp" //包含所有類型和 i/o
或
#include "boost/date_time/gregorian/gregorian_types.hpp" //只有類型沒有 i/o
| 語法 | 說明 |
|---|---|
| 例子 | |
static short day_of_week(ymd_type) |
返回星期幾(0==星期天,1==星期一,等等) |
| 參見 gregorian::date day_of_week | |
static date_int_type day_number(ymd_type) |
將 ymd_type 轉換為天數。該天數是一個從 epoch 起計的絕對數字。 |
static short end_of_month_day(year_type, |
給定年份和月份,確定該月最後一天。 |
static ymd_type from_day_number(date_int_type) |
將天數轉換為 ymd 結構。 |
static bool is_leap_year(year_type) |
返回 true 如果指定年份是閏年。 |
gregorian_calendar::is_leap_year(2000) |
| Copyright © 2001-2005 CrystalClear Software, Inc |