{"id":28137,"date":"2021-06-01T19:27:27","date_gmt":"2021-06-01T19:27:27","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=28137"},"modified":"2021-06-01T19:27:27","modified_gmt":"2021-06-01T19:27:27","slug":"cpp20s-extensions-to-chrono-available-in-visual-studio-2019-version-16-10","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/cpp20s-extensions-to-chrono-available-in-visual-studio-2019-version-16-10\/","title":{"rendered":"C++20&#8217;s Extensions to Chrono Available in Visual Studio 2019 version 16.10"},"content":{"rendered":"<p>While the <code>&lt;chrono&gt;<\/code> header has been available as part of the STL since C++11, among the changes included in C++20 there were several extensions to chrono including support for calendrical types, time zones, leap seconds, and integration with format. A great deal of innovation and work was required in order to complete these additional features; shipping these new C++20 additions so soon would not have been possible without the amazing support of the open-source community. In particular, I would like to recognize the significant contributions from <a href=\"https:\/\/github.com\/MattStephanson\">Matt Stephanson<\/a>, <a href=\"https:\/\/github.com\/statementreply\">statementreply<\/a>, and <a href=\"https:\/\/github.com\/SuperWig\">Daniel Marshall<\/a> in helping complete our implementation.<\/p>\n<h2>Overview &amp; Examples<\/h2>\n<p>There were numerous additions to the <code>&lt;chrono&gt;<\/code> header in the changes for C++20, and here I\u2019d like to highlight a few.<\/p>\n<h2>Calendrical Types<\/h2>\n<p>The PR <a href=\"https:\/\/github.com\/microsoft\/STL\/pull\/323\">GH-323: &lt;chrono&gt; Partially implement P0355R7<\/a>, authored by Daniel Marshall added a long list of new calendrical types to the header for date support. For example:<\/p>\n<pre class=\"prettyprint\">#include &lt;chrono&gt;\r\nusing namespace std::chrono;\r\n\r\nint main() {\r\n   year y{2021};\r\n   year_month_day world_bee_day = May\/20d\/y;\r\n   month_weekday mwd = May\/Thurs[3];\r\n   year_month_weekday world_bee_day2 = 2021\/mwd;\r\n}<\/pre>\n<p>Here we create a <code>year<\/code> object for the year 2021, then use it to create a <code>year_month_day<\/code> object representing May 20, 2021 or World Bee Day. We then use an alternate form to represent the exact same day by making a <code>month_weekday<\/code> object representing the third Thursday of May (indicated with the <code>Thurs[3]<\/code> which is creating a <code>weekday_indexed<\/code> object) in an unspecified year, and then using that to create a <code>year_month_weekday<\/code> object by combining It with the integer <code>2021<\/code> which is interpreted as the year.<\/p>\n<p>You can see that the library now includes a variety of different calendrical types that allow users to create dates in a variety of different ways. These different forms of dates are intended to be very easy-to-use and intuitive, so that users can choose the method most comfortable or natural to them.<\/p>\n<h2>Time Zones<\/h2>\n<p>Awareness of time zones were another significant addition to the <code>&lt;chrono&gt;<\/code> header, which included new types (e.g., <code>time_zone<\/code>, <code>tzdb<\/code>, <code>zoned_time<\/code>) as well as significant consideration for how to manage the data that library\u2019s newfound time-zone-awareness would require. A small example displaying an example of the new time zone feature follows:<\/p>\n<pre class=\"prettyprint\">#include &lt;chrono&gt;\r\nusing namespace std::chrono;\r\n\r\nint main() {\r\n   const auto&amp; my_tzdb = get_tzdb();\r\n   const time_zone* la_tz = my_tzdb.locate_zone(\"America\/Los_Angeles\");\r\n   auto world_nutella_day = local_days{2021y\/Feb\/5};\r\n   zoned_time la_nutella_day{la_tz, world_nutella_day + 3h + 44min + 12s};\r\n   zoned_time utc_nutella_day{\"Etc\/UTC\", la_nutella_day};\r\n}<\/pre>\n<p><span style=\"font-size: 1rem;\">This is only a small example of the functionalities included in newly-added time zone support. The feature also supports converting between different time zones, notions of \u201clocal\u201d time, and possibilities of ambiguous or nonexistent conversions to\/from time zones due to daylight savings transitions.\u00a0 <\/span>In this example, we first attain a reference to the most up-to-date <code>tzdb<\/code> object which contains data about time zones. We then use it to look up the America\/Los Angeles time zone (GMT-07:00) by name, storing a <code>time_zone<\/code> pointer pointing to that entry in the <code>tzdb<\/code>. Next we create a specific date (corresponding to World Nutella Day) using <code>local_days<\/code> and some of the calendrical types mentioned above, which we can then use to create a <code>zoned_time<\/code> object which pairs a specific date\/time (in this case World Nutella Day at 03:44:12) with a given time zone (America\/Los Angeles in this case).\u00a0 We then use the America\/Los Angeles <code>zoned_time<\/code> to create a <code>zoned_time<\/code> corresponding to UTC time, illustrating the time zone conversion functionality.<\/p>\n<p>One specific challenge that we encountered in our implementation was how to actually access the data that the time zones required. The C++20 Standard defines the time zone functionality in terms of the <a href=\"https:\/\/www.iana.org\/time-zones\">IANA database<\/a>, however MSVC\u2019s STL would not be able to ship the entire database with its implementation due to its size and the issue of how to provide updates to it. We had to explore alternate options as we pondered how to support this Standard-mandated feature without subjecting our customers to absurd header size increases. We eventually discovered the <a href=\"https:\/\/unicode-org.github.io\/icu\/userguide\/datetime\/\">ICU<\/a> library which <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/intl\/international-components-for-unicode--icu-\">ships as part of the Windows 10 operating system<\/a> in more recent versions (19H1 and after) and derives its data from the IANA database itself. As a result, updates to the time zone data will be executed along with updates to the OS through Windows Update. While our current implementation relies on the availability of the ICU DLL in more recent OS versions, we have plans to <a href=\"https:\/\/github.com\/microsoft\/STL\/issues\/1911\">revisit the issue<\/a> and investigate implementing a fallback for older operating systems. While there are a few discrepancies between the IANA database and the ICU library, the data should largely be the same.<\/p>\n<h2>Leap Seconds<\/h2>\n<p>Our recent changes also include support for tracking leap seconds, largely implemented in MattStephanson\u2019s <a href=\"https:\/\/github.com\/microsoft\/STL\/pull\/1671\">GH-1671: C++20 clocks, clock_cast, tzdb::leap_seconds<\/a>, with valuable input from statementreply. With this new support, you can ask whether a given time occurs during a leap second insertion or removal (fun fact, both <a href=\"https:\/\/en.wikipedia.org\/wiki\/Leap_second\">positive <em>and<\/em> negative leap seconds<\/a> are possible!) or not. C++20 also added several new clock types (in addition to <code>system_clock<\/code>, <code>steady_clock<\/code>, and <code>high_resolution_clock<\/code> which have existed since C++11), some of them leap-second-aware (such as <code>utc_clock<\/code>) while others are not (such as <code>system_clock<\/code>). We detect new leap seconds through Windows registries (with the guidance of <a href=\"https:\/\/techcommunity.microsoft.com\/t5\/networking-blog\/leap-seconds-for-the-it-pro-what-you-need-to-know\/ba-p\/339811\">Dan Cuomo\u2019s networking blogpost<\/a>), so any new leap seconds will need to be detected through Windows updates as well.<\/p>\n<h2>\u201cChronat\u201d<\/h2>\n<p>The intersection of <code>chrono<\/code> and <code>std::format<\/code>, lovingly dubbed \u201cchronat\u201d in our repo, brings two of C++20\u2019s largest features together. \u201cChronat\u201d includes both parsing and formatting for <code>chrono<\/code>\u2019s new types with format specifiers \/ parse flags that are for the most part analogous to <code>strftime<\/code>\u2019s formatting codes. For the formatting side, there are <code>struct formatter<\/code> specializations for almost every new type added to chrono, allowing it to seamlessly integrate with <code>std::format<\/code>\u2019s interface. See Charlie Barto\u2019s blogpost for more information about <code>std::format<\/code>. A brief example of <code>chrono<\/code>\u2019s parsing and formatting follows:<\/p>\n<pre class=\"prettyprint\">#include &lt;chrono&gt;\r\n#include &lt;sstream&gt;\r\n#include &lt;string&gt;\r\nusing namespace std;\r\nusing namespace std::chrono;\r\n\r\nint main() {\r\n   day d;\r\n   basic_stringstream&lt;char&gt; sstr{\"22\"};\r\n   basic_string&lt;char&gt; s{\"%d\"};\r\n   sstr &gt;&gt; parse(s, d);\r\n   cout &lt;&lt; d &lt;&lt; \"\\n\";\r\n\r\n   year_month_day programmers_day{January\/7d\/2021};\r\n   cout &lt;&lt; format(\"International Programmer\u2019s day: {%F}\", programmers_day);\r\n}<\/pre>\n<p>We first have an example where we parse a <code>stringstream<\/code> into a <code>day<\/code> which can then be output to <code>std::cout<\/code>, then we also see an example where we use the <code>\"%F\"<\/code> format specifier and <code>std::format<\/code> and nicely format a <code>year_month_day<\/code> object to <code>std::cout<\/code> as well.<\/p>\n<h2>Implementing in the Open<\/h2>\n<p>Given the magnitude of the feature, we used several tools to help the maintainers and the community organize and track the work that needed to be done. The additions to the <code>&lt;chrono&gt;<\/code> header were tracked through the feature\u2019s <a href=\"https:\/\/github.com\/microsoft\/STL\/issues\/12\">GitHub issue<\/a>, and work was organized through the <a href=\"https:\/\/github.com\/microsoft\/STL\/projects\/7\">Extensions to &lt;chrono&gt;<\/a> GitHub project and the <a href=\"https:\/\/github.com\/microsoft\/STL\/issues\/1704\">Tracking Issue<\/a>. You can read more about the changes in code required for the feature and specific considerations we had to account for during implementation there.<\/p>\n<h2>Give it a try!<\/h2>\n<p>This has been a moderately brief overview of the extensions to <code>&lt;chrono&gt;<\/code> included in C++20, but there has been much more added to the header than has been covered here. These features are available for public consumption under <code>\/std:c++latest<\/code> as of Visual Studio 2019 version 10 Previews 3, 4, and GA. I encourage you to use them to implement all of your wildest calendar-, time-zone-, and leap-second-related dreams and let us know what you think!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While the &lt;chrono&gt; header has been available as part of the STL since C++11, among the changes included in C++20 there were several extensions to chrono including support for calendrical types, time zones, leap seconds, and integration with format. A great deal of innovation and work was required in order to complete these additional features; [&hellip;]<\/p>\n","protected":false},"author":26194,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[270,1],"tags":[],"class_list":["post-28137","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-announcement","category-cplusplus"],"acf":[],"blog_post_summary":"<p>While the &lt;chrono&gt; header has been available as part of the STL since C++11, among the changes included in C++20 there were several extensions to chrono including support for calendrical types, time zones, leap seconds, and integration with format. A great deal of innovation and work was required in order to complete these additional features; [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/28137","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/26194"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=28137"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/28137\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=28137"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=28137"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=28137"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}