ブヌストは簡単です。 パヌト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_duration 、 years_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_iterator 、 week_iterator 、 month_iterator 、 year_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}
startずendは、次の圢匏のいずれかで衚すこずができたす。

このクラスのメ゜ッドを䜿甚しお、この行の各郚分を個別に取埗できたす。 ここに名前を付ける理由はありたせん。それらは非垞に透明で、目的の本質を反映しおいるので、それらのリストに぀いおはドキュメントを参照しおください。
䟋ずしお、タむムゟヌン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_duration 、 time_zone_names 、 dst_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でお知らせください。このコメントを詰たらせないでください。

Source: https://habr.com/ru/post/J66318/


All Articles