Added etl::chrono::year_month

This commit is contained in:
John Wellbelove 2025-04-25 19:21:41 +01:00
parent d604d40648
commit 4485a90c04
9 changed files with 455 additions and 1 deletions

View File

@ -35,6 +35,7 @@ SOFTWARE.
#include "platform.h"
#include "type_traits.h"
#include "integral_limits.h"
#if ETL_NOT_USING_CPP11
#error NOT SUPPORTED FOR C++03 OR BELOW
@ -67,6 +68,7 @@ namespace etl
#include "private/chrono/month_day.h"
#include "private/chrono/month_weekday.h"
#include "private/chrono/year.h"
#include "private/chrono/year_month.h"
#include "private/chrono/hh_mm_ss.h"
#include "private/chrono/operators.h"
#endif

View File

@ -60,6 +60,8 @@ namespace etl
{
public:
ETL_STATIC_ASSERT(etl::chrono::is_duration<TDuration>::value, "TDuration not etl::chrono::duration");
//***********************************************************************
// Fractional width for the duration's subseconds
//***********************************************************************

View File

@ -144,7 +144,7 @@ namespace etl
//***********************************************************************
ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT
{
return (value != -32768);
return (value != etl::integral_limits<int16_t>::min);
}
//***********************************************************************

View File

@ -0,0 +1,233 @@
///\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 year_month
{
public:
//*************************************************************************
/// Default constructor.
//*************************************************************************
year_month()
: y(etl::integral_limits<int16_t>::min)
, m(0)
{
}
//*************************************************************************
/// Construct from month and day.
//*************************************************************************
ETL_CONSTEXPR year_month(const etl::chrono::year& y_, const etl::chrono::month& m_) ETL_NOEXCEPT
: y(y_)
, m(m_)
{
}
//*************************************************************************
/// Returns the year.
//*************************************************************************
ETL_CONSTEXPR etl::chrono::year year() const ETL_NOEXCEPT
{
return y;
}
//*************************************************************************
/// Returns the month.
//*************************************************************************
ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT
{
return m;
}
//*************************************************************************
/// Returns true if the month/day is valid.
//*************************************************************************
ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT
{
return y.ok() && m.ok();
}
//*************************************************************************
/// Adds etl::chrono::years
//*************************************************************************
friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::year_month& ym,
const etl::chrono::years& dy) ETL_NOEXCEPT
{
return etl::chrono::year_month(ym.year() + dy, ym.month());
}
//*************************************************************************
/// Adds etl::chrono::years
//*************************************************************************
friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::years& dy,
const etl::chrono::year_month& ym) ETL_NOEXCEPT
{
return etl::chrono::year_month(ym.year() + dy, ym.month());
}
//*************************************************************************
/// Adds etl::chrono::months
//*************************************************************************
friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::year_month& ym,
const etl::chrono::months& dm) ETL_NOEXCEPT
{
return etl::chrono::year_month(ym.year(), ym.month() + dm);
}
//*************************************************************************
/// Adds etl::chrono::months
//*************************************************************************
friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::months& dm,
const etl::chrono::year_month& ym) ETL_NOEXCEPT
{
return etl::chrono::year_month(ym.year(), ym.month() + dm);
}
//*************************************************************************
/// Subtracts etl::chrono::years
//*************************************************************************
friend ETL_CONSTEXPR14 etl::chrono::year_month operator -(const etl::chrono::year_month& ym,
const etl::chrono::years& dy) ETL_NOEXCEPT
{
return etl::chrono::year_month(ym.year() - dy, ym.month());
}
//*************************************************************************
/// Subtracts etl::chrono::months
//*************************************************************************
friend ETL_CONSTEXPR14 etl::chrono::year_month operator -(const etl::chrono::year_month& ym,
const etl::chrono::months& dm) ETL_NOEXCEPT
{
return etl::chrono::year_month(ym.year(), ym.month() - dm);
}
//*************************************************************************
/// Subtracts etl::chrono::year_month
//*************************************************************************
friend ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::year_month& ym1,
const etl::chrono::year_month& ym2) ETL_NOEXCEPT
{
return etl::chrono::months(static_cast<int>(((int(ym1.year()) - int(ym2.year())) * 12) + (unsigned(ym1.month()) - unsigned(ym2.month()))));
}
//*************************************************************************
/// Equality operator.
//*************************************************************************
friend ETL_CONSTEXPR bool operator ==(const etl::chrono::year_month& lhs,
const etl::chrono::year_month& rhs) ETL_NOEXCEPT
{
return (lhs.y == rhs.y) && (lhs.m == rhs.m);
}
//*************************************************************************
/// Inequality operator.
//*************************************************************************
friend ETL_CONSTEXPR bool operator !=(const etl::chrono::year_month& lhs,
const etl::chrono::year_month& rhs) ETL_NOEXCEPT
{
return !(lhs == rhs);
}
//***********************************************************************
/// Spaceship operator
//***********************************************************************
#if ETL_USING_CPP20
[[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::year_month& lhs,
const etl::chrono::year_month& rhs) ETL_NOEXCEPT
{
auto cmp = lhs.year()<=> rhs.year();
if (cmp != 0)
{
return cmp;
}
else
{
return lhs.month() <=> rhs.month();
}
}
#endif
//***********************************************************************
/// Compare year_month with another.
/// if month < other.month, returns -1;
/// else if month > other.month, returns 1;
/// else if day < other.day, returns -1;
/// else if day > other.day, returns 1;
/// else returns 0;
//***********************************************************************
ETL_CONSTEXPR14 int compare(const year_month& other) const ETL_NOEXCEPT
{
if (y < other.y) return -1;
if (y > other.y) return 1;
if (m < other.m) return -1;
if (m > other.m) return 1;
return 0;
}
private:
etl::chrono::year y;
etl::chrono::month m;
};
}
//*************************************************************************
/// Hash function for etl::chrono::year_month
//*************************************************************************
#if ETL_USING_8BIT_TYPES
template <>
struct hash<etl::chrono::year_month>
{
size_t operator()(const etl::chrono::year_month& md) const
{
uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int)];
unsigned int y = md.year();
unsigned int m = md.month();
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int));
}
};
#endif
}

