ブーストは簡単です。 パート2. Boost.Date_time

既に理解しているように、この記事ではBoost.Date_Timeライブラリに焦点を当てます。 時間を操作するためのライブラリ。









この記事では、ライブラリの次の部分について検討します。









はじめに



今では、自分の目的のために時間を使用する必要性に直面することのない人、またはむしろ彼のデジタルプレゼンテーションを見つけることはおそらく難しいでしょう。 目標は、特定のコードが実行される時間間隔の単純な測定とはまったく異なる場合があります(方法については、プロファイリングの完全に誤った方法ですが、現在ではそうではありません)。アプリケーションで本格的なカレンダーをサポートします。地球上で。 これらのすべての操作は、かなり厳格で使いやすいが、同時に強力なBoost.Date_Timeライブラリを使用して実行できます。 ライブラリでは、 うるう年うるう秒 、夏時間などが考慮されます。

ライブラリで使用されるいくつかの用語を扱いましょう。

ライブラリには、3つのグローバルタイプのタイムシェアリングがあります。

  1. 時間ポイント -連続時間の特定のポイント、たとえば、生年月日
  2. 継続時間 -連続体のどの点にも結び付けられていない時間間隔
  3. 時間間隔 -時間連続の特定のポイントに関連付けられた時間間隔


また、時間を取得する各方法の解像度を覚えておく必要があります。解像度( Resolution )は、時間オブジェクトの分析に使用できる最小単位時間を示します。 つまり、得られた時点の精度の程度に他なりません。 最後に、ライブラリの機能を直接知り合いましょう。



ブースト::グレゴリアン



この記事で使用するすべての例は、各コンパイル済みユニットの先頭で名前空間boost :: <corresponding_namespace>を使用することを意味しています。

このコンポーネントは、 グレゴリオ暦とそれを使用して考えられるすべての可能性を提示します。 次に、次のコンポーネントに分割されます。



それぞれの目的を分析しましょう。



boost :: gregorian :: date-簡単に日付を保存するように設計されています-連続した時点。 time_tに関連付けられた標準C \ C ++メカニズムに基づいて、特定の形式の文字列からの日付の作成、およびboost :: date_time :: day_clockクラスを介した日付の作成をサポートします。

日付(演算子=を除いてオブジェクトによって変更できない)の保存に加えて、クラスには日付の特定の部分(年()、月()、日()など)を受け取り、日付の内部表現を文字列に変換するメソッド*があります、特定の形式(to_simple_string()、to_iso_string()、to_iso_extended_string())および標準C \ C ++構造体tm (to_tm()、date_from_tm())への変換(およびその逆)



*- 各機能の説明は提供しません。さらに、利用可能な機能の完全なリストも提供しません。特定のクラスに対応するリンクでそれらのリストを確認できます。 非常に多くの関数があり、それらは非常に使いやすいので、現時点で重要でないと考える場合、関数パラメーターの存在を省略します。

例:

date xGPWStart(1941, Jun, 22);

date xNowdays = day_clock::local_day();

std::cout << "The Great Patriotic War was started in " << xGPWStart << std::endl;

std::cout << "And the current data is " << xNowdays;




* This source code was highlighted with Source Code Highlighter .








結論:

大祖国戦争は1941年6月22日に開始されました

そして現在のデータは2009年7月26日です


boost :: gregorian :: date_duration-計算にboost :: gregorian :: dateを使用して日数をカウントします。

date_durationでの作業の便宜上、 months_durationyears_duration 、およびweeks_durationの 3つのクラスがあります(これらの型にはtypedefもありそれぞれが表示されます)。date_durationから加算または減算して、目的の結果を取得できます。 これらの3つのクラスに関連する落とし穴があります。 計算で使用すると、予期しない結果が得られる可能性があります。 例を挙げます。

date xSomeDay(1999, Jan, 28);

date xDayInNextMonth;

std::cout << "That's right: " << ( xDayInNextMonth = xSomeDay + months(1) ) << std::endl;

