Add missing interfaces to etl::chrono (#1489)

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
Roland Reichwein 2026-07-07 21:00:09 +02:00 committed by GitHub
parent c52b2ac7b1
commit dca6653b37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 468 additions and 1 deletions

View File

@ -135,4 +135,49 @@ ETL_NOEXCEPT
```
A specialisation of absolute for `etl::chrono::duration`.
**Return**
The absolute duration value.
The absolute duration value.
## 12/24 hour functions
```cpp
ETL_NODISCARD
inline ETL_CONSTEXPR14
bool is_am(const etl::chrono::hours& h)
ETL_NOEXCEPT
```
**Description**
Returns `true` if `h` is in the range [0h, 11h] (an am hour).
---
```cpp
ETL_NODISCARD
inline ETL_CONSTEXPR14
bool is_pm(const etl::chrono::hours& h)
ETL_NOEXCEPT
```
**Description**
Returns `true` if `h` is in the range [12h, 23h] (a pm hour).
---
```cpp
ETL_NODISCARD
inline ETL_CONSTEXPR14
etl::chrono::hours make12(const etl::chrono::hours& h)
ETL_NOEXCEPT
```
**Description**
Returns the 12-hour equivalent of `h` in the range [1h, 12h].
If `h` is not in the range [0h, 23h], the value returned is unspecified.
---
```cpp
ETL_NODISCARD
inline ETL_CONSTEXPR14
etl::chrono::hours make24(const etl::chrono::hours& h, bool is_pm)
ETL_NOEXCEPT
```
**Description**
Returns the 24-hour equivalent of `h`, which is assumed to represent the hour with the indicated am/pm.
If `h` is not in the range [1h, 12h], the value returned is unspecified.

View File

@ -100,6 +100,41 @@ ETL_NOEXCEPT
**Description**
Subtracts a duration.
## Increment/decrement
```cpp
ETL_CONSTEXPR14 time_point& operator ++()
ETL_NOEXCEPT
```
**Description**
Pre-increments the stored duration by one tick.
---
```cpp
ETL_CONSTEXPR14 time_point operator ++(int)
ETL_NOEXCEPT
```
**Description**
Post-increments the stored duration by one tick.
---
```cpp
ETL_CONSTEXPR14 time_point& operator --()
ETL_NOEXCEPT
```
**Description**
Pre-decrements the stored duration by one tick.
---
```cpp
ETL_CONSTEXPR14 time_point operator --(int)
ETL_NOEXCEPT
```
**Description**
Post-decrements the stored duration by one tick.
## Constants
```cpp
ETL_NODISCARD
@ -180,6 +215,65 @@ If time_point < other, returns -1
else if time_point > other, returns 1
else returns 0
## Non-member mathematical operators
```cpp
template <typename TClock, typename TDuration1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14
etl::chrono::time_point<TClock, typename etl::common_type<TDuration1, etl::chrono::duration<TRep2, TPeriod2> >::type>
operator +(const time_point<TClock, TDuration1>& lhs,
const etl::chrono::duration<TRep2, TPeriod2>& rhs)
ETL_NOEXCEPT
```
**Description**
Adds a duration to a time_point.
**Return**
A time_point whose duration is the common type of the two.
---
```cpp
template <typename TRep1, typename TPeriod1, typename TClock, typename TDuration2>
ETL_CONSTEXPR14
etl::chrono::time_point<TClock, typename etl::common_type<etl::chrono::duration<TRep1, TPeriod1>, TDuration2>::type>
operator +(const etl::chrono::duration<TRep1, TPeriod1>& lhs,
const time_point<TClock, TDuration2>& rhs)
ETL_NOEXCEPT
```
**Description**
Adds a duration to a time_point.
**Return**
A time_point whose duration is the common type of the two.
---
```cpp
template <typename TClock, typename TDuration1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14
etl::chrono::time_point<TClock, typename etl::common_type<TDuration1, etl::chrono::duration<TRep2, TPeriod2> >::type>
operator -(const time_point<TClock, TDuration1>& lhs,
const etl::chrono::duration<TRep2, TPeriod2>& rhs)
ETL_NOEXCEPT
```
**Description**
Subtracts a duration from a time_point.
**Return**
A time_point whose duration is the common type of the two.
---
```cpp
template <typename TClock, typename TDuration1, typename TDuration2>
ETL_CONSTEXPR14
typename etl::common_type<TDuration1, TDuration2>::type
operator -(const time_point<TClock, TDuration1>& lhs,
const time_point<TClock, TDuration2>& rhs)
ETL_NOEXCEPT
```
**Description**
Subtracts one time_point from another.
**Return**
The duration between them as the common type of the two durations.
## Non-member comparison operators
```cpp
template <typename TClock, typename TDuration1, typename TDuration2>

View File

@ -184,5 +184,64 @@ namespace etl
template <typename TDuration>
constexpr int etl::chrono::hh_mm_ss<TDuration>::fractional_width;
//***********************************************************************
/// 12/24 hours functions
//***********************************************************************
//***********************************************************************
/// Returns true if h is in the range [0h, 11h] (an am hour).
//***********************************************************************
ETL_NODISCARD
inline ETL_CONSTEXPR14 bool is_am(const etl::chrono::hours& h) ETL_NOEXCEPT
{
return (h >= etl::chrono::hours(0)) && (h <= etl::chrono::hours(11));
}
//***********************************************************************
/// Returns true if h is in the range [12h, 23h] (a pm hour).
//***********************************************************************
ETL_NODISCARD
inline ETL_CONSTEXPR14 bool is_pm(const etl::chrono::hours& h) ETL_NOEXCEPT
{
return (h >= etl::chrono::hours(12)) && (h <= etl::chrono::hours(23));
}
//***********************************************************************
/// Returns the 12-hour equivalent of h in the range [1h, 12h].
/// If h is not in the range [0h, 23h], the value returned is unspecified.
//***********************************************************************
ETL_NODISCARD
inline ETL_CONSTEXPR14 etl::chrono::hours make12(const etl::chrono::hours& h) ETL_NOEXCEPT
{
if (h == etl::chrono::hours(0))
{
return etl::chrono::hours(12);
}
else if (h > etl::chrono::hours(12))
{
return h - etl::chrono::hours(12);
}
return h;
}
//***********************************************************************
/// Returns the 24-hour equivalent of h, which is assumed to represent the
/// hour with the indicated am/pm.
/// If h is not in the range [1h, 12h], the value returned is unspecified.
//***********************************************************************
ETL_NODISCARD
inline ETL_CONSTEXPR14 etl::chrono::hours make24(const etl::chrono::hours& h, bool is_pm) ETL_NOEXCEPT
{
if (is_pm)
{
return (h == etl::chrono::hours(12)) ? h : (h + etl::chrono::hours(12));
}
else
{
return (h == etl::chrono::hours(12)) ? etl::chrono::hours(0) : h;
}
}
} // namespace chrono
} // namespace etl

View File

@ -122,6 +122,48 @@ namespace etl
return *this;
}
//***************************************************************************
/// Pre-increments the stored duration by one tick.
//***************************************************************************
ETL_CONSTEXPR14 time_point& operator++() ETL_NOEXCEPT
{
++dur;
return *this;
}
//***************************************************************************
/// Post-increments the stored duration by one tick.
//***************************************************************************
ETL_CONSTEXPR14 time_point operator++(int) ETL_NOEXCEPT
{
time_point temp(*this);
++dur;
return temp;
}
//***************************************************************************
/// Pre-decrements the stored duration by one tick.
//***************************************************************************
ETL_CONSTEXPR14 time_point& operator--() ETL_NOEXCEPT
{
--dur;
return *this;
}
//***************************************************************************
/// Post-decrements the stored duration by one tick.
//***************************************************************************
ETL_CONSTEXPR14 time_point operator--(int) ETL_NOEXCEPT
{
time_point temp(*this);
--dur;
return temp;
}
//***************************************************************************
/// Returns a time_point with the smallest possible duration.
//***************************************************************************
@ -200,6 +242,59 @@ namespace etl
return etl::chrono::time_point<TClock, TToDuration>(dur);
}
//***************************************************************************
/// Adds a duration to a time_point.
/// Returns a time_point whose duration is the common type of the two.
//***************************************************************************
template <typename TClock, typename TDuration1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 etl::chrono::time_point<TClock, typename etl::common_type<TDuration1, etl::chrono::duration<TRep2, TPeriod2> >::type>
operator+(const time_point<TClock, TDuration1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs) ETL_NOEXCEPT
{
using common_duration = typename etl::common_type<TDuration1, etl::chrono::duration<TRep2, TPeriod2> >::type;
using result_time_point = etl::chrono::time_point<TClock, common_duration>;
return result_time_point(lhs.time_since_epoch() + rhs);
}
//***************************************************************************
/// Adds a time_point to a duration.
/// Returns a time_point whose duration is the common type of the two.
//***************************************************************************
template <typename TRep1, typename TPeriod1, typename TClock, typename TDuration2>
ETL_CONSTEXPR14 etl::chrono::time_point<TClock, typename etl::common_type<etl::chrono::duration<TRep1, TPeriod1>, TDuration2>::type>
operator+(const etl::chrono::duration<TRep1, TPeriod1>& lhs, const time_point<TClock, TDuration2>& rhs) ETL_NOEXCEPT
{
using common_duration = typename etl::common_type<etl::chrono::duration<TRep1, TPeriod1>, TDuration2>::type;
using result_time_point = etl::chrono::time_point<TClock, common_duration>;
return result_time_point(lhs + rhs.time_since_epoch());
}
//***************************************************************************
/// Subtracts a duration from a time_point.
/// Returns a time_point whose duration is the common type of the two.
//***************************************************************************
template <typename TClock, typename TDuration1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 etl::chrono::time_point<TClock, typename etl::common_type<TDuration1, etl::chrono::duration<TRep2, TPeriod2> >::type>
operator-(const time_point<TClock, TDuration1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs) ETL_NOEXCEPT
{
using common_duration = typename etl::common_type<TDuration1, etl::chrono::duration<TRep2, TPeriod2> >::type;
using result_time_point = etl::chrono::time_point<TClock, common_duration>;
return result_time_point(lhs.time_since_epoch() - rhs);
}
//***************************************************************************
/// Subtracts one time_point from another.
/// Returns the duration between them as the common type of the two durations.
//***************************************************************************
template <typename TClock, typename TDuration1, typename TDuration2>
ETL_CONSTEXPR14 typename etl::common_type<TDuration1, TDuration2>::type operator-(const time_point<TClock, TDuration1>& lhs,
const time_point<TClock, TDuration2>& rhs) ETL_NOEXCEPT
{
return lhs.time_since_epoch() - rhs.time_since_epoch();
}
//***************************************************************************
/// Equality operator
//***************************************************************************

View File

@ -286,5 +286,86 @@ namespace
CHECK_EQUAL(0, time.fractional_width);
CHECK_TRUE((std::is_same<duration_type, Chrono::hh_mm_ss<duration_type>::precision>::value));
}
//*************************************************************************
TEST(test_is_am)
{
for (int h = 0; h <= 11; ++h)
{
CHECK_TRUE(Chrono::is_am(Chrono::hours(h)));
}
for (int h = 12; h <= 23; ++h)
{
CHECK_FALSE(Chrono::is_am(Chrono::hours(h)));
}
}
//*************************************************************************
TEST(test_is_pm)
{
for (int h = 0; h <= 11; ++h)
{
CHECK_FALSE(Chrono::is_pm(Chrono::hours(h)));
}
for (int h = 12; h <= 23; ++h)
{
CHECK_TRUE(Chrono::is_pm(Chrono::hours(h)));
}
}
//*************************************************************************
TEST(test_make12)
{
// Midnight (0h) maps to 12h.
CHECK_EQUAL(12, Chrono::make12(Chrono::hours(0)).count());
// 1h..12h are unchanged.
for (int h = 1; h <= 12; ++h)
{
CHECK_EQUAL(h, Chrono::make12(Chrono::hours(h)).count());
}
// 13h..23h map to 1h..11h.
for (int h = 13; h <= 23; ++h)
{
CHECK_EQUAL(h - 12, Chrono::make12(Chrono::hours(h)).count());
}
}
//*************************************************************************
TEST(test_make24)
{
// am: 12h maps to 0h, 1h..11h are unchanged.
CHECK_EQUAL(0, Chrono::make24(Chrono::hours(12), false).count());
for (int h = 1; h <= 11; ++h)
{
CHECK_EQUAL(h, Chrono::make24(Chrono::hours(h), false).count());
}
// pm: 12h stays 12h, 1h..11h map to 13h..23h.
CHECK_EQUAL(12, Chrono::make24(Chrono::hours(12), true).count());
for (int h = 1; h <= 11; ++h)
{
CHECK_EQUAL(h + 12, Chrono::make24(Chrono::hours(h), true).count());
}
}
//*************************************************************************
TEST(test_make12_make24_round_trip)
{
// For every 24-hour value, make12 plus its am/pm flag round-trips via make24.
for (int h = 0; h <= 23; ++h)
{
Chrono::hours h24(h);
bool pm = Chrono::is_pm(h24);
Chrono::hours h12 = Chrono::make12(h24);
CHECK_EQUAL(h, Chrono::make24(h12, pm).count());
}
}
}
} // namespace

View File

@ -185,6 +185,99 @@ namespace
}
}
//*************************************************************************
TEST(test_operator_plus_time_point_duration)
{
TimePoint tp{Chrono::hours(10)};
// Same duration type.
auto result = tp + Chrono::hours(5);
CHECK_EQUAL(15, result.time_since_epoch().count());
// Mixed duration types resolve to the common (finer) type.
auto result_mixed = tp + Chrono::days(1); // 10 hours + 24 hours
CHECK_EQUAL(34, result_mixed.time_since_epoch().count());
CHECK_TRUE((std::is_same<decltype(result_mixed)::duration, Chrono::hours>::value));
}
//*************************************************************************
TEST(test_operator_plus_duration_time_point)
{
TimePoint tp{Chrono::hours(10)};
// Same duration type.
auto result = Chrono::hours(5) + tp;
CHECK_EQUAL(15, result.time_since_epoch().count());
// Mixed duration types resolve to the common (finer) type.
auto result_mixed = Chrono::days(1) + tp; // 24 hours + 10 hours
CHECK_EQUAL(34, result_mixed.time_since_epoch().count());
CHECK_TRUE((std::is_same<decltype(result_mixed)::duration, Chrono::hours>::value));
}
//*************************************************************************
TEST(test_operator_minus_time_point_duration)
{
TimePoint tp{Chrono::hours(50)};
// Same duration type.
auto result = tp - Chrono::hours(5);
CHECK_EQUAL(45, result.time_since_epoch().count());
// Mixed duration types resolve to the common (finer) type.
auto result_mixed = tp - Chrono::days(1); // 50 hours - 24 hours
CHECK_EQUAL(26, result_mixed.time_since_epoch().count());
CHECK_TRUE((std::is_same<decltype(result_mixed)::duration, Chrono::hours>::value));
}
//*************************************************************************
TEST(test_operator_minus_time_point_time_point)
{
TimePoint tp1{Chrono::hours(50)};
TimePoint tp2{Chrono::hours(20)};
// Subtracting two time_points yields the duration between them.
auto diff = tp1 - tp2;
CHECK_EQUAL(30, diff.count());
CHECK_TRUE((std::is_same<decltype(diff), Chrono::hours>::value));
// Mixed duration types resolve to the common (finer) duration.
Chrono::time_point<test_clock, Chrono::days> tp_days{Chrono::days(2)}; // 48 hours
auto diff_mixed = tp1 - tp_days; // 50 hours - 48 hours
CHECK_EQUAL(2, diff_mixed.count());
CHECK_TRUE((std::is_same<decltype(diff_mixed), Chrono::hours>::value));
// The reverse difference is negative.
auto diff_negative = tp2 - tp1;
CHECK_EQUAL(-30, diff_negative.count());
}
//*************************************************************************
TEST(test_increment_decrement_operators)
{
TimePoint tp{Chrono::hours(10)};
// Pre-increment.
auto& pre_inc = ++tp;
CHECK_EQUAL(11, tp.time_since_epoch().count());
CHECK_EQUAL(11, pre_inc.time_since_epoch().count());
// Post-increment returns the previous value.
TimePoint post_inc = tp++;
CHECK_EQUAL(11, post_inc.time_since_epoch().count());
CHECK_EQUAL(12, tp.time_since_epoch().count());
// Pre-decrement.
auto& pre_dec = --tp;
CHECK_EQUAL(11, tp.time_since_epoch().count());
CHECK_EQUAL(11, pre_dec.time_since_epoch().count());
// Post-decrement returns the previous value.
TimePoint post_dec = tp--;
CHECK_EQUAL(11, post_dec.time_since_epoch().count());
CHECK_EQUAL(10, tp.time_since_epoch().count());
}
#if ETL_USING_ETL_CHRONO
//*************************************************************************
TEST(test_min_max_time_point)