diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 0cf26e5b..8972d49e 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -31,9 +31,22 @@ SOFTWARE. #ifndef ETL_CHRONO_INCLUDED #define ETL_CHRONO_INCLUDED -#include "platform.h" +#define ETL_IN_CHRONO_H +#include "platform.h" +#include "hash.h" + +#include + +#include "private/chrono/last_spec.h" #include "private/chrono/duration.h" #include "private/chrono/day.h" +#include "private/chrono/weekday.h" +#include "private/chrono/weekday_indexed.h" +#include "private/chrono/weekday_last.h" +#include "private/chrono/month.h" +#include "private/chrono/year.h" +#undef ETL_IN_CHRONO_H + #endif diff --git a/include/etl/platform.h b/include/etl/platform.h index e66a0e08..361fade2 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -271,6 +271,38 @@ SOFTWARE. #define ETL_HAS_VIRTUAL_MESSAGES 1 #endif +//************************************* +// Indicate if etl::literals::chrono_literals has weekdays (_day) +#if defined(ETL_DISABLE_CHRONO_LITERALS_WEEKDAY) + #define ETL_HAS_CHRONO_LITERALS_DAY 0 +#else + #define ETL_HAS_CHRONO_LITERALS_DAY 1 +#endif + +//************************************* +// Indicate if etl::literals::chrono_literals has weekdays (_weekday) +#if defined(ETL_DISABLE_CHRONO_LITERALS_WEEKDAY) + #define ETL_HAS_CHRONO_LITERALS_WEEKDAY 0 +#else + #define ETL_HAS_CHRONO_LITERALS_WEEKDAY 1 +#endif + +//************************************* +// Indicate if etl::literals::chrono_literals has month (_month) +#if defined(ETL_DISABLE_CHRONO_LITERALS_MONTH) + #define ETL_HAS_CHRONO_LITERALS_MONTH 0 +#else + #define ETL_HAS_CHRONO_LITERALS_MONTH 1 +#endif + +//************************************* +// Indicate if etl::literals::chrono_literals has year (_year) +#if defined(ETL_DISABLE_CHRONO_LITERALS_YEAR) + #define ETL_HAS_CHRONO_LITERALS_YEAR 0 +#else + #define ETL_HAS_CHRONO_LITERALS_YEAR 1 +#endif + //************************************* // The macros below are dependent on the profile. // C++11 @@ -512,6 +544,10 @@ namespace etl static ETL_CONSTANT bool has_mutable_array_view = (ETL_HAS_MUTABLE_ARRAY_VIEW == 1); static ETL_CONSTANT bool has_ideque_repair = (ETL_HAS_IDEQUE_REPAIR == 1); static ETL_CONSTANT bool has_virtual_messages = (ETL_HAS_VIRTUAL_MESSAGES == 1); + static ETL_CONSTANT bool has_chrono_literals_day = (ETL_HAS_CHRONO_LITERALS_DAY == 1); + static ETL_CONSTANT bool has_chrono_literals_weekday = (ETL_HAS_CHRONO_LITERALS_WEEKDAY == 1); + static ETL_CONSTANT bool has_chrono_literals_month = (ETL_HAS_CHRONO_LITERALS_MONTH == 1); + static ETL_CONSTANT bool has_chrono_literals_year = (ETL_HAS_CHRONO_LITERALS_YEAR == 1); // Is... static ETL_CONSTANT bool is_debug_build = (ETL_IS_DEBUG_BUILD == 1); diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index 8079680d..812ef06c 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -28,15 +28,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ -#ifndef ETL_CHRONO_DAY_INCLUDED -#define ETL_CHRONO_DAY_INCLUDED - -#include "../../platform.h" -#include "../../hash.h" - -#include "duration.h" - -#include +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif namespace etl { @@ -50,25 +44,33 @@ namespace etl public: //*********************************************************************** - ETL_CONSTEXPR day() + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR day() ETL_NOEXCEPT : value(0) { } //*********************************************************************** - ETL_CONSTEXPR day(unsigned value_) + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit day(unsigned value_) ETL_NOEXCEPT : value(value_) { } //*********************************************************************** - ETL_CONSTEXPR day(const etl::chrono::day& other) + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR day(const etl::chrono::day& other) ETL_NOEXCEPT : value(other.value) { } //*********************************************************************** - ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::day& rhs) + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::day& rhs) ETL_NOEXCEPT { value = rhs.value; @@ -76,6 +78,7 @@ namespace etl } //*********************************************************************** + /// Pre-increment operator template ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::duration& rhs) { @@ -90,6 +93,8 @@ namespace etl return *this; } + //*********************************************************************** + /// Post-increment operator //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day operator ++(int) ETL_NOEXCEPT { @@ -99,6 +104,8 @@ namespace etl return temp; } + //*********************************************************************** + /// Pre-decrement operator //*********************************************************************** ETL_CONSTEXPR etl::chrono::day& operator --() ETL_NOEXCEPT { @@ -107,6 +114,8 @@ namespace etl return *this; } + //*********************************************************************** + /// Post-decrement operator //*********************************************************************** ETL_CONSTEXPR14 etl::chrono::day operator --(int) ETL_NOEXCEPT { @@ -116,6 +125,8 @@ namespace etl return temp; } + //*********************************************************************** + /// Plus-equals operator adding etl::chrono::days //*********************************************************************** ETL_CONSTEXPR etl::chrono::day& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT { @@ -124,6 +135,8 @@ namespace etl return *this; } + //*********************************************************************** + /// Minus-equals operator subtracting etl::chrono::days //*********************************************************************** ETL_CONSTEXPR etl::chrono::day& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT { @@ -133,24 +146,105 @@ namespace etl } //*********************************************************************** - ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + /// Returns true if the day is within the valid 1 to 31 range + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { return (value >= 1U) && (value <= 31U); } + //*********************************************************************** + /// Conversion operator to unsigned int //*********************************************************************** ETL_CONSTEXPR operator unsigned() const ETL_NOEXCEPT { return static_cast(value); } + //*********************************************************************** + /// The minimum day value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day min() ETL_NOEXCEPT + { + return etl::chrono::day(1); + } + + //*********************************************************************** + /// The maximum day value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day max() ETL_NOEXCEPT + { + return etl::chrono::day(31); + } + private: - unsigned value; + unsigned char value; }; //*********************************************************************** - ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + /// Equality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) == static_cast(d2)); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return !(d1 == d2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) < static_cast(d2)); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) <= static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) > static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) >= static_cast(d2)); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::day& d1, const etl::chrono::day& d2) noexcept + { + return (static_cast(d1) <=> static_cast(d2)); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::days to etl::chrono::day + ///\return etl::chrono::day + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT { etl::chrono::day result(d); @@ -160,7 +254,10 @@ namespace etl } //*********************************************************************** - ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT + /// Add etl::chrono::day to etl::chrono::days + ///\return etl::chrono::day + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT { etl::chrono::day result(d); @@ -170,7 +267,10 @@ namespace etl } //*********************************************************************** - ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + /// Subtract etl::chrono::days from etl::chrono::day + ///\return etl::chrono::day + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT { etl::chrono::day result(d); @@ -180,59 +280,18 @@ namespace etl } //*********************************************************************** - ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + /// Subtract etl::chrono::day from etl::chrono::day + ///\return etl::chrono::days + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { return etl::chrono::days(static_cast(static_cast(d1)) - static_cast(static_cast(d2))); } - - //*********************************************************************** - ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) == static_cast(d2)); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return !(d1 == d2); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator <(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) < static_cast(d2)); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) <= static_cast(d2)); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) > static_cast(d2)); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) >= static_cast(d2)); - } - - //*********************************************************************** -#if ETL_USING_CPP20 - ETL_CONSTEXPR auto operator <=>(const etl::chrono::day& d1, const etl::chrono::day& d2) - { - return (static_cast(d1) <=> static_cast(d2)); - } -#endif } //************************************************************************* - /// Hash function. + /// Hash function for etl::chrono::day //************************************************************************* #if ETL_USING_8BIT_TYPES template <> @@ -249,6 +308,7 @@ namespace etl #endif } +#if ETL_HAS_CHRONO_LITERALS_DAY #if ETL_USING_CPP11 namespace etl { @@ -259,13 +319,12 @@ namespace etl //*********************************************************************** /// Literal for days //*********************************************************************** - ETL_CONSTEXPR etl::chrono::day operator ""_d(unsigned long long d) ETL_NOEXCEPT + constexpr etl::chrono::day operator ""_day(unsigned long long d) noexcept { - return etl::chrono::day(d); + return etl::chrono::day(static_cast(d)); } } } } #endif - -#endif \ No newline at end of file +#endif diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 3e4ec95e..553ba123 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -28,10 +28,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ -#ifndef ETL_CHRONO_DURATION_INCLUDED -#define ETL_CHRONO_DURATION_INCLUDED +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif -#include "../../platform.h" #include "../../ratio.h" #include "../../static_assert.h" #include "../../limits.h" @@ -50,6 +50,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR duration() ETL_NOEXCEPT + : value(0) { } @@ -93,7 +94,7 @@ namespace etl } //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR TValue count() const + ETL_NODISCARD ETL_CONSTEXPR TValue count() const ETL_NOEXCEPT { return value; } @@ -101,7 +102,6 @@ namespace etl private: TValue value; - //TPeriod period; }; //*********************************************************************** @@ -129,7 +129,7 @@ namespace etl /// duration_cast //*********************************************************************** template - ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) + ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT { return TToDuration(); } diff --git a/include/etl/private/chrono/last_spec.h b/include/etl/private/chrono/last_spec.h new file mode 100644 index 00000000..71bda5fe --- /dev/null +++ b/include/etl/private/chrono/last_spec.h @@ -0,0 +1,52 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + struct last_spec + { + ETL_CONSTEXPR explicit last_spec() + { + } + }; + +#if ETL_USING_CPP17 + inline constexpr last_spec last{}; +#else + static ETL_CONSTANT last_spec last{}; +#endif + } +} \ No newline at end of file diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h new file mode 100644 index 00000000..907b5d84 --- /dev/null +++ b/include/etl/private/chrono/month.h @@ -0,0 +1,383 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + class month; + + ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::months& ms, const etl::chrono::month& m) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::month operator -(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT; + + //*********************************************************************** + /// month + //*********************************************************************** + class month + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR month() ETL_NOEXCEPT + : value(0) + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit month(unsigned value_) ETL_NOEXCEPT + : value(value_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR month(const etl::chrono::month& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator =(const etl::chrono::month& rhs) ETL_NOEXCEPT + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + /// Pre-increment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator ++() ETL_NOEXCEPT + { + *this += etl::chrono::months(1); + + return *this; + } + + //*********************************************************************** + /// Post-increment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::month operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::month temp = *this; + + *this += etl::chrono::months(1); + + return temp; + } + + //*********************************************************************** + /// Pre-decrement operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator --() ETL_NOEXCEPT + { + *this -= etl::chrono::months(1); + + return *this; + } + + //*********************************************************************** + /// Post-decrement operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::month operator --(int) ETL_NOEXCEPT + { + etl::chrono::month temp = *this; + + *this -= etl::chrono::months(1); + + return temp; + } + + //*********************************************************************** + /// Plus-equals operator adding etl::chrono::months + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator +=(const etl::chrono::months& ms) ETL_NOEXCEPT + { + *this = *this + ms; + + return *this; + } + + //*********************************************************************** + /// Minus-equals operator subtracting etl::chrono::months + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator -=(const etl::chrono::months& ms) ETL_NOEXCEPT + { + *this = *this - ms; + + return *this; + } + + //*********************************************************************** + /// Returns true if the month is within the valid 1 to 31 range + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value >= 1U) && (value <= 12U); + } + + //*********************************************************************** + /// The minimum month value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month min() ETL_NOEXCEPT + { + return etl::chrono::month(1); + } + + //*********************************************************************** + /// The maximum month value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month max() ETL_NOEXCEPT + { + return etl::chrono::month(12); + } + + //*********************************************************************** + /// Conversion operator to unsigned int + //*********************************************************************** + ETL_CONSTEXPR operator unsigned() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + //*********************************************************************** + /// Normalise to a in-range month + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR void normalise() ETL_NOEXCEPT + { + value = ((value % 12U) == 0U) ? 12U : value; + } + + unsigned char value; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) == static_cast(d2)); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return !(d1 == d2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator <(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) < static_cast(d2)); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) <= static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) > static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) >= static_cast(d2)); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::month& d1, const etl::chrono::month& d2) noexcept + { + return (static_cast(d1) <=> static_cast(d2)); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::months to etl::chrono::month + ///\return etl::chrono::month + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::month operator +(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT + { + unsigned int value = static_cast(m); + + value = value % 12U; + + if (value == 0U) + { + value = 12U; + } + + int delta = ms.count() % 12; + + // Adjust to allow a limited +-11 month delta + value += 11U; + value += delta; + value %= 12U; + ++value; + + return etl::chrono::month(value); + } + + //*********************************************************************** + /// Add etl::chrono::month to etl::chrono::months + ///\return etl::chrono::month + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::months& ms, const etl::chrono::month& m) ETL_NOEXCEPT + { + return m + ms; + } + + //*********************************************************************** + /// Subtract etl::chrono::months from etl::chrono::month + ///\return etl::chrono::month + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month operator -(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT + { + return m + etl::chrono::months(-ms.count()); + } + + //*********************************************************************** + /// Subtract etl::chrono::month from etl::chrono::month + ///\return etl::chrono::months + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::month& m1, const etl::chrono::month& m2) ETL_NOEXCEPT + { + if (m1.ok() && m2.ok()) + { + etl::chrono::months ms(static_cast(static_cast(m1)) - + static_cast(static_cast(m2)) % 12); + + if (m1 == (m2 + ms)) + { + return ms; + } + } + + return etl::chrono::months(); + } + +#if ETL_USING_CPP17 + inline constexpr etl::chrono::month January{ 1 }; + inline constexpr etl::chrono::month February{ 2 }; + inline constexpr etl::chrono::month March{ 3 }; + inline constexpr etl::chrono::month April{ 4 }; + inline constexpr etl::chrono::month May{ 5 }; + inline constexpr etl::chrono::month June{ 6 }; + inline constexpr etl::chrono::month July{ 7 }; + inline constexpr etl::chrono::month August{ 8 }; + inline constexpr etl::chrono::month September{ 9 }; + inline constexpr etl::chrono::month October{ 10 }; + inline constexpr etl::chrono::month November{ 11 }; + inline constexpr etl::chrono::month December{ 12 }; +#else + static ETL_CONSTANT etl::chrono::month January{ 1 }; + static ETL_CONSTANT etl::chrono::month February{ 2 }; + static ETL_CONSTANT etl::chrono::month March{ 3 }; + static ETL_CONSTANT etl::chrono::month April{ 4 }; + static ETL_CONSTANT etl::chrono::month May{ 5 }; + static ETL_CONSTANT etl::chrono::month June{ 6 }; + static ETL_CONSTANT etl::chrono::month July{ 7 }; + static ETL_CONSTANT etl::chrono::month August{ 8 }; + static ETL_CONSTANT etl::chrono::month September{ 9 }; + static ETL_CONSTANT etl::chrono::month October{ 10 }; + static ETL_CONSTANT etl::chrono::month November{ 11 }; + static ETL_CONSTANT etl::chrono::month December{ 12 }; +#endif + } + + //************************************************************************* + /// Hash function for etl::chrono::month + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::month& m) const + { + unsigned value = m; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +#if ETL_HAS_CHRONO_LITERALS_MONTH +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for months + //*********************************************************************** + constexpr etl::chrono::month operator ""_month(unsigned long long m) noexcept + { + return etl::chrono::month(m); + } + } + } +} +#endif +#endif diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h new file mode 100644 index 00000000..aafb8ee0 --- /dev/null +++ b/include/etl/private/chrono/weekday.h @@ -0,0 +1,396 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + class weekday; + class weekday_indexed; + class weekday_last; + struct last_spec; + + ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::days& ds, const etl::chrono::weekday& m) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::weekday operator -(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT; + + //*********************************************************************** + /// weekday + //*********************************************************************** + class weekday + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR weekday() ETL_NOEXCEPT + : value(255U) + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit weekday(unsigned value_) ETL_NOEXCEPT + : value(value_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR weekday(const etl::chrono::weekday& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator =(const etl::chrono::weekday& rhs) ETL_NOEXCEPT + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + /// Pre-increment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator ++() ETL_NOEXCEPT + { + *this += etl::chrono::days(1); + + return *this; + } + + //*********************************************************************** + /// Post-increment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::weekday temp = *this; + + *this += etl::chrono::days(1); + + return temp; + } + + //*********************************************************************** + /// Pre-decrement operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator --() ETL_NOEXCEPT + { + *this -= etl::chrono::days(1); + + return *this; + } + + //*********************************************************************** + /// Post-decrement operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday operator --(int) ETL_NOEXCEPT + { + etl::chrono::weekday temp = *this; + + *this -= etl::chrono::days(1); + + return temp; + } + + //*********************************************************************** + /// Plus-equals operator adding etl::chrono::days + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + *this = *this + ds; + + return *this; + } + + //*********************************************************************** + /// Minus-equals operator subtracting etl::chrono::days + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + *this = *this - ds; + + return *this; + } + + //*********************************************************************** + /// Returns true if the weekday is within the valid 1 to 31 range + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (c_encoding() <= 6U); + } + + //*********************************************************************** + /// The minimum weekday value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday min() ETL_NOEXCEPT + { + return etl::chrono::weekday(0); + } + + //*********************************************************************** + /// The maximum weekday value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday max() ETL_NOEXCEPT + { + return etl::chrono::weekday(6); + } + + //*********************************************************************** + /// Get the C encoding of the weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR unsigned c_encoding() const ETL_NOEXCEPT + { + return (value == 7U) ? 0U : value; + } + + //*********************************************************************** + /// Get the ISO encoding of the weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR unsigned iso_encoding() const ETL_NOEXCEPT + { + return (value == 0U) ? 7U : value; + } + + //*********************************************************************** + /// Index operator from index + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_indexed operator[](unsigned index) const ETL_NOEXCEPT; + + //*********************************************************************** + /// Index operator from etl::chrono::last_spec + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_last operator[](etl::chrono::last_spec) const ETL_NOEXCEPT; + + //*********************************************************************** + /// Returns true if the day is a weekend. + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR14 bool is_weekend() ETL_NOEXCEPT + { + return (c_encoding() == 0U) || (c_encoding() == 6U); + } + + private: + + //*********************************************************************** + /// Normalise to a in-range weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR void normalise() ETL_NOEXCEPT + { + value %= 7U; + } + + unsigned char value; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() == wd2.c_encoding()); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return !(wd1 == wd2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator <(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() < wd2.c_encoding()); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() <= wd2.c_encoding()); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() > wd2.c_encoding()); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() >= wd2.c_encoding()); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) noexcept + { + return (wd1.c_encoding() <=> wd2.c_encoding()); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::days to etl::chrono::weekday + ///\return etl::chrono::weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::weekday operator +(const etl::chrono::weekday& wd, const etl::chrono::days& ds) ETL_NOEXCEPT + { + unsigned int value = wd.c_encoding(); + + value = value % 7U; + + int delta = ds.count() % 7; + + // Adjust to allow a limited +-7 weekday delta + value += 7U; + value += delta; + value %= 7U; + + return etl::chrono::weekday(value); + } + + //*********************************************************************** + /// Add etl::chrono::weekday to etl::chrono::days + ///\return etl::chrono::weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::days& ds, const etl::chrono::weekday& wd) ETL_NOEXCEPT + { + return wd + ds; + } + + //*********************************************************************** + /// Subtract etl::chrono::days from etl::chrono::weekday + ///\return etl::chrono::weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday operator -(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT + { + return m + etl::chrono::days(-ds.count()); + } + + //*********************************************************************** + /// Subtract etl::chrono::weekday from etl::chrono::weekday + ///\return etl::chrono::days + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::days operator -(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + if (wd1.ok() && wd2.ok()) + { + etl::chrono::days ds(static_cast(wd1.c_encoding()) - + static_cast(wd2.c_encoding()) % 12); + + if (wd1 == (wd2 + ds)) + { + return ds; + } + } + + return etl::chrono::days(); + } + +#if ETL_USING_CPP17 + inline constexpr etl::chrono::weekday Sunday{ 0 }; + inline constexpr etl::chrono::weekday Monday{ 1 }; + inline constexpr etl::chrono::weekday Tuesday{ 2 }; + inline constexpr etl::chrono::weekday Wednesday{ 3 }; + inline constexpr etl::chrono::weekday Thursday{ 4 }; + inline constexpr etl::chrono::weekday Friday{ 5 }; + inline constexpr etl::chrono::weekday Saturday{ 6 }; +#else + static ETL_CONSTANT etl::chrono::weekday Sunday{ 0 }; + static ETL_CONSTANT etl::chrono::weekday Monday{ 1 }; + static ETL_CONSTANT etl::chrono::weekday Tuesday{ 2 }; + static ETL_CONSTANT etl::chrono::weekday Wednesday{ 3 }; + static ETL_CONSTANT etl::chrono::weekday Thursday{ 4 }; + static ETL_CONSTANT etl::chrono::weekday Friday{ 5 }; + static ETL_CONSTANT etl::chrono::weekday Saturday{ 6 }; +#endif + } + + //************************************************************************* + /// Hash function for etl::chrono::weekday + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::weekday& wd) const + { + unsigned value = wd.c_encoding(); + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +#if ETL_HAS_CHRONO_LITERALS_WEEKDAY +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for weekdays + //*********************************************************************** + constexpr etl::chrono::weekday operator ""_weekday(unsigned long long m) noexcept + { + return etl::chrono::weekday(m); + } + } + } +} +#endif +#endif diff --git a/include/etl/private/chrono/weekday_indexed.h b/include/etl/private/chrono/weekday_indexed.h new file mode 100644 index 00000000..6c2f37e3 --- /dev/null +++ b/include/etl/private/chrono/weekday_indexed.h @@ -0,0 +1,151 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// weekday_indexed + //*********************************************************************** + class weekday_indexed + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR weekday_indexed() ETL_NOEXCEPT + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR weekday_indexed(const etl::chrono::weekday& wd_, unsigned index_) ETL_NOEXCEPT + : wd(wd_) + , i(index_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR weekday_indexed(const etl::chrono::weekday_indexed& other) ETL_NOEXCEPT + : wd(other.wd) + , i(other.i) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday_indexed& operator =(const etl::chrono::weekday_indexed& rhs) ETL_NOEXCEPT + { + wd = rhs.wd; + i = rhs.i; + + return *this; + } + + //*********************************************************************** + /// Get weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT + { + return wd; + } + + //*********************************************************************** + /// Get index + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR unsigned index() const ETL_NOEXCEPT + { + return i; + } + + //*********************************************************************** + /// Returns true if the weekday and index are valid + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return wd.ok() && (i >= 1U) && (i <= 5); + } + + private: + + etl::chrono::weekday wd; + unsigned i; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday_indexed& wd1, const etl::chrono::weekday_indexed& wd2) ETL_NOEXCEPT + { + return (wd1.weekday() == wd2.weekday()) && + (wd1.index() == wd2.index()); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday_indexed& wd1, const etl::chrono::weekday_indexed& wd2) ETL_NOEXCEPT + { + return !(wd1 == wd2); + } + + //*********************************************************************** + /// weekday index operator from index + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_indexed etl::chrono::weekday::operator[](unsigned index) const ETL_NOEXCEPT + { + return etl::chrono::weekday_indexed(*this, index); + } + } + + //************************************************************************* + /// Hash function for etl::chrono::weekday_indexed + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::weekday_indexed& wdi) const + { + return etl::hash()(wdi.weekday()) ^ etl::hash()(wdi.index()); + } + }; +#endif +} diff --git a/include/etl/private/chrono/weekday_last.h b/include/etl/private/chrono/weekday_last.h new file mode 100644 index 00000000..e61890f9 --- /dev/null +++ b/include/etl/private/chrono/weekday_last.h @@ -0,0 +1,138 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// weekday_last + //*********************************************************************** + class weekday_last + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR weekday_last() ETL_NOEXCEPT + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR weekday_last(const etl::chrono::weekday& wd_) ETL_NOEXCEPT + : wd(wd_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR weekday_last(const etl::chrono::weekday_last& other) ETL_NOEXCEPT + : wd(other.wd) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday_last& operator =(const etl::chrono::weekday_last& rhs) ETL_NOEXCEPT + { + wd = rhs.wd; + + return *this; + } + + //*********************************************************************** + /// Get weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT + { + return wd; + } + + //*********************************************************************** + /// Returns true if the weekday is valid + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return wd.ok(); + } + + private: + + etl::chrono::weekday wd; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday_last& wd1, const etl::chrono::weekday_last& wd2) ETL_NOEXCEPT + { + return (wd1.weekday() == wd2.weekday()); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday_last& wd1, const etl::chrono::weekday_last& wd2) ETL_NOEXCEPT + { + return !(wd1 == wd2); + } + + //*********************************************************************** + /// weekday index operator from index + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_last etl::chrono::weekday::operator[](etl::chrono::last_spec) const ETL_NOEXCEPT + { + return etl::chrono::weekday_last(*this); + } + } + + //************************************************************************* + /// Hash function for etl::chrono::weekday_last + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::weekday_last& wdl) const + { + return etl::hash()(wdl.weekday()); + } + }; +#endif +} diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h new file mode 100644 index 00000000..1b8cb517 --- /dev/null +++ b/include/etl/private/chrono/year.h @@ -0,0 +1,332 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// year + //*********************************************************************** + class year + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR year() ETL_NOEXCEPT + : value(0) + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit year(unsigned value_) ETL_NOEXCEPT + : value(value_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR year(const etl::chrono::year& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator =(const etl::chrono::year& rhs) ETL_NOEXCEPT + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + /// Pre-increment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator ++() ETL_NOEXCEPT + { + ++value; + + return *this; + } + + //*********************************************************************** + /// Post-increment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::year operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::year temp = *this; + ++value; + + return temp; + } + + //*********************************************************************** + /// Pre-decrement operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator --() ETL_NOEXCEPT + { + --value; + + return *this; + } + + //*********************************************************************** + /// Post-decrement operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::year operator --(int) ETL_NOEXCEPT + { + const etl::chrono::year temp = *this; + --value; + + return temp; + } + + //*********************************************************************** + /// Plus-equals operator adding etl::chrono::years + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator +=(const etl::chrono::years& ys) ETL_NOEXCEPT + { + value += static_cast(ys.count()); + + return *this; + } + + //*********************************************************************** + /// Minus-equals operator subtracting etl::chrono::years + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator -=(const etl::chrono::years& ys) ETL_NOEXCEPT + { + value -= static_cast(ys.count()); + + return *this; + } + + //*********************************************************************** + /// Returns true if the year is within the valid -32767 to 32767 range + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value >= -32767) && (value <= 32767); + } + + //*********************************************************************** + /// The minimum year value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year min() ETL_NOEXCEPT + { + return etl::chrono::year(-32767); + } + + //*********************************************************************** + /// The maximum year value for which ok() will return true + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year max() ETL_NOEXCEPT + { + return etl::chrono::year(32767); + } + + //*********************************************************************** + /// Returns true if the year is a leap year + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool is_leap() const ETL_NOEXCEPT + { + return ((value % 4) == 0) && !((value % 400) == 0); + } + + //*********************************************************************** + /// Conversion operator to unsigned int + //*********************************************************************** + ETL_CONSTEXPR operator int() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + int16_t value; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) == static_cast(y2)); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return !(y1 == y2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator <(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) < static_cast(y2)); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) <= static_cast(y2)); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) > static_cast(y2)); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) >= static_cast(y2)); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::year& y1, const etl::chrono::year& y2) noexcept + { + return (static_cast(y1) <=> static_cast(y2)); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::years to etl::chrono::year + ///\return etl::chrono::year + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT + { + etl::chrono::year result(y); + + result += ys; + + return result; + } + + //*********************************************************************** + /// Add etl::chrono::year to etl::chrono::years + ///\return etl::chrono::year + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::years& ys, const etl::chrono::year& y) ETL_NOEXCEPT + { + etl::chrono::year result(y); + + result += ys; + + return result; + } + + //*********************************************************************** + /// Subtract etl::chrono::years from etl::chrono::year + ///\return etl::chrono::year + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year operator -(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT + { + etl::chrono::year result(y); + + result -= ys; + + return result; + } + + //*********************************************************************** + /// Subtract etl::chrono::year from etl::chrono::year + ///\return etl::chrono::years + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::years operator -(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return etl::chrono::years(static_cast(static_cast(y1)) - + static_cast(static_cast(y2))); + } + } + + //************************************************************************* + /// Hash function for etl::chrono::year + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::year& y) const + { + int value = y; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(int)); + } + }; +#endif +} + +#if ETL_HAS_CHRONO_LITERALS_YEAR +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for years + //*********************************************************************** + constexpr etl::chrono::year operator ""_year(unsigned long long y) noexcept + { + return etl::chrono::year(static_cast(y)); + } + } + } +} +#endif +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d152f2d6..12c018ab 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -59,6 +59,9 @@ add_executable(etl_tests test_checksum.cpp test_chrono_day.cpp + test_chrono_weekday.cpp + test_chrono_month.cpp + test_chrono_year.cpp test_circular_buffer.cpp test_circular_buffer_external_buffer.cpp diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp index e6de125c..815cb4f4 100644 --- a/test/test_chrono_day.cpp +++ b/test/test_chrono_day.cpp @@ -37,6 +37,8 @@ SOFTWARE. #include "etl/chrono.h" #include +#include +#include namespace { @@ -156,105 +158,128 @@ namespace //************************************************************************* TEST(test_day_plus_days) { - std::chrono::day std_day(0); - etl::chrono::day day(0); - - std::chrono::days std_days(2); - etl::chrono::days days(2); - - for (int i = 0; i < 128; ++i) + for (int d = 0; d < 256; ++d) { - std_day = std_day + std_days; - day = day + days; + for (int ds = 0; ds < 256; ++ds) + { + std::chrono::day std_day(d); + etl::chrono::day day(d); - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_day = std_day + std_days; + day = day + days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } } } //************************************************************************* TEST(test_days_plus_day) { - std::chrono::day std_day(0); - etl::chrono::day day(0); - - std::chrono::days std_days(2); - etl::chrono::days days(2); - - for (int i = 0; i < 128; ++i) + for (int d = 0; d < 256; ++d) { - std_day = std_days + std_day; - day = days + day; + for (int ds = 0; ds < 256; ++ds) + { + std::chrono::day std_day(d); + etl::chrono::day day(d); - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_day = std_days + std_day; + day = days + day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } } } //************************************************************************* TEST(test_minus_equal_days) { - std::chrono::day std_day(256); - etl::chrono::day day(256); - - std::chrono::days std_days(2); - etl::chrono::days days(2); - - for (int i = 0; i < 128; ++i) + for (int d = 0; d <= 256; ++d) { - std_day -= std_days; - day -= days; + for (int ds = 0; ds <= 256; ++ds) + { + std::chrono::day std_day(d); + etl::chrono::day day(d); - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_day -= std_days; + day -= days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } } } //************************************************************************* TEST(test_day_minus_days) { - std::chrono::day std_day(0); - etl::chrono::day day(0); - - std::chrono::days std_days(2); - etl::chrono::days days(2); - - for (int i = 0; i < 128; ++i) + for (int d = 0; d <= 256; ++d) { - std_day = std_day - std_days; - day = day - days; + for (int ds = 0; ds <= 256; ++ds) + { + std::chrono::day std_day(d); + etl::chrono::day day(d); - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_day = std_day - std_days; + day = day - days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } } } //************************************************************************* TEST(test_day_minus_day) { - for (int i = 1; i < 31; ++i) + for (int d = 0; d < 256; ++d) { - std::chrono::day std_day1(i); - std::chrono::day std_day2(31 - i); + std::chrono::day std_day1(d); + std::chrono::day std_day2(255 - d); - etl::chrono::day day1(i); - etl::chrono::day day2(31 - i); + std::chrono::day day1(d); + std::chrono::day day2(255 - d); - std::chrono::days std_days = std_day1 - std_day2; - etl::chrono::days days = day1 - day2; + auto std_days12 = std_day1 - std_day2; + auto std_days21 = std_day2 - std_day1; - CHECK_EQUAL(std_days.count(), days.count()); + auto days12 = day1 - day2; + auto days21 = day2 - day1; + + CHECK_EQUAL(std_days12.count(), days12.count()); + CHECK_EQUAL(std_days21.count(), days21.count()); } } //************************************************************************* - TEST(test_literal_days) + TEST(test_min_max_day) + { + CHECK_EQUAL(1U, etl::chrono::day::min()); + CHECK_EQUAL(31U, etl::chrono::day::max()); + } + + //************************************************************************* + TEST(test_literal_day) { using namespace std::literals::chrono_literals; using namespace etl::literals::chrono_literals; std::chrono::day std_day = 25d; - etl::chrono::day day = 25_d; + etl::chrono::day day = 25_day; CHECK_EQUAL(std_day.ok(), day.ok()); CHECK_EQUAL(unsigned(std_day), unsigned(day)); @@ -289,15 +314,18 @@ namespace } //************************************************************************* - TEST(test_day_hash) + TEST(test_day_hashes_are_unique) { - etl::chrono::day day(10); + std::vector hashes; - size_t h = 0; - - h = etl::hash()(day); + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::day(i))); + } - CHECK_TRUE(h != 0); + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); } }; } diff --git a/test/test_chrono_month.cpp b/test/test_chrono_month.cpp new file mode 100644 index 00000000..2dcc7187 --- /dev/null +++ b/test/test_chrono_month.cpp @@ -0,0 +1,385 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include +#include + +namespace +{ + SUITE(test_chrono_month) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::month std_month; + etl::chrono::month month; + + CHECK_EQUAL(std_month.ok(), month.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 256; ++i) + { + std::chrono::month std_month(i); + etl::chrono::month month(i); + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::month std_month(0); + etl::chrono::month month(0); + + for (int i = 0; i < 255; ++i) + { + ++std_month; + ++month; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::month std_month(0); + etl::chrono::month month(0); + + for (int i = 0; i < 256; ++i) + { + std::chrono::month std_last_month = std_month++; + etl::chrono::month last_month = month++; + + CHECK_EQUAL(std_last_month.ok(), last_month.ok()); + CHECK_EQUAL(unsigned(std_last_month), unsigned(last_month)); + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::month std_month(255); + etl::chrono::month month(255); + + for (int i = 0; i < 256; ++i) + { + --std_month; + --month; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::month std_month(255); + etl::chrono::month month(255); + + for (int i = 0; i < 256; ++i) + { + std::chrono::month std_last_month = std_month--; + etl::chrono::month last_month = month--; + + CHECK_EQUAL(std_last_month.ok(), last_month.ok()); + CHECK_EQUAL(unsigned(std_last_month), unsigned(last_month)); + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_plus_equal_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month += std_months; + month += months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_month_plus_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month = std_month + std_months; + month = month + months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_months_plus_month) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month = std_months + std_month; + month = months + month; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_minus_equal_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month -= std_months; + month -= months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_month_minus_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month = std_month - std_months; + month = month - months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_month_minus_month) + { + for (int m = 0; m < 256; ++m) + { + std::chrono::month std_month1(m); + std::chrono::month std_month2(255 - m); + + std::chrono::month month1(m); + std::chrono::month month2(255 - m); + + auto std_months12 = std_month1 - std_month2; + auto std_months21 = std_month2 - std_month1; + + auto months12 = month1 - month2; + auto months21 = month2 - month1; + + CHECK_EQUAL(std_months12.count(), months12.count()); + CHECK_EQUAL(std_months21.count(), months21.count()); + } + } + + //************************************************************************* + TEST(test_min_max_month) + { + CHECK_EQUAL(1U, etl::chrono::month::min()); + CHECK_EQUAL(12U, etl::chrono::month::max()); + } + + //************************************************************************* + TEST(test_literal_month) + { + using namespace etl::literals::chrono_literals; + + etl::chrono::month month1 = 1_month; + etl::chrono::month month2 = 2_month; + etl::chrono::month month3 = 3_month; + etl::chrono::month month4 = 4_month; + etl::chrono::month month5 = 5_month; + etl::chrono::month month6 = 6_month; + etl::chrono::month month7 = 7_month; + etl::chrono::month month8 = 8_month; + etl::chrono::month month9 = 9_month; + etl::chrono::month month10 = 10_month; + etl::chrono::month month11 = 11_month; + etl::chrono::month month12 = 12_month; + + CHECK_TRUE(month1.ok()); + CHECK_TRUE(month2.ok()); + CHECK_TRUE(month3.ok()); + CHECK_TRUE(month4.ok()); + CHECK_TRUE(month5.ok()); + CHECK_TRUE(month6.ok()); + CHECK_TRUE(month7.ok()); + CHECK_TRUE(month8.ok()); + CHECK_TRUE(month9.ok()); + CHECK_TRUE(month10.ok()); + CHECK_TRUE(month11.ok()); + CHECK_TRUE(month12.ok()); + + CHECK_EQUAL(1U, unsigned(month1)); + CHECK_EQUAL(2U, unsigned(month2)); + CHECK_EQUAL(3U, unsigned(month3)); + CHECK_EQUAL(4U, unsigned(month4)); + CHECK_EQUAL(5U, unsigned(month5)); + CHECK_EQUAL(6U, unsigned(month6)); + CHECK_EQUAL(7U, unsigned(month7)); + CHECK_EQUAL(8U, unsigned(month8)); + CHECK_EQUAL(9U, unsigned(month9)); + CHECK_EQUAL(10U, unsigned(month10)); + CHECK_EQUAL(11U, unsigned(month11)); + CHECK_EQUAL(12U, unsigned(month12)); + } + + //************************************************************************* + TEST(test_month_comparison_operators) + { + etl::chrono::month month1(1); + etl::chrono::month month2(2); + + CHECK_TRUE(month1 == month1); + CHECK_FALSE(month1 != month1); + CHECK_TRUE(month1 < month2); + CHECK_FALSE(month1 < month1); + CHECK_FALSE(month2 < month1); + CHECK_TRUE(month1 <= month2); + CHECK_TRUE(month1 <= month1); + CHECK_FALSE(month2 <= month1); + CHECK_FALSE(month1 > month2); + CHECK_FALSE(month1 > month1); + CHECK_TRUE(month2 > month1); + CHECK_FALSE(month1 >= month2); + CHECK_TRUE(month1 >= month1); + CHECK_TRUE(month2 >= month1); + +#if ETL_USING_CPP20 + CHECK_TRUE((month1 <=> month1) == 0); + CHECK_TRUE((month1 <=> month2) < 0); + CHECK_TRUE((month2 <=> month1) > 0); +#endif + } + + //************************************************************************* + TEST(test_month_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::month(i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); + } + + //************************************************************************* + TEST(test_month_types) + { + CHECK_EQUAL(static_cast(std::chrono::January), static_cast(etl::chrono::January)); + CHECK_EQUAL(static_cast(std::chrono::February), static_cast(etl::chrono::February)); + CHECK_EQUAL(static_cast(std::chrono::March), static_cast(etl::chrono::March)); + CHECK_EQUAL(static_cast(std::chrono::April), static_cast(etl::chrono::April)); + CHECK_EQUAL(static_cast(std::chrono::May), static_cast(etl::chrono::May)); + CHECK_EQUAL(static_cast(std::chrono::June), static_cast(etl::chrono::June)); + CHECK_EQUAL(static_cast(std::chrono::July), static_cast(etl::chrono::July)); + CHECK_EQUAL(static_cast(std::chrono::August), static_cast(etl::chrono::August)); + CHECK_EQUAL(static_cast(std::chrono::September), static_cast(etl::chrono::September)); + CHECK_EQUAL(static_cast(std::chrono::October), static_cast(etl::chrono::October)); + CHECK_EQUAL(static_cast(std::chrono::November), static_cast(etl::chrono::November)); + CHECK_EQUAL(static_cast(std::chrono::December), static_cast(etl::chrono::December)); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/test_chrono_weekday.cpp b/test/test_chrono_weekday.cpp new file mode 100644 index 00000000..0594ea75 --- /dev/null +++ b/test/test_chrono_weekday.cpp @@ -0,0 +1,386 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include +#include + +namespace +{ + SUITE(test_chrono_weekday) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::weekday std_weekday; + etl::chrono::weekday weekday; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 256U; ++i) + { + std::chrono::weekday std_weekday(i); + etl::chrono::weekday weekday(i); + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + + //************************************************************************* + TEST(test_encodings) + { + std::chrono::weekday std_weekday; + etl::chrono::weekday weekday; + + for (unsigned i = 0U; i < 256; ++i) + { + std_weekday = std::chrono::weekday(i); + weekday = etl::chrono::weekday(i); + + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_EQUAL(std_weekday.iso_encoding(), weekday.iso_encoding()); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::weekday std_weekday(0); + etl::chrono::weekday weekday(0); + + for (int i = 0; i < 255; ++i) + { + ++std_weekday; + ++weekday; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::weekday std_weekday(0); + etl::chrono::weekday weekday(0); + + for (int i = 0; i < 256; ++i) + { + std::chrono::weekday std_last_weekday = std_weekday++; + etl::chrono::weekday last_weekday = weekday++; + + CHECK_EQUAL(std_last_weekday.ok(), last_weekday.ok()); + CHECK_EQUAL(std_last_weekday.c_encoding(), last_weekday.c_encoding()); + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::weekday std_weekday(255); + etl::chrono::weekday weekday(255); + + for (int i = 0; i < 256; ++i) + { + --std_weekday; + --weekday; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::weekday std_weekday(255); + etl::chrono::weekday weekday(255); + + for (int i = 0; i < 256; ++i) + { + std::chrono::weekday std_last_weekday = std_weekday--; + etl::chrono::weekday last_weekday = weekday--; + + CHECK_EQUAL(std_last_weekday.ok(), last_weekday.ok()); + CHECK_EQUAL(std_last_weekday.c_encoding(), last_weekday.c_encoding()); + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + + //************************************************************************* + TEST(test_plus_equal_days) + { + for (int wd = 0; wd <= 6; ++wd) + { + for (int ds = 0; ds <= 14; ++ds) + { + std::chrono::weekday std_weekday(wd); + etl::chrono::weekday weekday(wd); + + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_weekday += std_days; + weekday += days; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + } + + //************************************************************************* + TEST(test_weekday_plus_days) + { + for (int wd = 0; wd <= 6; ++wd) + { + for (int ds = 0; ds <= 14; ++ds) + { + std::chrono::weekday std_weekday(wd); + etl::chrono::weekday weekday(wd); + + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_weekday = std_weekday + std_days; + weekday = weekday + days; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + } + + //************************************************************************* + TEST(test_days_plus_weekday) + { + for (int wd = 0; wd <= 6; ++wd) + { + for (int ds = 0; ds <= 14; ++ds) + { + std::chrono::weekday std_weekday(wd); + etl::chrono::weekday weekday(wd); + + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_weekday = std_days + std_weekday; + weekday = days + weekday; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + } + + //************************************************************************* + TEST(test_minus_equal_days) + { + for (int wd = 0; wd <= 6; ++wd) + { + for (int ds = 0; ds <= 14; ++ds) + { + std::chrono::weekday std_weekday(wd); + etl::chrono::weekday weekday(wd); + + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_weekday -= std_days; + weekday -= days; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + } + + //************************************************************************* + TEST(test_weekday_minus_days) + { + for (int wd = 0; wd <= 6; ++wd) + { + for (int ds = 0; ds <= 14; ++ds) + { + std::chrono::weekday std_weekday(wd); + etl::chrono::weekday weekday(wd); + + std::chrono::days std_days(ds); + etl::chrono::days days(ds); + + std_weekday = std_weekday - std_days; + weekday = weekday - days; + + CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + } + } + } + + //************************************************************************* + TEST(test_weekday_minus_weekday) + { + for (int m = 0; m < 256; ++m) + { + std::chrono::weekday std_weekday1(m); + std::chrono::weekday std_weekday2(255 - m); + + std::chrono::weekday weekday1(m); + std::chrono::weekday weekday2(255 - m); + + auto std_days12 = std_weekday1 - std_weekday2; + auto std_days21 = std_weekday2 - std_weekday1; + + auto days12 = weekday1 - weekday2; + auto days21 = weekday2 - weekday1; + + CHECK_EQUAL(std_days12.count(), days12.count()); + CHECK_EQUAL(std_days21.count(), days21.count()); + } + } + + //************************************************************************* + TEST(test_min_max_weekday) + { + CHECK_EQUAL(etl::chrono::Sunday.c_encoding(), etl::chrono::weekday::min().c_encoding()); + CHECK_EQUAL(etl::chrono::Saturday.c_encoding(), etl::chrono::weekday::max().c_encoding()); + } + + //************************************************************************* + TEST(test_literal_weekday) + { + using namespace etl::literals::chrono_literals; + + etl::chrono::weekday weekday0 = 0_weekday; + etl::chrono::weekday weekday1 = 1_weekday; + etl::chrono::weekday weekday2 = 2_weekday; + etl::chrono::weekday weekday3 = 3_weekday; + etl::chrono::weekday weekday4 = 4_weekday; + etl::chrono::weekday weekday5 = 5_weekday; + etl::chrono::weekday weekday6 = 6_weekday; + + CHECK_TRUE(weekday0.ok()); + CHECK_TRUE(weekday1.ok()); + CHECK_TRUE(weekday2.ok()); + CHECK_TRUE(weekday3.ok()); + CHECK_TRUE(weekday4.ok()); + CHECK_TRUE(weekday5.ok()); + CHECK_TRUE(weekday6.ok()); + + CHECK_EQUAL(0U, weekday0.c_encoding()); + CHECK_EQUAL(1U, weekday1.c_encoding()); + CHECK_EQUAL(2U, weekday2.c_encoding()); + CHECK_EQUAL(3U, weekday3.c_encoding()); + CHECK_EQUAL(4U, weekday4.c_encoding()); + CHECK_EQUAL(5U, weekday5.c_encoding()); + CHECK_EQUAL(6U, weekday6.c_encoding()); + } + + //************************************************************************* + TEST(test_weekday_comparison_operators) + { + etl::chrono::weekday weekday1(1); + etl::chrono::weekday weekday2(2); + + CHECK_TRUE(weekday1 == weekday1); + CHECK_FALSE(weekday1 != weekday1); + CHECK_TRUE(weekday1 < weekday2); + CHECK_FALSE(weekday1 < weekday1); + CHECK_FALSE(weekday2 < weekday1); + CHECK_TRUE(weekday1 <= weekday2); + CHECK_TRUE(weekday1 <= weekday1); + CHECK_FALSE(weekday2 <= weekday1); + CHECK_FALSE(weekday1 > weekday2); + CHECK_FALSE(weekday1 > weekday1); + CHECK_TRUE(weekday2 > weekday1); + CHECK_FALSE(weekday1 >= weekday2); + CHECK_TRUE(weekday1 >= weekday1); + CHECK_TRUE(weekday2 >= weekday1); + +#if ETL_USING_CPP20 + CHECK_TRUE((weekday1 <=> weekday1) == 0); + CHECK_TRUE((weekday1 <=> weekday2) < 0); + CHECK_TRUE((weekday2 <=> weekday1) > 0); +#endif + } + + //************************************************************************* + TEST(test_weekday_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::weekday(i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); + } + + //************************************************************************* + TEST(test_weekday_types) + { + CHECK_EQUAL(static_cast(std::chrono::January), static_cast(etl::chrono::January)); + CHECK_EQUAL(static_cast(std::chrono::February), static_cast(etl::chrono::February)); + CHECK_EQUAL(static_cast(std::chrono::March), static_cast(etl::chrono::March)); + CHECK_EQUAL(static_cast(std::chrono::April), static_cast(etl::chrono::April)); + CHECK_EQUAL(static_cast(std::chrono::May), static_cast(etl::chrono::May)); + CHECK_EQUAL(static_cast(std::chrono::June), static_cast(etl::chrono::June)); + CHECK_EQUAL(static_cast(std::chrono::July), static_cast(etl::chrono::July)); + CHECK_EQUAL(static_cast(std::chrono::August), static_cast(etl::chrono::August)); + CHECK_EQUAL(static_cast(std::chrono::September), static_cast(etl::chrono::September)); + CHECK_EQUAL(static_cast(std::chrono::October), static_cast(etl::chrono::October)); + CHECK_EQUAL(static_cast(std::chrono::November), static_cast(etl::chrono::November)); + CHECK_EQUAL(static_cast(std::chrono::December), static_cast(etl::chrono::December)); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp new file mode 100644 index 00000000..e927668f --- /dev/null +++ b/test/test_chrono_year.cpp @@ -0,0 +1,315 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +namespace +{ + SUITE(test_chrono_year) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::year std_year; + etl::chrono::year year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (int32_t i = -32767; i <= 32767; ++i) + { + std::chrono::year std_year(i); + etl::chrono::year year(i); + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::year std_year(-32767); + etl::chrono::year year(-32767); + + for (int32_t i = 0; i < 65536; ++i) + { + ++std_year; + ++year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::year std_year(-32767); + etl::chrono::year year(-32767); + + for (int32_t i = 0; i < 65536; ++i) + { + std::chrono::year std_last_year = std_year++; + etl::chrono::year last_year = year++; + + CHECK_EQUAL(std_last_year.ok(), last_year.ok()); + CHECK_EQUAL(int(std_last_year), int(last_year)); + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::year std_year(256); + etl::chrono::year year(256); + + for (int i = 0; i < 255; ++i) + { + --std_year; + --year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::year std_year(256); + etl::chrono::year year(256); + + for (int i = 0; i < 255; ++i) + { + std::chrono::year std_last_year = std_year--; + etl::chrono::year last_year = year--; + + CHECK_EQUAL(std_last_year.ok(), last_year.ok()); + CHECK_EQUAL(int(std_last_year), int(last_year)); + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_plus_equal_years) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year += std_years; + year += years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_year_plus_years) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year = std_year + std_years; + year = year + years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_years_plus_year) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year = std_years + std_year; + year = years + year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_minus_equal_years) + { + std::chrono::year std_year(256); + etl::chrono::year year(256); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year -= std_years; + year -= years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_year_minus_years) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year = std_year - std_years; + year = year - years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_year_minus_year) + { + for (int i = 1; i < 31; ++i) + { + std::chrono::year std_year1(i); + std::chrono::year std_year2(31 - i); + + etl::chrono::year year1(i); + etl::chrono::year year2(31 - i); + + std::chrono::years std_years = std_year1 - std_year2; + etl::chrono::years years = year1 - year2; + + CHECK_EQUAL(std_years.count(), years.count()); + } + } + + //************************************************************************* + TEST(test_min_max_year) + { + CHECK_EQUAL(-32767, etl::chrono::year::min()); + CHECK_EQUAL(32767, etl::chrono::year::max()); + } + + //************************************************************************* + TEST(test_literal_year) + { + using namespace std::literals::chrono_literals; + using namespace etl::literals::chrono_literals; + + std::chrono::year std_year = 25y; + etl::chrono::year year = 25_year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + + //************************************************************************* + TEST(test_year_comparison_operators) + { + etl::chrono::year year10(10); + etl::chrono::year year20(20); + + CHECK_TRUE(year10 == year10); + CHECK_FALSE(year10 != year10); + CHECK_TRUE(year10 < year20); + CHECK_FALSE(year10 < year10); + CHECK_FALSE(year20 < year10); + CHECK_TRUE(year10 <= year20); + CHECK_TRUE(year10 <= year10); + CHECK_FALSE(year20 <= year10); + CHECK_FALSE(year10 > year20); + CHECK_FALSE(year10 > year10); + CHECK_TRUE(year20 > year10); + CHECK_FALSE(year10 >= year20); + CHECK_TRUE(year10 >= year10); + CHECK_TRUE(year20 >= year10); + +#if ETL_USING_CPP20 + CHECK_TRUE((year10 <=> year10) == 0); + CHECK_TRUE((year10 <=> year20) < 0); + CHECK_TRUE((year20 <=> year10) > 0); +#endif + } + + //************************************************************************* + TEST(test_year_hashes_are_unique) + { + std::vector hashes; + + for (int32_t i = -32767; i < 32768; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::year(i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(65535U, hashes.size()); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index a75e23c5..c335a411 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3093,6 +3093,13 @@ + + + + + + + @@ -7754,6 +7761,9 @@ + + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 1a3a341a..b2bbfa53 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1380,6 +1380,30 @@ ETL\Utilities + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + ETL\Utilities @@ -2501,6 +2525,15 @@ Tests\Chrono + + Tests\Chrono + + + Tests\Chrono + + + Tests\Chrono + Tests\Syntax Checks\Source