std::cout << "And that's not: " << xDayInNextMonth + months(1);



* This source code was highlighted with Source Code Highlighter .






そうです:1999年2月28日

それは違います:1999-Mar-31


この動作は、最初のオブジェクトが月( 28、29、30、31)を終了する可能性のある数値のいずれかを指している場合、 months_durationクラスの特性によるものです。このクラスは、算術演算で常に月末を使用します。 このタイプを使用するときmonth_iteratorにこの欠点がありません(利点?) ことに注意してください。しかし、後で説明します。



boost :: gregorian :: date_period-クラスは、2つの日付間の間隔を簡単に表示するために提示され、時間間隔(()を含む)、間隔(交差()、交差())、隣接日付( is_adjacent())およびある日付の位置と別の日付の位置の関係を決定します(is_after()、is_before())。 さらに、間隔を結合する方法(マージ()、スパン())とそれらを変更する方法(シフト()、展開())があります。 期間の最後のお金は期間全体に含まれないことを覚えておくことが重要です。つまり、期間1999年1月1日\ 1999年1月10日では、最終日は10ではなく1月9日になります。

例:

date_period xGPWDuration( date(1941, Jun, 22), date(1945, May, 9) );

date_period xStalinLifeYears( date(1878, Dec, 18), date(1953, Mar, 6) ); date_period xJukovsIncorrectLifeYears( date(1896, Dec, 6), date(1974, Jun, 14) );

std::cout << "The Great Patriotic War duration is " << xGPWDuration << std::endl;

std::cout << "Was the GPW inside the Stalin's life years? " << std::boolalpha << xStalinLifeYears.contains(xGPWDuration) << std::endl;

std::cout << "Jukov's incorrect life years is " << xJukovsIncorrectLifeYears << std::endl;

xJukovsIncorrectLifeYears.expand( days(5) );

std::cout << "Jukov's correct life years is " << xJukovsIncorrectLifeYears << std::endl;

//Last day isn't included in the interval

date_period xFirstPeriod( date(1999, Jan, 1), date(1999, Jan, 10) );

date_period xSecondPeriod( date(1999, Jan, 10), date(1999, Jan, 12) );

std::cout << "Does these periods intersect? " << std::boolalpha << xFirstPeriod.intersects(xSecondPeriod) << std::endl;



* This source code was highlighted with Source Code Highlighter .






結論:

大祖国戦争の期間は[1941-Jun-22 / 1945-May-08]です

GPWはスターリンの生涯の中でしたか? 本当

ユコフの誤った生年は[1896-Dec-06 / 1974-Jun-13]です

ユコフの正しい寿命は[1896-Dec-01 / 1974-Jun-18]です

これらの期間は交差していますか? 偽


boost :: gregorian :: date_iterator-名前が示すとおり-これは、日付を「移動」するように設計された典型的な反復子です。 date_iterator自体は、抽象クラスであり、その下位クラスであるday_iteratorweek_iteratormonth_iteratoryear_iteratorであるため、興味深いものではありません。

例として、誤った日付を受け取ったdate_durationの例を使用します(月のある落とし穴のため)。 前述したように、 date_iteratorにはそのような問題はありません

month_iterator xSomeDay(date(1999, Jan, 28));

std::cout << "That's right: " << *++xSomeDay << std::endl;

std::cout << "And that's too!: " << *++xSomeDay;



* This source code was highlighted with Source Code Highlighter .






そうです:1999年2月28日

そしてそれも!:1999-Mar-28




日付を操作するためのアルゴリズム -日付のさまざまな操作のための多様なクラスと関数のセット。 各クラスにはget_data()メソッドがあり、このクラスで生成された日付を取得できます。 クラスは次の機能を提供します。



関数は次の機能を提供します。



例:

last_day_of_the_week_in_month xLastFriday(Friday, Jul);

partial_date xJunTen(10, Jun);

