C++20 のカレンダーとタイム ゾーン:カレンダーの日付

C++20 の chrono 拡張機能の新しいタイプは、カレンダーの日付です。 C++20 では、カレンダーの日付を作成して操作するためのさまざまな方法が提供されています。

ほぼ 20 のカレンダー関連のデータ型を理解するのにしばらく時間がかかりました。そのため、カレンダーの日付から始めます。前回の投稿「C++20 でのカレンダーとタイムゾーン:時刻」のように、新しい chrono 拡張機能のプロトタイプとして Howard Hinnant の日付ライブラリを使用しています。

カレンダーの日付

暦日は、年、月、日で構成される日付です。したがって、C++20 には特定のデータ型 std::chrono::year_month_day があります。 . C++20 には、さらに多くの機能があります。どちらの表も最初の概要を示しています。

簡単に始めましょう。次のプログラム createCalendar.cpp カレンダー関連の日付を作成するさまざまな方法を示します。

// createCalendar.cpp

#include <iostream>
#include "date.h"
 
int main() {

 std::cout << std::endl;
 
 using namespace date;

 constexpr auto yearMonthDay{year(1940)/month(6)/day(26)}; // (1)
 std::cout << yearMonthDay << " ";
 std::cout << date::year_month_day(1940_y, June, 26_d) << std::endl; // (2)

 std::cout << std::endl;

 constexpr auto yearMonthDayLast{year(2010)/March/last}; // (3)
 std::cout << yearMonthDayLast << " ";
 std::cout << date::year_month_day_last(2010_y, month_day_last(month(3))) << std::endl;

 constexpr auto yearMonthWeekday{year(2020)/March/Thursday[2]}; // (4)
 std::cout << yearMonthWeekday << " ";
 std::cout << date::year_month_weekday(2020_y, month(March), Thursday[2]) << std::endl;

 constexpr auto yearMonthWeekdayLast{year(2010)/March/Monday[last]}; // (5)
 std::cout << yearMonthWeekdayLast << " ";
 std::cout << date::year_month_weekday_last(2010_y, month(March), weekday_last(Monday)) << std::endl;

 std::cout << std::endl;

 constexpr auto day_{day(19)}; // (5)
 std::cout << day_ << " ";
 std::cout << date::day(19) << std::endl;

 constexpr auto month_{month(1)}; // (6)
 std::cout << month_ << " ";
 std::cout << date::month(1) << std::endl;

 constexpr auto year_{year(1988)}; // (7)
 std::cout << year_ << " ";
 std::cout << date::year(1988) << std::endl;

 constexpr auto weekday_{weekday(5)};
 std::cout << weekday_ << " ";
 std::cout << date::weekday(5) << std::endl;
 
 constexpr auto yearMonth{year(1988)/1};
 std::cout << yearMonth << " ";
 std::cout << date::year_month(year(1988), January) << std::endl;
 
 constexpr auto monthDay{10/day(22)};
 std::cout << monthDay << " ";
 std::cout << date::month_day(October, day(22)) << std::endl;

 constexpr auto monthDayLast{June/last};
 std::cout << monthDayLast << " ";
 std::cout << date::month_day_last(month(6)) << std::endl;
 
 constexpr auto monthWeekday{2/Monday[3]};
 std::cout << monthWeekday << " ";
 std::cout << date::month_weekday(February, Monday[3]) << std::endl;
 
 constexpr auto monthWeekDayLast{June/Sunday[last]};
 std::cout << monthWeekDayLast << " ";
 std::cout << date::month_weekday_last(June, weekday_last(Sunday)) << std::endl;

 std::cout << std::endl;

}

カレンダーの日付を作成するには、基本的に 2 つの方法があります。いわゆるかわいい構文を使用できます yearMonthDay{year(1940)/month(6)/day(26)} (1 行目)、または明示的な型 date::year_month_day(1940_y, June, 26_d) を使用できます (2行目)。あなたを圧倒しないように、かわいい構文の説明をこの投稿の次のセクションに延ばします.明示的な型は、日時リテラル 1940_y、26_d、および事前定義された定数 June を使用するため、非常に興味深いものです。 . C++20 では、日付リテラル 1940_y そして 26_d アンダースコアなしで書かれている:1940y26d .これは明らかな部分でした。

