From 40b83654b6d44a8d2775aa06aabe4771384f7522 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sat, 2 Jun 2018 22:56:10 -0400 Subject: [PATCH] [API BREAKING] Remove conversion from weekday to unsigned * There has been a great deal of anguish over the encoding of weekdays: whether [0, 6] maps to [Sunday, Saturday] or [1, 7] maps to [Monday, Sunday]. This commit attempts to address that issue, but will break a small amount of code at compile-time. See below on how to fix that. * The weekday constructor used to accept [0, 6] to represent [Sunday, Saturday]. It now accepts [0, 7] to represent [Sunday, Saturday] with both 0 and 7 mapping to Sunday. * The conversion from weekday to unsigned has been removed. * To convert a weekday to unsigned replace: auto u = unsigned{wd}; with: auto u = (wd - Sunday).count(); This maps [Sunday, Saturday] to [0, 6], which is the C/POSIX mapping. If you prefer the ISO mapping ([Monday, Sunday] -> [1, 7]), then do: auto u = (wd - Monday).count() + 1; --- include/date/date.h | 59 +++++++++++++++++---------------- include/date/iso_week.h | 2 +- test/date_test/weekday.pass.cpp | 5 ++- test/iso_week/weekday.pass.cpp | 2 +- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/include/date/date.h b/include/date/date.h index ee3d6c3..7354c1a 100644 --- a/include/date/date.h +++ b/include/date/date.h @@ -431,7 +431,6 @@ public: CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT; CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT; - CONSTCD11 explicit operator unsigned() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT; @@ -439,6 +438,14 @@ public: private: static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT; + + friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; + friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; + friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const weekday& wd); + friend class weekday_indexed; }; CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; @@ -1765,7 +1772,7 @@ weekday::weekday_from_days(int z) NOEXCEPT CONSTCD11 inline weekday::weekday(unsigned wd) NOEXCEPT - : wd_(static_cast(wd)) + : wd_(static_cast(wd != 7 ? wd : 0)) {} CONSTCD11 @@ -1803,13 +1810,6 @@ weekday::operator-=(const days& d) NOEXCEPT return *this; } -CONSTCD11 -inline -weekday::operator unsigned() const NOEXCEPT -{ - return static_cast(wd_); -} - CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;} CONSTCD11 @@ -1817,7 +1817,7 @@ inline bool operator==(const weekday& x, const weekday& y) NOEXCEPT { - return static_cast(x) == static_cast(y); + return x.wd_ == y.wd_; } CONSTCD11 @@ -1833,8 +1833,9 @@ inline days operator-(const weekday& x, const weekday& y) NOEXCEPT { - auto const diff = static_cast(x) - static_cast(y); - return days{diff <= 6 ? diff : diff + 7}; + auto const wdu = x.wd_ - y.wd_; + auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; + return days{wdu - wk * 7}; } CONSTCD14 @@ -1842,7 +1843,7 @@ inline weekday operator+(const weekday& x, const days& y) NOEXCEPT { - auto const wdu = static_cast(static_cast(x)) + y.count(); + auto const wdu = static_cast(static_cast(x.wd_)) + y.count(); auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; return weekday{static_cast(wdu - wk * 7)}; } @@ -1874,7 +1875,7 @@ operator<<(std::basic_ostream& os, const weekday& wd) os << format(fmt, wd); } else - os << static_cast(wd) << " is not a valid weekday"; + os << static_cast(wd.wd_) << " is not a valid weekday"; return os; } @@ -1939,13 +1940,13 @@ CONSTDATA date::month October{10}; CONSTDATA date::month November{11}; CONSTDATA date::month December{12}; -CONSTDATA date::weekday Sunday{0u}; -CONSTDATA date::weekday Monday{1u}; -CONSTDATA date::weekday Tuesday{2u}; -CONSTDATA date::weekday Wednesday{3u}; -CONSTDATA date::weekday Thursday{4u}; -CONSTDATA date::weekday Friday{5u}; -CONSTDATA date::weekday Saturday{6u}; +CONSTDATA date::weekday Monday{1}; +CONSTDATA date::weekday Tuesday{2}; +CONSTDATA date::weekday Wednesday{3}; +CONSTDATA date::weekday Thursday{4}; +CONSTDATA date::weekday Friday{5}; +CONSTDATA date::weekday Saturday{6}; +CONSTDATA date::weekday Sunday{7}; // weekday_indexed @@ -1975,7 +1976,7 @@ weekday_indexed::ok() const NOEXCEPT CONSTCD11 inline weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT - : wd_(static_cast(static_cast(wd))) + : wd_(static_cast(static_cast(wd.wd_))) , index_(static_cast(index)) {} @@ -4337,11 +4338,11 @@ extract_weekday(std::basic_ostream& os, const fields& f os.setstate(std::ios::failbit); return 7; } - unsigned wd; + weekday wd; if (fds.ymd.ok()) { - wd = static_cast(weekday{fds.ymd}); - if (fds.wd.ok() && wd != static_cast(fds.wd)) + wd = weekday{fds.ymd}; + if (fds.wd.ok() && wd != fds.wd) { // fds.ymd and fds.wd are inconsistent os.setstate(std::ios::failbit); @@ -4349,8 +4350,8 @@ extract_weekday(std::basic_ostream& os, const fields& f } } else - wd = static_cast(fds.wd); - return wd; + wd = fds.wd; + return static_cast((wd - Sunday).count()); } template @@ -7216,8 +7217,8 @@ from_stream(std::basic_istream& is, const CharT* fmt, if (ymd.ok()) { if (wd == not_a_weekday) - wd = static_cast(static_cast(weekday(ymd))); - else if (wd != static_cast(static_cast(weekday(ymd)))) + wd = static_cast((weekday(ymd) - Sunday).count()); + else if (wd != static_cast((weekday(ymd) - Sunday).count())) goto broken; if (!computed) { diff --git a/include/date/iso_week.h b/include/date/iso_week.h index fb6df1b..2b8e4a5 100644 --- a/include/date/iso_week.h +++ b/include/date/iso_week.h @@ -451,7 +451,7 @@ weekday::weekday(unsigned wd) NOEXCEPT CONSTCD11 inline weekday::weekday(date::weekday wd) NOEXCEPT - : wd_(to_iso_encoding(static_cast(wd))) + : wd_((wd-date::Monday).count() + 1) {} CONSTCD11 diff --git a/test/date_test/weekday.pass.cpp b/test/date_test/weekday.pass.cpp index 1a526d0..de31faf 100644 --- a/test/date_test/weekday.pass.cpp +++ b/test/date_test/weekday.pass.cpp @@ -77,11 +77,9 @@ static_assert( std::is_trivially_move_assignable{}, ""); static_assert( std::is_nothrow_constructible{}, ""); static_assert( std::is_nothrow_constructible{}, ""); -static_assert( std::is_nothrow_constructible{}, ""); static_assert(!std::is_convertible{}, ""); static_assert( std::is_convertible{}, ""); static_assert(!std::is_convertible{}, ""); -static_assert(static_cast(date::weekday{1u}) == 1, ""); static_assert( date::weekday{0u}.ok(), ""); static_assert( date::weekday{1u}.ok(), ""); @@ -90,7 +88,8 @@ static_assert( date::weekday{3u}.ok(), ""); static_assert( date::weekday{4u}.ok(), ""); static_assert( date::weekday{5u}.ok(), ""); static_assert( date::weekday{6u}.ok(), ""); -static_assert(!date::weekday{7u}.ok(), ""); +static_assert( date::weekday{7u}.ok(), ""); +static_assert(!date::weekday{8u}.ok(), ""); void test_weekday_arithmetic() diff --git a/test/iso_week/weekday.pass.cpp b/test/iso_week/weekday.pass.cpp index 19908e2..25b3545 100644 --- a/test/iso_week/weekday.pass.cpp +++ b/test/iso_week/weekday.pass.cpp @@ -171,7 +171,7 @@ test_with_date_weekday() auto constexpr d1 = iso_week::sun; static_assert(unsigned{d1} == 7, ""); auto constexpr d2 = date::weekday{d1}; - static_assert(unsigned{d2} == 0, ""); + static_assert(d2 == date::Sunday, ""); auto constexpr d3 = iso_week::weekday{d2}; static_assert(unsigned{d3} == 7, ""); }