std::cout << "What is the date of the last friday in the July 2009? " << xLastFriday.get_date(2009) << std::endl;

std::cout << "Just dusplay 10 Jun of 2009 " << xJunTen.get_date(2009) << std::endl;

std::cout << "How much days from now till next friday? " << days_until_weekday( day_clock::local_day(), greg_weekday(Friday) )<< std::endl;



* This source code was highlighted with Source Code Highlighter .






結論:

2009年7月の最後の金曜日の日付は何ですか? 2009年7月31日

2009年6月10日2009年6月10日

今から次の金曜日まで何日ですか? 5


boost :: gregorian :: gregorian_calendar-日付を操作するための有用な静的関数セットを提供します。

関数を説明する代わりに、その使用例を示します(関数は単純で、名前はそれ自体を物語っています)。

std::cout << "What the day of the GPW begining? " << DayToString( gregorian_calendar::day_of_week( gregorian_calendar::ymd_type(1941, Jun, 22) ) ) << std::endl;

std::cout << "And what is the number of this day frome the epoch start? " << gregorian_calendar::day_number( gregorian_calendar::ymd_type(1941, Jun, 22) ) << std::endl;

std::cout << "And what is the number of this day frome the epoch start? " << gregorian_calendar::day_number( gregorian_calendar::ymd_type(1400, Jan, 1) ) << std::endl;

std::cout << "What is the last day in the February 1941? " << gregorian_calendar::end_of_month_day(1941, Feb) << std::endl;

std::cout << "What is the date of the 3333333 day from the epoch start? " << date( gregorian_calendar::from_day_number(3333333) ) << std::endl;

std::cout << "Is the 2004 year a leap year? " << std::boolalpha << gregorian_calendar::is_leap_year(2004) << std::endl;



* This source code was highlighted with Source Code Highlighter .






結論:

GPWが始まる日は? 日曜日

そして、エポックの開始からこの日の数は何ですか? 2430168

そして、エポックの開始からこの日の数は何ですか? 2232400

1941年2月の最終日は何ですか? 28

エポック開始から3333333日の日付は何ですか? 4414-Apr-03

2004年はle年ですか? 本当


経験的に、関数day_number()およびfrom_day_number()の最小値は、それぞれ1400-Jan-1および2232400であることがわかりました。 1400-Jan-1より前の日付を使用しようとすると、例外が発生します。 同じことが日数にも当てはまります。



ブースト:: posix_time



このコンポーネントは、ポイントインタイムでの便利な操作方法を提供しますが、 boost :: gregorian boost :: posix_timeとは異なり、低解像度のタイムポイント(ナノ秒まで)で機能するため、 boostを使用して解像度(日付)の大部分が実装されます:グレゴリアン 。 このコンポーネントは、時間を正確に取得する必要があるタスク(たとえば、ログファイルのレコード行)に特に便利です。 次の部分に分かれています。



各部分の目的を分析しましょう:



boost :: posix_time :: ptime-連続時間のポイントを表します。 boost :: gregorian:dateと非常によく似ていますが、マイクロ秒までの解像度を持ちます。 gregorian:dateのみでクラスのインスタンスを作成する場合、「低解像度」部分は深夜(すべてゼロ)に設定されます。

使用例:

ptime xTime(date(1961, Apr, 12), hours(9) + minutes(7));

std::cout << "Did you know that Gagrin said \"Poehali\" at " << xTime << "\n" ;

ptime xTimeStr( time_from_string( "1961-04-12 09.07.00.0000" ) );

std::cout << "And the same time point constructed from a string: " << xTimeStr << "\n" ;

std::cout << "Current time with second resolution: " << second_clock::local_time() << "\nAnd with microsecond:" << microsec_clock::local_time();



* This source code was highlighted with Source Code Highlighter .






結論:

1961年4月12日09:07:00にギャグリンが「ポエハリ」と言ったことをご存知ですか

そして、文字列から構築された同じ時点:1961-Apr-12 09:07:00

