diff options
author | Mark de Wever <koraq@xs4all.nl> | 2023-12-12 19:14:13 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-12 19:14:13 +0100 |
commit | 766bf140ffd6ce420426b80aa2cce0cb0d25ab7d (patch) | |
tree | b7e7c6027c358d0c6e988929a1d21f412203876b | |
parent | 831484efa06bee798e218813cb1890ef108ed519 (diff) | |
download | llvm-766bf140ffd6ce420426b80aa2cce0cb0d25ab7d.zip llvm-766bf140ffd6ce420426b80aa2cce0cb0d25ab7d.tar.gz llvm-766bf140ffd6ce420426b80aa2cce0cb0d25ab7d.tar.bz2 |
[libc++][chrono] Fixes year_month year wrapping. (#74938)
Adding months to a year_month should wrap the year when the month
becomes greater than twelve or less than one.
This fixes the issue for year_month. Other classes with a year and month
do not have this issue. This has been verified and tests are added to
avoid possible regressions.
Also fixes some variable copy-paste errors in the tests.
Fixes https://github.com/llvm/llvm-project/issues/73162
15 files changed, 329 insertions, 161 deletions
diff --git a/libcxx/include/__chrono/year_month.h b/libcxx/include/__chrono/year_month.h index f4eea84..d1657b6 100644 --- a/libcxx/include/__chrono/year_month.h +++ b/libcxx/include/__chrono/year_month.h @@ -36,10 +36,10 @@ public: : __y_{__yval}, __m_{__mval} {} _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m_ += __dm; return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m_ -= __dm; return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const years& __dy) noexcept { this->__y_ += __dy; return *this; } - _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const years& __dy) noexcept { this->__y_ -= __dy; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const months& __dm) noexcept; + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const months& __dm) noexcept; + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const years& __dy) noexcept; + _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const years& __dy) noexcept; _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __m_.ok(); } }; @@ -92,6 +92,26 @@ _LIBCPP_HIDE_FROM_ABI constexpr year_month operator-(const year_month& __lhs, const years& __rhs) noexcept { return __lhs + -__rhs; } +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator+=(const months& __dm) noexcept { + *this = *this + __dm; + return *this; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator-=(const months& __dm) noexcept { + *this = *this - __dm; + return *this; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator+=(const years& __dy) noexcept { + *this = *this + __dy; + return *this; +} + +_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator-=(const years& __dy) noexcept { + *this = *this - __dy; + return *this; +} + } // namespace chrono _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp index 6d1273e..cc9fff8 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp @@ -38,6 +38,16 @@ constexpr bool test() { assert(ym.year() == y); } + { // Test year wrapping + year_month ym{year{2020}, month{4}}; + + ym += months{12}; + assert((ym == year_month{year{2021}, month{4}})); + + ym -= months{12}; + assert((ym == year_month{year{2020}, month{4}})); + } + return true; } diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp index 5bacee9..977c566 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp @@ -46,12 +46,17 @@ constexpr bool test() { { // year_month - months year_month ym{year{1234}, std::chrono::November}; - for (int i = 0; i <= 10; ++i) // TODO test wrap-around - { + for (int i = 0; i <= 10; ++i) { year_month ym1 = ym - months{i}; assert(static_cast<int>(ym1.year()) == 1234); assert(ym1.month() == month(11 - i)); } + // Test the year wraps around. + for (int i = 12; i <= 15; ++i) { + year_month ym1 = ym - months{i}; + assert(static_cast<int>(ym1.year()) == 1233); + assert(ym1.month() == month(11 - i + 12)); + } } { // year_month - year_month diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp index 315d74b..60747a2 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp @@ -29,10 +29,10 @@ #include "test_macros.h" -using year = std::chrono::year; -using years = std::chrono::years; -using month = std::chrono::month; -using months = std::chrono::months; +using year = std::chrono::year; +using years = std::chrono::years; +using month = std::chrono::month; +using months = std::chrono::months; using year_month = std::chrono::year_month; // year_month + years @@ -40,10 +40,8 @@ constexpr bool test_ym_plus_y() { ASSERT_NOEXCEPT(std::declval<year_month>() + std::declval<years>()); ASSERT_NOEXCEPT(std::declval<years>() + std::declval<year_month>()); - ASSERT_SAME_TYPE( - year_month, decltype(std::declval<year_month>() + std::declval<years>())); - ASSERT_SAME_TYPE( - year_month, decltype(std::declval<years>() + std::declval<year_month>())); + ASSERT_SAME_TYPE(year_month, decltype(std::declval<year_month>() + std::declval<years>())); + ASSERT_SAME_TYPE(year_month, decltype(std::declval<years>() + std::declval<year_month>())); year_month ym{year{1234}, std::chrono::January}; for (int i = 0; i <= 10; ++i) { @@ -64,10 +62,17 @@ constexpr bool test_ym_plus_m() { ASSERT_NOEXCEPT(std::declval<year_month>() + std::declval<months>()); ASSERT_NOEXCEPT(std::declval<months>() + std::declval<year_month>()); - ASSERT_SAME_TYPE(year_month, decltype(std::declval<year_month>() + - std::declval<months>())); - ASSERT_SAME_TYPE(year_month, decltype(std::declval<months>() + - std::declval<year_month>())); + ASSERT_SAME_TYPE(year_month, decltype(std::declval<year_month>() + std::declval<months>())); + ASSERT_SAME_TYPE(year_month, decltype(std::declval<months>() + std::declval<year_month>())); + + { + // [time.cal.ym.nonmembers]/4 + // Returns: A year_month value z such that z.ok() && z - ym == dm is true. + year_month ym = {year{1234}, std::chrono::January}; + months dm = months{42}; + year_month z = ym + dm; + assert(z.ok() && z - ym == dm); + } year_month ym{year{1234}, std::chrono::January}; for (int i = 0; i <= 11; ++i) { @@ -89,7 +94,6 @@ constexpr bool test_ym_plus_m() { assert(ym2.month() == month(1 + i % 12)); assert(ym1 == ym2); } - return true; } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp index f656d8f..40db399 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp @@ -42,6 +42,40 @@ constexpr bool test() { assert(static_cast<unsigned>((ymd).month()) == i + 1); } + { // Validate the ok status when the day is not present in the new month. + year_month_day ymd{year{2020}, month{3}, day{31}}; + ymd += months{1}; + assert((ymd == year_month_day{year{2020}, month{4}, day{31}})); + assert(!ymd.ok()); + + ymd -= months{1}; + assert((ymd == year_month_day{year{2020}, month{3}, day{31}})); + assert(ymd.ok()); + } + + { // Validate the ok status when the day becomes present in the new month. + year_month_day ymd{year{2020}, month{4}, day{31}}; + assert(!ymd.ok()); + + ymd += months{1}; + assert((ymd == year_month_day{year{2020}, month{5}, day{31}})); + assert(ymd.ok()); + + ymd -= months{2}; + assert((ymd == year_month_day{year{2020}, month{3}, day{31}})); + assert(ymd.ok()); + } + + { // Test year wrapping + year_month_day ymd{year{2020}, month{4}, day{31}}; + + ymd += months{12}; + assert((ymd == year_month_day{year{2021}, month{4}, day{31}})); + + ymd -= months{12}; + assert((ymd == year_month_day{year{2020}, month{4}, day{31}})); + } + return true; } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp index 27626e4..b172cb1 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp @@ -39,32 +39,43 @@ using year_month_day = std::chrono::year_month_day; constexpr bool test() { { // year_month_day + months year_month_day ym{year{1234}, std::chrono::January, day{12}}; - for (int i = 0; i <= 10; ++i) // TODO test wrap-around - { - year_month_day ym1 = ym + months{i}; - year_month_day ym2 = months{i} + ym; - assert(static_cast<int>(ym1.year()) == 1234); - assert(static_cast<int>(ym2.year()) == 1234); - assert(ym1.month() == month(1 + i)); - assert(ym2.month() == month(1 + i)); - assert(ym1.day() == day{12}); - assert(ym2.day() == day{12}); - assert(ym1 == ym2); + for (int i = 0; i <= 10; ++i) { + year_month_day ymd1 = ym + months{i}; + year_month_day ymd2 = months{i} + ym; + assert(static_cast<int>(ymd1.year()) == 1234); + assert(static_cast<int>(ymd2.year()) == 1234); + assert(ymd1.month() == month(1 + i)); + assert(ymd2.month() == month(1 + i)); + assert(ymd1.day() == day{12}); + assert(ymd2.day() == day{12}); + assert(ymd1 == ymd2); + } + // Test the year wraps around. + for (int i = 12; i <= 15; ++i) { + year_month_day ymd1 = ym + months{i}; + year_month_day ymd2 = months{i} + ym; + assert(static_cast<int>(ymd1.year()) == 1235); + assert(static_cast<int>(ymd2.year()) == 1235); + assert(ymd1.month() == month(1 + i - 12)); + assert(ymd2.month() == month(1 + i - 12)); + assert(ymd1.day() == day{12}); + assert(ymd2.day() == day{12}); + assert(ymd1 == ymd2); } } { // year_month_day + years year_month_day ym{year{1234}, std::chrono::January, day{12}}; for (int i = 0; i <= 10; ++i) { - year_month_day ym1 = ym + years{i}; - year_month_day ym2 = years{i} + ym; - assert(static_cast<int>(ym1.year()) == i + 1234); - assert(static_cast<int>(ym2.year()) == i + 1234); - assert(ym1.month() == std::chrono::January); - assert(ym2.month() == std::chrono::January); - assert(ym1.day() == day{12}); - assert(ym2.day() == day{12}); - assert(ym1 == ym2); + year_month_day ymd1 = ym + years{i}; + year_month_day ymd2 = years{i} + ym; + assert(static_cast<int>(ymd1.year()) == i + 1234); + assert(static_cast<int>(ymd2.year()) == i + 1234); + assert(ymd1.month() == std::chrono::January); + assert(ymd2.month() == std::chrono::January); + assert(ymd1.day() == day{12}); + assert(ymd2.day() == day{12}); + assert(ymd1 == ymd2); } } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp index dfa0f00..1c08479 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp @@ -29,15 +29,25 @@ constexpr bool test() { for (unsigned i = 0; i <= 10; ++i) { year y{1234}; month_day_last mdl{month{i}}; - year_month_day_last ym(y, mdl); - assert(static_cast<unsigned>((ym += months{2}).month()) == i + 2); - assert(ym.year() == y); - assert(static_cast<unsigned>((ym).month()) == i + 2); - assert(ym.year() == y); - assert(static_cast<unsigned>((ym -= months{1}).month()) == i + 1); - assert(ym.year() == y); - assert(static_cast<unsigned>((ym).month()) == i + 1); - assert(ym.year() == y); + year_month_day_last ymdl(y, mdl); + assert(static_cast<unsigned>((ymdl += months{2}).month()) == i + 2); + assert(ymdl.year() == y); + assert(static_cast<unsigned>((ymdl).month()) == i + 2); + assert(ymdl.year() == y); + assert(static_cast<unsigned>((ymdl -= months{1}).month()) == i + 1); + assert(ymdl.year() == y); + assert(static_cast<unsigned>((ymdl).month()) == i + 1); + assert(ymdl.year() == y); + } + + { // Test year wrapping + year_month_day_last ymdl{year{2020}, month_day_last{month{4}}}; + + ymdl += months{12}; + assert((ymdl == year_month_day_last{year{2021}, month_day_last{month{4}}})); + + ymdl -= months{12}; + assert((ymdl == year_month_day_last{year{2020}, month_day_last{month{4}}})); } return true; diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp index 009790a..22d1acf 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp @@ -38,22 +38,27 @@ constexpr bool test() { { // year_month_day_last - years - year_month_day_last ym{year{1234}, month_day_last{December}}; + year_month_day_last ymdl{year{1234}, month_day_last{December}}; for (int i = 0; i <= 10; ++i) { - year_month_day_last ym1 = ym - years{i}; - assert(static_cast<int>(ym1.year()) == 1234 - i); - assert(ym1.month() == December); + year_month_day_last ymdl1 = ymdl - years{i}; + assert(static_cast<int>(ymdl1.year()) == 1234 - i); + assert(ymdl1.month() == December); } } { // year_month_day_last - months - // TODO test wrapping - year_month_day_last ym{year{1234}, month_day_last{December}}; + year_month_day_last ymdl{year{1234}, month_day_last{December}}; for (unsigned i = 0; i <= 10; ++i) { - year_month_day_last ym1 = ym - months{i}; - assert(static_cast<int>(ym1.year()) == 1234); - assert(static_cast<unsigned>(ym1.month()) == 12U - i); + year_month_day_last ymdl1 = ymdl - months{i}; + assert(static_cast<int>(ymdl1.year()) == 1234); + assert(static_cast<unsigned>(ymdl1.month()) == 12U - i); + } + // Test the year wraps around. + for (unsigned i = 12; i <= 15; ++i) { + year_month_day_last ymdl1 = ymdl - months{i}; + assert(static_cast<int>(ymdl1.year()) == 1233); + assert(static_cast<unsigned>(ymdl1.month()) == 12U - i + 12); } } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp index 4cbc3d1..1a4609e 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp @@ -49,29 +49,37 @@ constexpr bool test() { { // year_month_day_last + months year_month_day_last ym{year{1234}, month_day_last{January}}; - for (int i = 0; i <= 10; ++i) // TODO test wrap-around - { - year_month_day_last ym1 = ym + months{i}; - year_month_day_last ym2 = months{i} + ym; - assert(static_cast<int>(ym1.year()) == 1234); - assert(static_cast<int>(ym2.year()) == 1234); - assert(ym1.month() == month(1 + i)); - assert(ym2.month() == month(1 + i)); - assert(ym1 == ym2); + for (int i = 0; i <= 10; ++i) { + year_month_day_last ymdl1 = ym + months{i}; + year_month_day_last ymdl2 = months{i} + ym; + assert(static_cast<int>(ymdl1.year()) == 1234); + assert(static_cast<int>(ymdl2.year()) == 1234); + assert(ymdl1.month() == month(1 + i)); + assert(ymdl2.month() == month(1 + i)); + assert(ymdl1 == ymdl2); + } + // Test the year wraps around. + for (int i = 12; i <= 15; ++i) { + year_month_day_last ymdl1 = ym + months{i}; + year_month_day_last ymdl2 = months{i} + ym; + assert(static_cast<int>(ymdl1.year()) == 1235); + assert(static_cast<int>(ymdl2.year()) == 1235); + assert(ymdl1.month() == month(1 + i - 12)); + assert(ymdl2.month() == month(1 + i - 12)); + assert(ymdl1 == ymdl2); } } { // year_month_day_last + years - year_month_day_last ym{year{1234}, month_day_last{January}}; for (int i = 0; i <= 10; ++i) { - year_month_day_last ym1 = ym + years{i}; - year_month_day_last ym2 = years{i} + ym; - assert(static_cast<int>(ym1.year()) == i + 1234); - assert(static_cast<int>(ym2.year()) == i + 1234); - assert(ym1.month() == std::chrono::January); - assert(ym2.month() == std::chrono::January); - assert(ym1 == ym2); + year_month_day_last ymdl1 = ym + years{i}; + year_month_day_last ymdl2 = years{i} + ym; + assert(static_cast<int>(ymdl1.year()) == i + 1234); + assert(static_cast<int>(ymdl2.year()) == i + 1234); + assert(ymdl1.month() == std::chrono::January); + assert(ymdl2.month() == std::chrono::January); + assert(ymdl1 == ymdl2); } } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp index 8b49540..6aaab2d 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp @@ -54,6 +54,16 @@ constexpr bool test() { assert(ymwd.index() == 2); } + { // Test year wrapping + year_month_weekday ymwd{year{2020}, month{4}, weekday_indexed{Tuesday, 2}}; + + ymwd += months{12}; + assert((ymwd == year_month_weekday{year{2021}, month{4}, weekday_indexed{Tuesday, 2}})); + + ymwd -= months{12}; + assert((ymwd == year_month_weekday{year{2020}, month{4}, weekday_indexed{Tuesday, 2}})); + } + return true; } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp index 2ab3462..5546d34 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp @@ -35,24 +35,32 @@ constexpr bool test() { constexpr weekday Tuesday = std::chrono::Tuesday; { // year_month_weekday - years - year_month_weekday ym{year{1234}, November, weekday_indexed{Tuesday, 1}}; + year_month_weekday ymwd{year{1234}, November, weekday_indexed{Tuesday, 1}}; for (int i = 0; i <= 10; ++i) { - year_month_weekday ym1 = ym - years{i}; - assert(static_cast<int>(ym1.year()) == 1234 - i); - assert(ym1.month() == November); - assert(ym1.weekday() == Tuesday); - assert(ym1.index() == 1); + year_month_weekday ymwd1 = ymwd - years{i}; + assert(static_cast<int>(ymwd1.year()) == 1234 - i); + assert(ymwd1.month() == November); + assert(ymwd1.weekday() == Tuesday); + assert(ymwd1.index() == 1); } } { // year_month_weekday - months - year_month_weekday ym{year{1234}, November, weekday_indexed{Tuesday, 2}}; + year_month_weekday ymwd{year{1234}, November, weekday_indexed{Tuesday, 2}}; for (unsigned i = 1; i <= 10; ++i) { - year_month_weekday ym1 = ym - months{i}; - assert(ym1.year() == year{1234}); - assert(ym1.month() == month{11 - i}); - assert(ym1.weekday() == Tuesday); - assert(ym1.index() == 2); + year_month_weekday ymwd1 = ymwd - months{i}; + assert(ymwd1.year() == year{1234}); + assert(ymwd1.month() == month{11 - i}); + assert(ymwd1.weekday() == Tuesday); + assert(ymwd1.index() == 2); + } + // Test the year wraps around. + for (unsigned i = 12; i <= 15; ++i) { + year_month_weekday ymwd1 = ymwd - months{i}; + assert(ymwd1.year() == year{1233}); + assert(ymwd1.month() == month{11 - i + 12}); + assert(ymwd1.weekday() == Tuesday); + assert(ymwd1.index() == 2); } } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/plus.pass.cpp index e757d81..1601e8f 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/plus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/plus.pass.cpp @@ -43,36 +43,49 @@ constexpr bool test() { { // year_month_weekday + months (and switched) year_month_weekday ym{year{1234}, January, weekday_indexed{Tuesday, 3}}; - for (int i = 0; i <= 10; ++i) // TODO test wrap-around - { - year_month_weekday ym1 = ym + months{i}; - year_month_weekday ym2 = months{i} + ym; - assert(static_cast<int>(ym1.year()) == 1234); - assert(static_cast<int>(ym2.year()) == 1234); - assert(ym1.month() == month(1 + i)); - assert(ym2.month() == month(1 + i)); - assert(ym1.weekday() == Tuesday); - assert(ym2.weekday() == Tuesday); - assert(ym1.index() == 3); - assert(ym2.index() == 3); - assert(ym1 == ym2); + for (int i = 0; i <= 10; ++i) { + year_month_weekday ymwd1 = ym + months{i}; + year_month_weekday ymwd2 = months{i} + ym; + assert(static_cast<int>(ymwd1.year()) == 1234); + assert(static_cast<int>(ymwd2.year()) == 1234); + assert(ymwd1.month() == month(1 + i)); + assert(ymwd2.month() == month(1 + i)); + assert(ymwd1.weekday() == Tuesday); + assert(ymwd2.weekday() == Tuesday); + assert(ymwd1.index() == 3); + assert(ymwd2.index() == 3); + assert(ymwd1 == ymwd2); + } + // Test the year wraps around. + for (int i = 12; i <= 15; ++i) { + year_month_weekday ymwd1 = ym + months{i}; + year_month_weekday ymwd2 = months{i} + ym; + assert(static_cast<int>(ymwd1.year()) == 1235); + assert(static_cast<int>(ymwd2.year()) == 1235); + assert(ymwd1.month() == month(1 + i - 12)); + assert(ymwd2.month() == month(1 + i - 12)); + assert(ymwd1.weekday() == Tuesday); + assert(ymwd2.weekday() == Tuesday); + assert(ymwd1.index() == 3); + assert(ymwd2.index() == 3); + assert(ymwd1 == ymwd2); } } { // year_month_weekday + years (and switched) year_month_weekday ym{year{1234}, std::chrono::January, weekday_indexed{Tuesday, 3}}; for (int i = 0; i <= 10; ++i) { - year_month_weekday ym1 = ym + years{i}; - year_month_weekday ym2 = years{i} + ym; - assert(static_cast<int>(ym1.year()) == i + 1234); - assert(static_cast<int>(ym2.year()) == i + 1234); - assert(ym1.month() == January); - assert(ym2.month() == January); - assert(ym1.weekday() == Tuesday); - assert(ym2.weekday() == Tuesday); - assert(ym1.index() == 3); - assert(ym2.index() == 3); - assert(ym1 == ym2); + year_month_weekday ymwd1 = ym + years{i}; + year_month_weekday ymwd2 = years{i} + ym; + assert(static_cast<int>(ymwd1.year()) == i + 1234); + assert(static_cast<int>(ymwd2.year()) == i + 1234); + assert(ymwd1.month() == January); + assert(ymwd2.month() == January); + assert(ymwd1.weekday() == Tuesday); + assert(ymwd2.weekday() == Tuesday); + assert(ymwd1.index() == 3); + assert(ymwd2.index() == 3); + assert(ymwd1 == ymwd2); } } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/plus_minus_equal_month.pass.cpp index 10c7902..ff52b14 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/plus_minus_equal_month.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/plus_minus_equal_month.pass.cpp @@ -31,25 +31,34 @@ constexpr bool test() { for (unsigned i = 0; i <= 10; ++i) { year y{1234}; - year_month_weekday_last ymwd(y, month{i}, weekday_last{Tuesday}); + year_month_weekday_last ymwdl(y, month{i}, weekday_last{Tuesday}); - assert(static_cast<unsigned>((ymwd += months{2}).month()) == i + 2); - assert(ymwd.year() == y); - assert(ymwd.weekday() == Tuesday); + assert(static_cast<unsigned>((ymwdl += months{2}).month()) == i + 2); + assert(ymwdl.year() == y); + assert(ymwdl.weekday() == Tuesday); - assert(static_cast<unsigned>((ymwd).month()) == i + 2); - assert(ymwd.year() == y); - assert(ymwd.weekday() == Tuesday); + assert(static_cast<unsigned>((ymwdl).month()) == i + 2); + assert(ymwdl.year() == y); + assert(ymwdl.weekday() == Tuesday); - assert(static_cast<unsigned>((ymwd -= months{1}).month()) == i + 1); - assert(ymwd.year() == y); - assert(ymwd.weekday() == Tuesday); + assert(static_cast<unsigned>((ymwdl -= months{1}).month()) == i + 1); + assert(ymwdl.year() == y); + assert(ymwdl.weekday() == Tuesday); - assert(static_cast<unsigned>((ymwd).month()) == i + 1); - assert(ymwd.year() == y); - assert(ymwd.weekday() == Tuesday); + assert(static_cast<unsigned>((ymwdl).month()) == i + 1); + assert(ymwdl.year() == y); + assert(ymwdl.weekday() == Tuesday); } + { // Test year wrapping + year_month_weekday_last ymwdl{year{2020}, month{4}, weekday_last{Tuesday}}; + + ymwdl += months{12}; + assert((ymwdl == year_month_weekday_last{year{2021}, month{4}, weekday_last{Tuesday}})); + + ymwdl -= months{12}; + assert((ymwdl == year_month_weekday_last{year{2020}, month{4}, weekday_last{Tuesday}})); + } return true; } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/minus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/minus.pass.cpp index a0dc754..6fe2ec3 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/minus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/minus.pass.cpp @@ -35,24 +35,32 @@ constexpr bool test() { constexpr weekday Tuesday = std::chrono::Tuesday; { // year_month_weekday_last - years - year_month_weekday_last ym{year{1234}, October, weekday_last{Tuesday}}; + year_month_weekday_last ymwdl{year{1234}, October, weekday_last{Tuesday}}; for (int i = 0; i <= 10; ++i) { - year_month_weekday_last ym1 = ym - years{i}; - assert(ym1.year() == year{1234 - i}); - assert(ym1.month() == October); - assert(ym1.weekday() == Tuesday); - assert(ym1.weekday_last() == weekday_last{Tuesday}); + year_month_weekday_last ymwdl1 = ymwdl - years{i}; + assert(ymwdl1.year() == year{1234 - i}); + assert(ymwdl1.month() == October); + assert(ymwdl1.weekday() == Tuesday); + assert(ymwdl1.weekday_last() == weekday_last{Tuesday}); } } { // year_month_weekday_last - months - year_month_weekday_last ym{year{1234}, October, weekday_last{Tuesday}}; + year_month_weekday_last ymwdl{year{1234}, October, weekday_last{Tuesday}}; for (unsigned i = 0; i < 10; ++i) { - year_month_weekday_last ym1 = ym - months{i}; - assert(ym1.year() == year{1234}); - assert(ym1.month() == month{10 - i}); - assert(ym1.weekday() == Tuesday); - assert(ym1.weekday_last() == weekday_last{Tuesday}); + year_month_weekday_last ymwdl1 = ymwdl - months{i}; + assert(ymwdl1.year() == year{1234}); + assert(ymwdl1.month() == month{10 - i}); + assert(ymwdl1.weekday() == Tuesday); + assert(ymwdl1.weekday_last() == weekday_last{Tuesday}); + } + // Test the year wraps around. + for (unsigned i = 12; i < 15; ++i) { + year_month_weekday_last ymwdl1 = ymwdl - months{i}; + assert(ymwdl1.year() == year{1233}); + assert(ymwdl1.month() == month{10 - i + 12}); + assert(ymwdl1.weekday() == Tuesday); + assert(ymwdl1.weekday_last() == weekday_last{Tuesday}); } } diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/plus.pass.cpp index 7529180..560b2fc 100644 --- a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/plus.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/plus.pass.cpp @@ -41,37 +41,50 @@ constexpr bool test() { constexpr month January = std::chrono::January; { // year_month_weekday_last + months - year_month_weekday_last ym{year{1234}, January, weekday_last{Tuesday}}; - for (int i = 0; i <= 10; ++i) // TODO test wrap-around - { - year_month_weekday_last ym1 = ym + months{i}; - year_month_weekday_last ym2 = months{i} + ym; - assert(ym1.year() == year(1234)); - assert(ym2.year() == year(1234)); - assert(ym1.month() == month(1 + i)); - assert(ym2.month() == month(1 + i)); - assert(ym1.weekday() == Tuesday); - assert(ym2.weekday() == Tuesday); - assert(ym1.weekday_last() == weekday_last{Tuesday}); - assert(ym2.weekday_last() == weekday_last{Tuesday}); - assert(ym1 == ym2); + year_month_weekday_last ymwdl{year{1234}, January, weekday_last{Tuesday}}; + for (int i = 0; i <= 10; ++i) { + year_month_weekday_last ymwdl1 = ymwdl + months{i}; + year_month_weekday_last ymwdl2 = months{i} + ymwdl; + assert(ymwdl1.year() == year{1234}); + assert(ymwdl2.year() == year{1234}); + assert(ymwdl1.month() == month(1 + i)); + assert(ymwdl2.month() == month(1 + i)); + assert(ymwdl1.weekday() == Tuesday); + assert(ymwdl2.weekday() == Tuesday); + assert(ymwdl1.weekday_last() == weekday_last{Tuesday}); + assert(ymwdl2.weekday_last() == weekday_last{Tuesday}); + assert(ymwdl1 == ymwdl2); + } + // Test the year wraps around. + for (int i = 12; i <= 15; ++i) { + year_month_weekday_last ymwdl1 = ymwdl + months{i}; + year_month_weekday_last ymwdl2 = months{i} + ymwdl; + assert(ymwdl1.year() == year{1235}); + assert(ymwdl2.year() == year{1235}); + assert(ymwdl1.month() == month(1 + i - 12)); + assert(ymwdl2.month() == month(1 + i - 12)); + assert(ymwdl1.weekday() == Tuesday); + assert(ymwdl2.weekday() == Tuesday); + assert(ymwdl1.weekday_last() == weekday_last{Tuesday}); + assert(ymwdl2.weekday_last() == weekday_last{Tuesday}); + assert(ymwdl1 == ymwdl2); } } { // year_month_weekday_last + years - year_month_weekday_last ym{year{1234}, std::chrono::January, weekday_last{Tuesday}}; + year_month_weekday_last ymwdl{year{1234}, std::chrono::January, weekday_last{Tuesday}}; for (int i = 0; i <= 10; ++i) { - year_month_weekday_last ym1 = ym + years{i}; - year_month_weekday_last ym2 = years{i} + ym; - assert(ym1.year() == year(1234 + i)); - assert(ym2.year() == year(1234 + i)); - assert(ym1.month() == January); - assert(ym2.month() == January); - assert(ym1.weekday() == Tuesday); - assert(ym2.weekday() == Tuesday); - assert(ym1.weekday_last() == weekday_last{Tuesday}); - assert(ym2.weekday_last() == weekday_last{Tuesday}); - assert(ym1 == ym2); + year_month_weekday_last ymwdl1 = ymwdl + years{i}; + year_month_weekday_last ymwdl2 = years{i} + ymwdl; + assert(ymwdl1.year() == year(1234 + i)); + assert(ymwdl2.year() == year(1234 + i)); + assert(ymwdl1.month() == January); + assert(ymwdl2.month() == January); + assert(ymwdl1.weekday() == Tuesday); + assert(ymwdl2.weekday() == Tuesday); + assert(ymwdl1.weekday_last() == weekday_last{Tuesday}); + assert(ymwdl2.weekday_last() == weekday_last{Tuesday}); + assert(ymwdl1 == ymwdl2); } } |