View File

@ -70,6 +70,7 @@ add_executable(etl_tests
test_chrono_weekday_indexed.cpp
test_chrono_weekday_last.cpp
test_chrono_year.cpp
test_chrono_year_month.cpp
# test_circular_buffer.cpp
# test_circular_buffer_external_buffer.cpp
# test_circular_iterator.cpp

View File

@ -0,0 +1,64 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Documentation:
Copyright(c) 2025 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"
#include "unit_test_framework.h"
#include "etl/chrono.h"
#include <vector>
#include <algorithm>
// Set to 0 to reference against std::chrono
#define ETL_USING_ETL_CHRONO 1
#if ETL_USING_ETL_CHRONO
#define Chrono etl::chrono
#else
#if ETL_USING_CPP20
#include <chrono>
#define Chrono std::chrono
#else
#error std::chrono not supported
#endif
#endif
namespace
{
SUITE(test_chrono_operators)
{
//*************************************************************************
TEST(test_operator_for_year_month)
{
}
};
}

View File

@ -0,0 +1,144 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Documentation:
Copyright(c) 2024 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"
#include "unit_test_framework.h"
#include "etl/chrono.h"
#include <vector>
#include <algorithm>
// Set to 0 to reference against std::chrono
#define ETL_USING_ETL_CHRONO 1
#if ETL_USING_ETL_CHRONO
#define Chrono etl::chrono
#else
#if ETL_USING_CPP20
#include <chrono>
#define Chrono std::chrono
#else
#error std::chrono not supported
#endif
#endif
namespace
{
SUITE(test_chrono_year_month)
{
//*************************************************************************
TEST(test_default_constructor)
{
Chrono::year_month ym;
CHECK_FALSE(ym.ok()); // Default-constructed year_month is not valid
}
//*************************************************************************
TEST(test_constructor_with_month_and_day)
{
Chrono::year_month ym{Chrono::year(2000), Chrono::January};
CHECK_TRUE(ym.ok()); // Valid year_month
CHECK_EQUAL(2000, (int)ym.year());
CHECK_EQUAL((unsigned)Chrono::January, (unsigned)ym.month());
}
//*************************************************************************
TEST(test_invalid_year_month)
{
Chrono::year_month ym{Chrono::year{32768}, Chrono::January}; // Invalid year
CHECK_FALSE(ym.ok()); // Invalid year_month
}
//*************************************************************************
TEST(test_invalid_month_in_year_month)
{
Chrono::year_month ym{Chrono::year{2000}, Chrono::month{13}}; // Invalid month (13)
CHECK_FALSE(ym.ok()); // Invalid year_month
}
#if ETL_USING_CPP20
//*************************************************************************
TEST(test_year_month_spaceship_operator)
{
Chrono::year_month ym1{Chrono::year(2000), Chrono::January};
Chrono::year_month ym2{Chrono::year(2001), Chrono::February};
Chrono::year_month ym3{Chrono::year(2000), Chrono::January};
CHECK_TRUE((ym1 <=> ym3) == std::strong_ordering::equal);
CHECK_TRUE((ym1 <=> ym2) == std::strong_ordering::less);
CHECK_TRUE((ym2 <=> ym1) == std::strong_ordering::greater);
}
#endif
#if ETL_USING_ETL_CHRONO
//*************************************************************************
TEST(test_year_month_compare)
{
Chrono::year_month ym1{Chrono::year(2000), Chrono::January};
Chrono::year_month ym2{Chrono::year(2001), Chrono::February};
Chrono::year_month ym3{Chrono::year(2000), Chrono::January};
CHECK_TRUE(ym1.compare(ym3) == 0);
CHECK_TRUE(ym1.compare(ym2) == -1);
CHECK_TRUE(ym2.compare(ym1) == 1);
}
#endif
//*************************************************************************
TEST(test_year_month_equality_operator)
{
Chrono::year_month ym1{Chrono::year(2000), Chrono::January};
Chrono::year_month ym2{Chrono::year(2001), Chrono::February};
Chrono::year_month ym3{Chrono::year(2000), Chrono::February};
CHECK_TRUE(ym1 == ym1); // 2000/January
CHECK_FALSE(ym1 == ym2); // 2000/January != 2001/February
CHECK_FALSE(ym1 == ym3); // 2000/January != 2000/February
}
//*************************************************************************
TEST(test_year_month_not_equality_operator)
{
Chrono::year_month ym1{Chrono::year(2000), Chrono::January};
Chrono::year_month ym2{Chrono::year(2001), Chrono::February};
Chrono::year_month ym3{Chrono::year(2000), Chrono::February};
CHECK_FALSE(ym1 != ym1); // 2000/January
CHECK_TRUE(ym1 != ym2); // 2000/January != 2001/February
CHECK_TRUE(ym1 != ym3); // 2000/January != 2000/February
}
};
}

View File

@ -3197,6 +3197,7 @@
<ClInclude Include="..\..\include\etl\private\chrono\operators.h" />
<ClInclude Include="..\..\include\etl\private\chrono\weekday.h" />
<ClInclude Include="..\..\include\etl\private\chrono\year.h" />
<ClInclude Include="..\..\include\etl\private\chrono\year_month.h" />
<ClInclude Include="..\..\include\etl\private\diagnostic_array_bounds_push.h" />
<ClInclude Include="..\..\include\etl\private\diagnostic_cxx_20_compat_push.h" />
<ClInclude Include="..\..\include\etl\private\diagnostic_deprecated_push.h" />
@ -8475,6 +8476,7 @@
<ClCompile Include="..\test_chrono_weekday_indexed.cpp" />
<ClCompile Include="..\test_chrono_weekday_last.cpp" />
<ClCompile Include="..\test_chrono_year.cpp" />
<ClCompile Include="..\test_chrono_year_month.cpp" />
<ClCompile Include="..\test_circular_buffer.cpp" />
<ClCompile Include="..\test_circular_buffer_external_buffer.cpp" />
<ClCompile Include="..\test_circular_iterator.cpp" />

View File

@ -1494,6 +1494,9 @@
<ClInclude Include="..\..\include\etl\private\chrono\hh_mm_ss.h">
<Filter>ETL\Private\chrono</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\private\chrono\year_month.h">
<Filter>ETL\Private\chrono</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test_string_char.cpp">
@ -3545,6 +3548,9 @@
<ClCompile Include="..\syntax_check\tuple.h.t.cpp">
<Filter>Tests\Syntax Checks\Source</Filter>
</ClCompile>
<ClCompile Include="..\test_chrono_year_month.cpp">
<Filter>Tests\Chrono</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">