2番目の解像度での現在の時刻:2009-Jul-29 16:41:51

そしてマイクロ秒で:2009-Jul-29 16:41:51.087000




boost :: posix_time :: time_duration-特定の日付に結び付けられていない期間を表します。 ライブラリーがデフォルトでマクロBOOST_DATE_TIME_POSIX_TIME_STD_CONFIGおよびマイクロ秒でコンパイルされる場合、期間の最大解像度はナノ秒に制限されます。 現在の期間に含まれる秒数、マイクロ秒数、ミリ秒数、ナノ秒数(適切なアセンブリを使用)の情報をオブジェクトから取得できます。

例:

time_duration xTime(1,2,3);

std::cout << "Print time: " << xTime << "\n" ;

std::cout << "Print increased time: " << xTime + hours(3) + seconds(2) + minutes(6) + milliseconds(15) + microseconds(25) << "\n" ;

std::cout << "Print total seconds: " << xTime.total_seconds() << " milliseconds: " <<

xTime.total_milliseconds() << " microseconds: " << xTime.total_microseconds() << "\n" ;



* This source code was highlighted with Source Code Highlighter .






結論:

印刷時間:01:02:03

印刷時間の増加:04:08:05.015025

印刷の合計秒:3723ミリ秒:3723000マイクロ秒:3723000000


boost :: posix_time :: time_period-期間を表します。クラスはgregorian :: date_periodに似ていますが、解像度は低くなります。 クラスの機能を使用すると、間隔の出現(含む())、交差(交差())、および間隔の長さ(長さ())を定義できます。 また、間隔を拡大(expand())、シフト(shift())、結合(merge())する可能性があります。

例:

ptime xDoomsday( date(2012, Jan, 1) );

time_period xArmageddonLast(xDoomsday, hours(1));

time_period xChakNorrisSmoke(xDoomsday, minutes(1));

std::cout << "Doomsday was during: " << xArmageddonLast<< "\n" ;

std::cout << "Chak Norris was smoking at " << xChakNorrisSmoke << "\n" ;

std::cout << "Did Chak Norris smoke during Doomsday breathtaking?" << std::boolalpha <<xArmageddonLast.contains(xChakNorrisSmoke);




* This source code was highlighted with Source Code Highlighter .






結論:

終末は次の期間でした:[2012-Jan-01 00:00:00 / 2012-Jan-01 00:59:59.999999]

Chak Norrisは[2012-Jan-01 00:00:00 / 2012-Jan-01 00:00:59.999999]で喫煙していました

チャクノリスは、終末の息をのむようなときに煙を出しましたか?


boost :: posix_time :: time_iterator- (おそらく誰もが推測したように)時間とともに反復するように設計されています。 この反復子の優れた機能は、反復で使用される時間間隔を設定する機能です。 時間の連続体の現在のポイントが反復ごとにどのくらい、どの単位で変化するか。 一時的な単位として、1時間からナノ秒までのすべての単位を使用できます(対応するフラグで収集された場合)

小さな例を挙げましょう。

ptime xTime(date(2012, Jan, 1));

time_iterator xIt(xTime, hours(6));

std::cout << "6 hours after Domsday has come!!!" << *++xIt;



* This source code was highlighted with Source Code Highlighter .






結論:

Domsdayの6時間後!!! 2012-Jan-01 06:00:00


現地時間システム



このコンポーネントは、さまざまなタイムゾーンで、夏時間に切り替えるためのさまざまなルールで、時間を操作する機会を提供します。 これはかなり強力で必要なコンポーネントであり、特に重要なのは現在の(現地の)時間だけではなく、時間に関する地域の合意(夏時間、タイムゾーンなど)に従ってさまざまな時間オフセットを考慮することが重要なアプリケーションに必要です。 そのため、このコンポーネントに含まれるパーツのリストを提供します。





