[libcxx-commits] [libcxx] [libc++][chrono] Fixes year_month year wrapping. (PR #74938)
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Dec 9 08:20:27 PST 2023
https://github.com/mordante created https://github.com/llvm/llvm-project/pull/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
>From 00ef9cd4eaf9328ace6e5d4c3dbf5cc39cb2479b Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Fri, 24 Nov 2023 08:23:01 +0100
Subject: [PATCH] [libc++][chrono] Fixes year_month year wrapping.
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
---
libcxx/include/__chrono/year_month.h | 28 ++++++--
.../plus_minus_equal_month.pass.cpp | 10 +++
.../time.cal.ym.nonmembers/minus.pass.cpp | 9 ++-
.../time.cal.ym.nonmembers/plus.pass.cpp | 30 +++++----
.../plus_minus_equal_month.pass.cpp | 34 ++++++++++
.../time.cal.ymd.nonmembers/plus.pass.cpp | 51 +++++++++------
.../plus_minus_equal_month.pass.cpp | 28 +++++---
.../minus.pass.cpp | 23 ++++---
.../time.cal.ymdlast.nonmembers/plus.pass.cpp | 42 +++++++-----
.../plus_minus_equal_month.pass.cpp | 10 +++
.../time.cal.ymwd.nonmembers/minus.pass.cpp | 32 +++++----
.../time.cal.ymwd.nonmembers/plus.pass.cpp | 61 ++++++++++-------
.../plus_minus_equal_month.pass.cpp | 35 ++++++----
.../minus.pass.cpp | 32 +++++----
.../plus.pass.cpp | 65 +++++++++++--------
15 files changed, 329 insertions(+), 161 deletions(-)
diff --git a/libcxx/include/__chrono/year_month.h b/libcxx/include/__chrono/year_month.h
index f4eea8427fc512..d1657b61015b9f 100644
--- a/libcxx/include/__chrono/year_month.h
+++ b/libcxx/include/__chrono/year_month.h
@@ -36,10 +36,10 @@ class year_month {
: __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 6d1273ead73919..cc9fff83a1cff1 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 5bacee9af7f821..977c566e745ac1 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 315d74b75bbcc1..60747a29714d11 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 f656d8f6cc056c..40db399b110b83 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 27626e40fceb7f..b172cb13845704 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 dfa0f002bfb925..1c084795960162 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 009790a450e9da..22d1acfbe28278 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 4cbc3d1a1994e6..1a4609e761baa7 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 8b49540be3fa2b..6aaab2dbfb31d3 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 2ab3462d7f7d18..5546d34ca22dd0 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 e757d81db4a149..1601e8fecb7a4b 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 10c7902cf2f494..ff52b1466cefa5 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 a0dc7545dc8a5b..6fe2ec3b6606d1 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 7529180d5731b3..560b2fcde05568 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);
}
}
More information about the libcxx-commits
mailing list