#include <iostream> #include <chrono> namespace chrono = std::chrono; using namespace std::chrono_literals; int main() { // 1 chrono::sys_days date1 = 2020y/3/chrono::Sunday[1]; assert(chrono::year_month_day{date1} == 2020y/3/1); // 2 chrono::sys_days date2 = 2020y/3/chrono::Sunday[2]; assert(chrono::year_month_day{date2} == 2020y/3/8); // 3 chrono::sys_days date3 = 2020y/3/chrono::Sunday[0]; assert(chrono::year_month_day{date3} == 2020y/2/23); } Assertion failed the program's No.3 patten. GCC 11 (trunk) returns `30297y/March/14d`. Clang (libc++) is OK. See the specification: > 27.8.16.2 [time.cal.ymwd.members] > If index() is 0 the returned sys_days represents the date 7 days prior to the first weekday() of year()/month().
- #include <iostream> + #include <cassert> #include <cassert> #include <chrono> namespace chrono = std::chrono; using namespace std::chrono_literals; int main() { chrono::sys_days date1 = 2020y/3/chrono::Sunday[1]; assert(chrono::year_month_day{date1} == 2020y/3/1); chrono::sys_days date2 = 2020y/3/chrono::Sunday[2]; assert(chrono::year_month_day{date2} == 2020y/3/8); chrono::sys_days date3 = 2020y/3/chrono::Sunday[0]; assert(chrono::year_month_day{date3} == 2020y/2/23); }
Confirmed.
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:8572edc828f6d1e7c8243f901fe7c96f62a11a8e commit r11-4490-g8572edc828f6d1e7c8243f901fe7c96f62a11a8e Author: Patrick Palka <ppalka@redhat.com> Date: Wed Oct 28 12:28:08 2020 -0400 libstdc++: Fix arithmetic bug in year_month_weekday conversion [PR96713] The conversion function year_month_weekday::operator sys_days computes the offset in days from the first weekday of the month with: days{(index()-1)*7} ^~~~~~~~~~~~~ type 'unsigned' We want the above to yield -7d when index() is 0u, but our 'days' alias is based on long instead of int, so the conversion from unsigned to the underlying type of 'days' instead yields a large positive value. This patch fixes this by casting the result of index() to int so that the initializer is sign-extended in the conversion to long. The added testcase also verifies we do the right thing when index() == 5. libstdc++-v3/ChangeLog: PR libstdc++/96713 * include/std/chrono (year_month_weekday::operator sys_days): Cast the result of index() to int so that the initializer for days{} is sign-extended when it's converted to the underlying type. * testsuite/std/time/year_month_weekday/3.cc: New test.
This should be fixed now, thanks for the report!