boost :: local_time :: posix_time_zoneは、タイムゾーンを表すデータとルールのセットです(GMTに対するオフセット、夏時間ルール、タイムゾーンの名前とその省略形)。 このタイプのオブジェクトは、文字列に基づいて作成されます;文字列形式は、タイムゾーン用の標準化されたPOSIX形式(IEEE Std 1003.1)です。

一般的に、この行は次のようになります。

stdオフセットdst [オフセット]、開始[/時間]、終了[/時間]

std-タイムゾーンの略語。

offset -GMTに対するオフセット。

dst-サマータイム中のタイムゾーンの略語。

[オフセット] -夏時間に切り替えたときに変化する時間(時間単位)を示します。 オプションのパラメーター。

開始と終了 -夏時間の間隔を設定します。

[/ time] -夏時間が始まる日、または夏時間が無効になる日の正確な時間を設定します。

オフセット時刻の形式は次のとおりです。[+ |-] hh [:mm [:ss]] {h = 0-23、m / s = 0-59}

startendは、次の形式のいずれかで表すことができます。



このクラスのメソッドを使用して、この行の各部分を個別に取得できます。 ここに名前を付ける理由はありません。それらは非常に透明で、目的の本質を反映しているので、それらのリストについてはドキュメントを参照してください。

例として、タイムゾーンGMT + 3(モスクワ時間)を使用しました。

posix_time_zone xZone( "MSK+3MSD+01,M3.5.0/02:00,M10.5.0/02:00" );

std::cout << "Dailight period in 2009 started at " << xZone.dst_local_start_time(2009) << "\nAnd it will finish at " << xZone.dst_local_end_time(2009);




* This source code was highlighted with Source Code Highlighter .








結論:

2009年のデイライト期間は2009年3月29日02:00:00に開始しました

そして、2009-Oct-25 02:00:00に終了します




boost :: local_time :: tz_databaseは、さまざまなタイムゾーンを格納するための便利なクラスです。 オブジェクトを作成すると、空のデータベースが作成され(もちろん大声で言うと:))、その後add_record()メソッドを使用して手動で入力するか、csv(カンマ区切り値)ファイルから読み取ることができます(多数のレコードを持つそのようなファイルの例) )は、 %boost%\ libs \ date_time \ data \ date_time_zonespec.csvに含まれています

このファイル内の記録形式は、次の標準に準拠する必要があります。
「ID」、「STD ABBR」、「STD NAME」、「DST ABBR」、「DST NAME」、「GMTオフセット」、「DST調整」、「DST開始日ルール」、「開始時刻」、「DST終了日」ルール "、"終了時間 "


どこで:

ID-特定のタイムゾーンを一意に識別する文字列が含まれます。

STD ABBR、STD NAME、DST ABBR、DST NAME-これらのフィールドには、標準および夏時間の名前と略語の行が入力されます。多くの場合、名前と略語は同一です。

GMTオフセット -グリニッジを基準とした時間オフセット。 その形式は次のとおりです。 {+ |-} hh:mm [:ss]

DST調整 -夏時間中のGMTオフセットに対するオフセット 。 形式はGMTオフセットと同じです。

DST開始日ルール - 夏時間の開始を通知する年の日を表す文字列。 また、独自の形式もあります(異なる形式はいくつありますか?):
平日、曜日、月

どこで:

weekday-普通の数字。どのアカウントの日が月にあるかを示します。

曜日 -曜日。

-月。

例:

-1; 0; 3-ロシアの「夏時間」の始まり(3月の最終日曜日)


開始時間 -真夜中以降の「夏時間」が有効になる時間。 形式はGMTオフセットと同じです。

DST終了日ルール - 夏時間の終了を通知する年の日を記述する文字列。 形式はDST開始日ルールと同じです。

終了時間 -「夏時間」の終了のみの開始時間の類似物。

例:

tz_database xDb;

xDb.load_from_file( "G:\\Program files\\boost\\boost_1_39_0\\\libs\\date_time\\data\\date_time_zonespec.csv" );

const std::vector<std:: string >& xAllRegions = xDb.region_list();