行 (3)、行 (4)、および行 (5) は、カレンダーの日付を作成する便利な方法を提供します。

  • 行 (3):2010 年 3 月末日:{year(2010)/March/last} または year_month_day_last(2010_y, month_day_last(month(3))
  • 行 (4):2020 年 3 月の第 2 木曜日:{year(2020)/March/Thursday[2]} または year_month_weekday(2020_y, month(March), Thursday[2])
  • 行 (5):2010 年 3 月の最終月曜日:{year(2010)/March/Monday[last]} または year_month_weekday_last(2010_y, month(March), weekday_last(Monday))

残りのカレンダーの種類は、日 (6 行目)、月 (7 行目)、または年 (8 行目) を表します。これらを組み合わせて、行 (3) から (4) など、完全に指定されたカレンダーの日付の基本構成要素として使用できます。

詳細に入る前に、プログラムの出力を次に示します。

お約束通り、キュートな構文について書かせてください。

かわいい構文

かわいい構文は、カレンダーの日付を指定するオーバーロードされた除算演算子で構成されています。オーバーロードされた演算子は時間リテラルをサポートします (例:2020_y, 31_d ) および定数 (January, February, March, April, May, June, July, August, September, October, November, December ).

cute 構文を使用すると、次の 3 つの年、月、日の組み合わせが可能です。

<オール>
  • 年/月/日
  • 日/月/年
  • 月/日/年
  • これらの組み合わせは、世界中で使用されているものであるため、任意に選択されたものではありません。他の組み合わせは使用できません

    したがって、最初の引数に年、月、または日の型を選択すると、残りの 2 つの引数の型は不要になり、積分が機能します。

    // cuteSyntax.cpp
    
    #include <iostream>
    #include "date.h"
    
    int main() {
    
     std::cout << std::endl;
    
     using namespace date;
    
     constexpr auto yearMonthDay{year(1966)/6/26};
     std::cout << yearMonthDay << std::endl;
    
     constexpr auto dayMonthYear{day(26)/6/1966};
     std::cout << dayMonthYear << std::endl;
    
     constexpr auto monthDayYear{month(6)/26/1966};
     std::cout << monthDayYear << std::endl;
    
     constexpr auto yearDayMonth{year(1966)/month(26)/6}; //(1)
     std::cout << yearDayMonth << std::endl;
    
     std::cout << std::endl;
    
    }
    

    年/日/月の組み合わせ (1 行目) は許可されておらず、ランタイム メッセージが発生します。

    カレンダーの日付 {year(2010)/March/last} を表示したいとします。 2020-03-31 などの読み取り可能な形式で。これは の仕事です local_days または sys_days

    カレンダーの日付の表示

    std::chrono::local_days に感謝 または std::chrono::sys_days 、カレンダーの日付を std::chrono::time_point に変換できます これと同じ日付を表す year_month_day.  std::chrono::sys_days を使用しています 私の例では std::chrono::sys_days std::chrono::system_clock に基づいています .カレンダーの日付を変換してみましょう (行 (3) - 行 (5) から前のプログラム createCalendar.cpp.

    // sysDays.cpp
    
    #include <iostream>
    #include "date.h"
     
    int main() {
    
     std::cout << std::endl;
     
     using namespace date;
    
     constexpr auto yearMonthDayLast{year(2010)/March/last};
     std::cout << "sys_days(yearMonthDayLast): " << sys_days(yearMonthDayLast) << std::endl;
    
     constexpr auto yearMonthWeekday{year(2020)/March/Thursday[2]};
     std::cout << "sys_days(yearMonthWeekday): " << sys_days(yearMonthWeekday) << std::endl;
    
     constexpr auto yearMonthWeekdayLast{year(2010)/March/Monday[last]};
     std::cout << "sys_days(yearMonthWeekdayLast): " << sys_days(yearMonthWeekdayLast) << std::endl;
    
     std::cout << std::endl;
    
     constexpr auto leapDate{year(2012)/February/last}; // (1)
     std::cout << "sys_days(leapDate): " << sys_days(leapDate) << std::endl;
    
     constexpr auto noLeapDate{year(2013)/February/last}; // (2)
     std::cout << "sys_day(noLeapDate): " << sys_days(noLeapDate) << std::endl;
    
     std::cout << std::endl;
    
    } 
    

    std::chrono::last 定数を使用すると、1 か月の日数を簡単に判断できます。その結果、出力は 2012 年がうるう年であることを示していますが、2013 年はそうではありません。

    次は?

    カレンダーの日付が有効かどうかを確認するとき、またはカレンダーの日付に期間を追加するときに、カレンダーの日付の操作は非常に強力になります。