std::cout << "Print first 10 zone IDs from the boost time zone file:" << std::endl;

for (std::vector<std:: string >::const_iterator it = xAllRegions.begin(); it != xAllRegions.begin() + 10; ++it)

std::cout << *it << std::endl;

std::cout << "And time when daylight saving was started at 2009: " << xDb.time_zone_from_region( "Europe/Moscow" )->dst_local_start_time(2009) << std::endl;



* This source code was highlighted with Source Code Highlighter .








結論:

ブーストタイムゾーンファイルの最初の10個のゾーンIDを出力します。

アフリカ/アビジャン

アフリカ/アクラ

アフリカ/アディスアベバ

アフリカ/アルジェ

アフリカ/アスメラ

アフリカ/バマコ

アフリカ/バンギ

アフリカ/バンジュル

アフリカ/ビサウ

アフリカ/ブランタイア

そして、2009年に夏時間が開始された時間:2009-Mar-29 02:00:00




boost :: local_time :: custom_time_zoneはタイムゾーンの説明を作成するためのクラスですが、 前述のboost :: local_time :: posix_time_zoneとは異なり、このクラスはタイムゾーンを構築するときに他の4つのクラスを使用します。 クラスは、 time_durationtime_zone_namesdst_adjustment_offsetsおよびdst_calc_ruleです。 クラスは目立ったものによって区別されないため、その使用例を簡単に示します。

time_zone_names xNames( "Moscow Standart Time" , "MST" , "Moscow Daylight Time" , "MDT" );

time_duration xGMTOffset(3, 0, 0);

dst_adjustment_offsets xRulesOffsets( time_duration(1,0,0), time_duration(2,0,0), time_duration(3,0,0) );

//Mak daylight's rule

last_day_of_the_week_in_month xStartRule(Sunday, Mar);

last_day_of_the_week_in_month xEndRule(Sunday, Oct);



boost::shared_ptr<dst_calc_rule> xRules( new last_last_dst_rule(xStartRule, xEndRule) );

custom_time_zone xCustomTimeZone(xNames, xGMTOffset, xRulesOffsets, xRules);



std::cout << "The our time zone name is: " << xCustomTimeZone.std_zone_name() << "\n"

<< "It has an " << xCustomTimeZone.base_utc_offset() << " offset from GMT.\n"

<< "And daylight period will end at " << xCustomTimeZone.dst_local_end_time(2009) <<std::endl;

std::cout << "Posix string which represents our custom_time_zone object is:\n" << xCustomTimeZone.to_posix_string();



* This source code was highlighted with Source Code Highlighter .






結論:

私たちのタイムゾーン名は:Moscow Standart Time

GMTからの03:00:00のオフセットがあります。

また、夏時間は2009年10月25日03:00:00に終了します

custom_time_zoneオブジェクトを表すPosix文字列は次のとおりです。

MST + 03MDT + 01、M3.5.0 / 02:00、M10.5.0 / 03:00


boost :: local_time :: local_date_timeおよびboost :: local_time :: local_time_periodクラスは、 boost :: posix_timeの同様のクラスをタイムゾーンにバインドして繰り返しているため、それらについては検討しません。



便利な機能と結論



Boost.Data_timeには、日付を作成するためのクラスに加えて、次のような便利なユーティリティがあります。 フォーマットされた入力/出力処理およびシリアル化 。 どちらのメカニズムも使用するのは非常に簡単であり、その記事の説明は冗長であると考えているため、非常に膨大であることが判明しました。

結論として、私はこの場所で読書をマスターしたすべての人に感謝したいと思います。また、プロジェクトでBoost.Date_timeを使用して幸運を祈ります。これを使用したことがない人に、この記事が彼らの使用を奨励することを願っています(すでに奨励されています)

PSこの記事を書くのに1ヶ月近くかかりました。もっと頻繁に書くことを望んでいます。 記事で間違いを見つけた場合は、PMでお知らせください。このコメントを詰まらせないでください。






All Articles