Added sys_day and local_day constructors and conversions

This commit is contained in:
John Wellbelove 2025-05-17 21:00:23 +01:00
parent d04ee8c5e7
commit ba31479481
16 changed files with 619 additions and 142 deletions

View File

@ -43,6 +43,8 @@ namespace etl
{
public:
using rep = uint_least8_t;
//***********************************************************************
/// Default constructor
//***********************************************************************
@ -195,7 +197,7 @@ namespace etl
private:
uint_least8_t value;
rep value;
};
//***********************************************************************
@ -315,10 +317,10 @@ namespace etl
{
size_t operator()(const etl::chrono::day& d) const
{
unsigned value = d;
etl::chrono::day::rep value = static_cast<etl::chrono::day::rep>(static_cast<unsigned>(d));
const uint8_t* p = reinterpret_cast<const uint8_t*>(&value);
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(unsigned));
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(value));
}
};
#endif

View File

@ -54,6 +54,8 @@ namespace etl
{
public:
using rep = uint_least8_t;
//***********************************************************************
/// Default constructor
//***********************************************************************
@ -200,7 +202,7 @@ namespace etl
private:
uint_least8_t value;
rep value;
};
//***********************************************************************
@ -434,10 +436,10 @@ namespace etl
{
size_t operator()(const etl::chrono::month& m) const
{
unsigned value = m;
etl::chrono::month::rep value = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(m));
const uint8_t* p = reinterpret_cast<const uint8_t*>(&value);
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(unsigned));
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(value));
}
};
#endif
@ -451,10 +453,10 @@ namespace etl
{
size_t operator()(const etl::chrono::month_day_last& mdl) const
{
unsigned value = (unsigned)mdl.month();
etl::chrono::month::rep value = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(mdl.month()));
const uint8_t* p = reinterpret_cast<const uint8_t*>(&value);
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(unsigned));
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(value));
}
};
#endif

View File

@ -213,16 +213,16 @@ namespace etl
struct hash<etl::chrono::month_day>
{
size_t operator()(const etl::chrono::month_day& md) const
{
uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int)];
unsigned int m = md.month();
unsigned int d = md.day();
{
etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(md.month()));
etl::chrono::day::rep d = static_cast<etl::chrono::day::rep>(static_cast<unsigned>(md.day()));
uint8_t buffer[sizeof(m) + sizeof(d)];
memcpy(buffer, &m, sizeof(m));
memcpy(buffer + sizeof(m), &d, sizeof(d));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(m) + sizeof(d));
}
};
#endif

View File

@ -172,18 +172,18 @@ namespace etl
struct hash<etl::chrono::month_weekday>
{
size_t operator()(const etl::chrono::month_weekday& mw) const
{
uint8_t buffer[3U * sizeof(unsigned int)];
unsigned int a = mw.month();
unsigned int b = mw.weekday_indexed().weekday().c_encoding();
unsigned int c = mw.weekday_indexed().index();
{
etl::chrono::month::rep a = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(mw.month()));
unsigned int b = mw.weekday_indexed().weekday().c_encoding();
unsigned int c = mw.weekday_indexed().index();
uint8_t buffer[sizeof(a) + sizeof(b) + sizeof(c)];
memcpy(buffer, &a, sizeof(a));
memcpy(buffer + sizeof(a), &b, sizeof(b));
memcpy(buffer + sizeof(b), &b, sizeof(c));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + 3U * sizeof(unsigned int));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(a) + sizeof(b) + sizeof(c));
}
};
#endif
@ -197,15 +197,15 @@ namespace etl
{
size_t operator()(const etl::chrono::month_weekday_last& mw) const
{
uint8_t buffer[2U * sizeof(unsigned int)];
etl::chrono::month::rep a = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(mw.month()));
unsigned int b = mw.weekday_last().weekday().c_encoding();
unsigned int a = mw.month();
unsigned int b = mw.weekday_last().weekday().c_encoding();
uint8_t buffer[sizeof(a) + sizeof(b)];
memcpy(buffer, &a, sizeof(a));
memcpy(buffer + sizeof(a), &b, sizeof(b));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + 2U * sizeof(unsigned int));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(a) + sizeof(b));
}
};
#endif

View File

@ -68,6 +68,34 @@ namespace etl
{
}
//*************************************************************************
/// Construct from sys_days.
//*************************************************************************
ETL_CONSTEXPR weekday(const etl::chrono::sys_days& sd) ETL_NOEXCEPT
{
// Get number of days since epoch
etl::chrono::days days_since_epoch = sd.time_since_epoch();
// Convert to weekday manually: epoch was Thursday (4)
value = (days_since_epoch.count() + 4) % 7;
// Normalize in case of negative modulo
if (value < 0)
{
value += 7;
}
}
//*************************************************************************
/// Construct from local_days.
//*************************************************************************
ETL_CONSTEXPR weekday(const etl::chrono::local_days& ld) ETL_NOEXCEPT
{
weekday wd(sys_days(ld.time_since_epoch()));
value = wd.c_encoding();
}
//***********************************************************************
/// Copy constructor
//***********************************************************************
@ -500,7 +528,15 @@ namespace etl
{
size_t operator()(const etl::chrono::weekday_indexed& wdi) const
{
return etl::hash<etl::chrono::weekday>()(wdi.weekday()) ^ etl::hash<unsigned>()(wdi.index());
unsigned int a = wdi.weekday().c_encoding();
unsigned int b = wdi.index();
uint8_t buffer[sizeof(a) + sizeof(b)];
memcpy(buffer, &a, sizeof(a));
memcpy(buffer + sizeof(a), &b, sizeof(b));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(a) + sizeof(b));
}
};
#endif

View File

@ -43,6 +43,8 @@ namespace etl
{
public:
using rep = int16_t;
//***********************************************************************
/// Default constructor
//***********************************************************************
@ -183,7 +185,7 @@ namespace etl
private:
int16_t value;
rep value;
};
//***********************************************************************
@ -316,10 +318,10 @@ namespace etl
{
size_t operator()(const etl::chrono::year& y) const
{
int value = y;
etl::chrono::year::rep value = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(y));
const uint8_t* p = reinterpret_cast<const uint8_t*>(&value);
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(int));
return etl::private_hash::generic_hash<size_t>(p, p + sizeof(value));
}
};
#endif

View File

@ -216,17 +216,17 @@ namespace etl
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();
size_t operator()(const etl::chrono::year_month& ym) const
{
etl::chrono::year::rep y = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(ym.year()));
etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(ym.month()));
uint8_t buffer[sizeof(y) + sizeof(m)];
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));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(y) + sizeof(m));
}
};
#endif

View File

@ -36,6 +36,8 @@ namespace etl
{
namespace chrono
{
class year_month_day_last;
//*************************************************************************
/// year_month_day
//*************************************************************************
@ -65,6 +67,73 @@ namespace etl
{
}
//*************************************************************************
/// Construct from year_month_day_last.
//*************************************************************************
ETL_CONSTEXPR year_month_day(const etl::chrono::year_month_day_last& ymdl) ETL_NOEXCEPT;
//*************************************************************************
/// Construct from sys_days.
//*************************************************************************
ETL_CONSTEXPR year_month_day(const etl::chrono::sys_days& sd) ETL_NOEXCEPT
{
// Days since 1970-01-01
int days_since_epoch = static_cast<int>(sd.time_since_epoch().count());
// Start from 1970-01-01
etl::chrono::year current_year(1970);
etl::chrono::month current_month(1);
// Find the year
while (true)
{
int days_in_year = current_year.is_leap() ? 366 : 365;
if (days_since_epoch < days_in_year)
{
break;
}
days_since_epoch -= days_in_year;
++current_year;
}
// Find the month
while (true)
{
unsigned char days_in_month = etl::chrono::private_chrono::days_in_month[current_month];
if (current_month == etl::chrono::February && current_year.is_leap())
{
++days_in_month;
}
if (days_since_epoch < days_in_month)
{
break;
}
days_since_epoch -= days_in_month;
++current_month;
}
// The remaining days are the day of the month (0-based)
y = current_year;
m = current_month;
d = etl::chrono::day(static_cast<unsigned>(days_since_epoch) + 1);
}
//*************************************************************************
/// Construct from sys_days.
//*************************************************************************
ETL_CONSTEXPR year_month_day(const etl::chrono::local_days& ld) ETL_NOEXCEPT
{
etl::chrono::year_month_day ymd = sys_days(ld.time_since_epoch());
y = ymd.year();
m = ymd.month();
d = ymd.day();
}
//*************************************************************************
/// Returns the year.
//*************************************************************************
@ -221,7 +290,7 @@ namespace etl
}
//***********************************************************************
/// Converts *this to etl::chrono::sys_days
/// Converts to etl::chrono::sys_days
//***********************************************************************
ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
{
@ -237,6 +306,7 @@ namespace etl
for (etl::chrono::month mth(1); mth < this->month(); ++mth)
{
day_count += private_chrono::days_in_month[mth];
if (mth == etl::chrono::February && this->year().is_leap())
{
++day_count; // Add one day for leap year February
@ -249,17 +319,13 @@ namespace etl
return sys_days(etl::chrono::days(day_count));
}
////***********************************************************************
///// Converts *this to etl::chrono::local_days
////***********************************************************************
//ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
//{
//// Convert the year_month_day to sys_days first
//etl::chrono::sys_days sys_days_representation = static_cast<etl::chrono::sys_days>(*this);
//// Convert sys_days to local_days (assuming local_days is a wrapper around sys_days)
//return etl::chrono::local_days(sys_days_representation);
//}
//***********************************************************************
/// Converts to etl::chrono::local_days
//***********************************************************************
ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
{
return local_days(sys_days(*this).time_since_epoch());
}
private:
@ -300,7 +366,7 @@ namespace etl
///
//*************************************************************************
ETL_CONSTEXPR14 year_month_day_last(const etl::chrono::year& y_,
const etl::chrono::month_day_last& mdl_) ETL_NOEXCEPT
const etl::chrono::month_day_last& mdl_) ETL_NOEXCEPT
: y(y_)
, m(mdl_.month())
{
@ -455,7 +521,7 @@ namespace etl
/// Inequality operator.
//*************************************************************************
friend ETL_CONSTEXPR14 bool operator !=(const etl::chrono::year_month_day_last& lhs,
const etl::chrono::year_month_day_last& rhs) ETL_NOEXCEPT
const etl::chrono::year_month_day_last& rhs) ETL_NOEXCEPT
{
return !(lhs == rhs);
}
@ -508,26 +574,38 @@ namespace etl
}
//*************************************************************************
///
/// Converts to etl::chrono::sys_days
//*************************************************************************
//ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
//{
// etl::chrono::sys_days();
//}
ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
{
etl::chrono::year_month_day ymd(year(), month(), day());
return etl::chrono::sys_days(ymd);
}
//*************************************************************************
///
/// Converts to etl::chrono::local_days
//*************************************************************************
//ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
//{
//}
ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
{
return local_days(sys_days(*this).time_since_epoch());
}
private:
etl::chrono::year y;
etl::chrono::month m;
};
//*************************************************************************
/// Construct from year_month_day_last.
//*************************************************************************
ETL_CONSTEXPR etl::chrono::year_month_day::year_month_day(const etl::chrono::year_month_day_last& ymdl) ETL_NOEXCEPT
: y(ymdl.year())
, m(ymdl.month())
, d(ymdl.day())
{
}
}
//*************************************************************************
@ -539,17 +617,17 @@ namespace etl
{
size_t operator()(const etl::chrono::year_month_day& ymd) const
{
uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)];
unsigned int y = ymd.year();
unsigned int m = ymd.month();
unsigned int d = ymd.day();
etl::chrono::year::rep y = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(ymd.year()));
etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(ymd.month()));
etl::chrono::day::rep d = static_cast<etl::chrono::day::rep>(static_cast<unsigned>(ymd.day()));
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
uint8_t buffer[sizeof(y) + sizeof(m) + sizeof(d)];
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(y) + sizeof(m) + sizeof(d));
}
};
#endif
@ -563,17 +641,17 @@ namespace etl
{
size_t operator()(const etl::chrono::year_month_day_last& ymdl) const
{
uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)];
etl::chrono::year::rep y = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(ymdl.year()));
etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(ymdl.month()));
etl::chrono::day::rep d = static_cast<etl::chrono::day::rep>(static_cast<unsigned>(ymdl.day()));
unsigned int y = ymdl.year();
unsigned int m = ymdl.month();
unsigned int d = ymdl.day();
uint8_t buffer[sizeof(y) + sizeof(m) + sizeof(d)];
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(y) + sizeof(m) + sizeof(d));
}
};
#endif

View File

@ -54,7 +54,7 @@ namespace etl
}
//*************************************************************************
/// Construct from month and day.
/// Construct from month, day, and weekday_indexed.
//*************************************************************************
ETL_CONSTEXPR year_month_weekday(const etl::chrono::year& y_,
const etl::chrono::month& m_,
@ -65,6 +65,47 @@ namespace etl
{
}
//*************************************************************************
/// Construct from sys_days.
//*************************************************************************
ETL_CONSTEXPR year_month_weekday(const etl::chrono::sys_days& sd) ETL_NOEXCEPT
{
// Extract year, month, and day
year_month_day ymd = year_month_day{sd};
etl::chrono::year yr = ymd.year();
etl::chrono::month mth = ymd.month();
etl::chrono::day dy = ymd.day();
// Get the weekday from sys_days
etl::chrono::weekday wd = etl::chrono::weekday{sd};
// Count how many times this weekday has occurred in the month so far
// We walk backward from the given day in steps of 7 days
unsigned index = 1;
for (int offset = static_cast<int>(dy) - 7; offset > 0; offset -= 7)
{
++index;
}
y = yr;
m = mth;
wdi = etl::chrono::weekday_indexed{ wd, index };
}
//*************************************************************************
/// Construct from local_days.
//*************************************************************************
ETL_CONSTEXPR year_month_weekday(const etl::chrono::local_days& ld) ETL_NOEXCEPT
{
year_month_weekday ymwd(sys_days(ld.time_since_epoch()));
y = ymwd.year();
m = ymwd.month();
wdi = ymwd.weekday_indexed();
}
//*************************************************************************
/// Returns the year.
//*************************************************************************
@ -171,7 +212,7 @@ namespace etl
/// Equality operator.
//*************************************************************************
friend ETL_CONSTEXPR14 bool operator ==(const etl::chrono::year_month_weekday& lhs,
const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT
const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT
{
return (lhs.y == rhs.y) && (lhs.m == rhs.m) && (lhs.wdi == rhs.wdi);
}
@ -180,51 +221,49 @@ namespace etl
/// Inequality operator.
//*************************************************************************
friend ETL_CONSTEXPR14 bool operator !=(const etl::chrono::year_month_weekday& lhs,
const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT
const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT
{
return !(lhs == rhs);
}
//***********************************************************************
/// Converts *this to etl::chrono::sys_days
/// Converts to etl::chrono::sys_days
//***********************************************************************
//ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
//{
// // Start with the first day of the given year and month
// etl::chrono::year_month_day first_day_of_month(y, m, etl::chrono::day(1));
ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
{
if (ok())
{
etl::chrono::year_month_weekday ymwd(*this);
etl::chrono::year_month_day ymd{ ymwd.year(), ymwd.month(), etl::chrono::day(1) };
// // Convert the first day of the month to sys_days
// etl::chrono::sys_days first_day_sys_days = static_cast<etl::chrono::sys_days>(first_day_of_month);
etl::chrono::sys_days sd = ymd;
// // Determine the weekday of the first day of the month
// etl::chrono::weekday first_weekday = etl::chrono::weekday(first_day_sys_days);
unsigned int target_wd = ymwd.weekday().c_encoding();
unsigned int target_index = ymwd.index();
// // Calculate the offset to the desired weekday
// int offset = (wd.weekday().c_encoding() - first_weekday.c_encoding() + 7) % 7;
etl::chrono::weekday first_weekday(static_cast<int>(sd.time_since_epoch().count()));
// // Calculate the day of the month for the desired weekday_indexed
// int day_of_month = 1 + offset + (wdi.index() - 1) * 7;
int first_wd = first_weekday.c_encoding();
int offset = (target_wd - first_wd + 7) % 7;
int day_of_month = offset + static_cast<int>(target_index - 1) * 7;
// // Ensure the calculated day is valid for the given month
// if (day_of_month > etl::chrono::month_day_last(m).day().count())
// {
// day_of_month = 0; // Invalid day
// }
etl::chrono::year_month_day result(year(), month(), etl::chrono::day(day_of_month));
// // Create a year_month_day object for the calculated day
// etl::chrono::year_month_day ymwd(y, m, etl::chrono::day(day_of_month));
return etl::chrono::sys_days(result);
}
else
{
return etl::chrono::sys_days();
}
}
// // Convert the year_month_day to sys_days
// return static_cast<etl::chrono::sys_days>(ymwd);
//}
////***********************************************************************
///// Converts *this to etl::chrono::local_days
////***********************************************************************
//ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
//{
// return etl::chrono::local_days();
//}
//***********************************************************************
/// Converts to etl::chrono::local_days
//***********************************************************************
ETL_CONSTEXPR14 operator etl::chrono::local_days() const ETL_NOEXCEPT
{
return local_days(sys_days(*this).time_since_epoch());
}
private:
@ -244,8 +283,8 @@ namespace etl
/// Construct from year, month, weekday_last
//*************************************************************************
ETL_CONSTEXPR14 year_month_weekday_last(const etl::chrono::year& y_,
const etl::chrono::month& m_,
const etl::chrono::weekday_last& wdl_) ETL_NOEXCEPT
const etl::chrono::month& m_,
const etl::chrono::weekday_last& wdl_) ETL_NOEXCEPT
: y(y_)
, m(m_)
, wdl(wdl_)
@ -382,7 +421,7 @@ namespace etl
/// Equality operator.
//*************************************************************************
friend ETL_CONSTEXPR14 bool operator ==(const etl::chrono::year_month_weekday_last& lhs,
const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT
const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT
{
return (lhs.y == rhs.y) && (lhs.m == rhs.m) && (lhs.weekday() == rhs.weekday());
}
@ -391,7 +430,7 @@ namespace etl
/// Inequality operator.
//*************************************************************************
friend ETL_CONSTEXPR14 bool operator !=(const etl::chrono::year_month_weekday_last& lhs,
const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT
const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT
{
return !(lhs == rhs);
}
@ -433,7 +472,7 @@ namespace etl
/// else if month > other.month, returns 1;
/// else returns 0;
//***********************************************************************
ETL_CONSTEXPR14 int compare(const year_month_weekday_last& other) const ETL_NOEXCEPT
ETL_CONSTEXPR14 int compare(const etl::chrono::year_month_weekday_last& other) const ETL_NOEXCEPT
{
if (y < other.y) return -1;
if (y > other.y) return 1;
@ -444,20 +483,40 @@ namespace etl
}
//*************************************************************************
///
/// Converts to etl::chrono::sys_days
//*************************************************************************
//ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
//{
// etl::chrono::sys_days();
//}
ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
{
// Get the last day of the month
etl::chrono::year_month_day_last ymdl(year(), etl::chrono::month_day_last(month()));
etl::chrono::day last_day = ymdl.day();
// Walk backward from the last day to find the last occurrence of the target weekday
unsigned d = static_cast<unsigned>(last_day);
for (; d >= 1; --d)
{
etl::chrono::year_month_day ymd(year(), month(), etl::chrono::day(d));
etl::chrono::sys_days ymd_sys_days = static_cast<etl::chrono::sys_days>(ymd);
etl::chrono::weekday wd(static_cast<int>(ymd_sys_days.time_since_epoch().count()));
if (wd == weekday())
{
return ymd_sys_days;
}
}
// If not found (should not happen for valid input), return epoch
return etl::chrono::sys_days();
}
//*************************************************************************
///
/// Converts to etl::chrono::local_days
//*************************************************************************
//ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
//{
//}
ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
{
return local_days(sys_days(*this).time_since_epoch());
}
private:
@ -476,17 +535,17 @@ namespace etl
{
size_t operator()(const etl::chrono::year_month_weekday& ymwd) const
{
uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)];
unsigned int y = ymwd.year();
unsigned int m = ymwd.month();
unsigned int d = ymwd.weekday().c_encoding();
etl::chrono::year::rep y = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(ymwd.year()));
etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(ymwd.month()));
unsigned int wd = ymwd.weekday().c_encoding();
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d));
uint8_t buffer[sizeof(y) + sizeof(m) + sizeof(wd)];
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int));
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
memcpy(buffer + sizeof(y) + sizeof(m), &wd, sizeof(wd));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(y) + sizeof(m) + sizeof(wd));
}
};
#endif
@ -500,17 +559,17 @@ namespace etl
{
size_t operator()(const etl::chrono::year_month_weekday_last& ymwdl) const
{
uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)];
etl::chrono::year::rep y = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(ymwdl.year()));
etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(ymwdl.month()));
unsigned int wd = ymwdl.weekday().c_encoding();
unsigned int y = ymwdl.year();
unsigned int m = ymwdl.month();
unsigned int d = ymwdl.weekday_last().weekday().c_encoding();
uint8_t buffer[sizeof(y) + sizeof(m) + sizeof(wd)];
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d));
memcpy(buffer, &y, sizeof(y));
memcpy(buffer + sizeof(y), &m, sizeof(m));
memcpy(buffer + sizeof(y) + sizeof(m), &wd, sizeof(wd));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int));
return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(y) + sizeof(m) + sizeof(wd));
}
};
#endif

View File

@ -65,6 +65,15 @@ namespace
CHECK_FALSE(weekday.ok());
}
//*************************************************************************
TEST(test_constructor_with_sys_days)
{
Chrono::weekday expected{Chrono::Tuesday};
Chrono::weekday actual{Chrono::sys_days(Chrono::days(10988))};
CHECK_EQUAL((unsigned)expected.c_encoding(), (unsigned)actual.c_encoding());
}
//*************************************************************************
TEST(test_constructor_in_range)
{

View File

@ -145,6 +145,17 @@ namespace
CHECK_EQUAL(10997, sd.time_since_epoch().count());
}
//*************************************************************************
TEST(test_from_sys_days)
{
Chrono::year_month_day ymd{Chrono::sys_days(etl::chrono::days(10997))};
Chrono::year_month_day expected{Chrono::year(2000), Chrono::February, Chrono::day(10)};
CHECK_EQUAL((unsigned)expected.year(), (unsigned)ymd.year());
CHECK_EQUAL((unsigned)expected.month(), (unsigned)ymd.month());
CHECK_EQUAL((unsigned)expected.day(), (unsigned)ymd.day());
}
//*************************************************************************
TEST(test_year_month_day_equality_operator)
{

View File

@ -144,5 +144,14 @@ namespace
(void)std::unique(hashes.begin(), hashes.end());
}
#endif
//*************************************************************************
TEST(test_to_sys_days)
{
Chrono::year_month_day_last ymdl{Chrono::year(2000), Chrono::month_day_last(Chrono::February)};
Chrono::sys_days sd = Chrono::sys_days(ymdl);
CHECK_EQUAL(11016, sd.time_since_epoch().count());
}
};
}

View File

@ -0,0 +1,154 @@
/******************************************************************************
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_year_month_weekday)
{
//*************************************************************************
TEST(test_default_constructor)
{
Chrono::year_month_weekday ymwd;
CHECK_FALSE(ymwd.ok()); // Default-constructed year_month_weekday is not valid
}
//*************************************************************************
TEST(test_constructor_with_month_and_day)
{
Chrono::year_month_weekday ymwd{Chrono::year(2000), Chrono::January, Chrono::weekday_indexed(Chrono::Thursday, 1)};
CHECK_TRUE(ymwd.ok()); // Valid year_month_weekday
CHECK_EQUAL(2000, (int)ymwd.year());
CHECK_EQUAL((unsigned)Chrono::January, (unsigned)ymwd.month());
CHECK_EQUAL(Chrono::Thursday.c_encoding(), ymwd.weekday().c_encoding());
CHECK_EQUAL(1, ymwd.index());
CHECK_TRUE(ymwd.weekday_indexed().ok());
CHECK_EQUAL(Chrono::Thursday.c_encoding(), ymwd.weekday_indexed().weekday().c_encoding());
CHECK_EQUAL(1, ymwd.weekday_indexed().index());
}
//*************************************************************************
TEST(test_constructor_with_sys_days)
{
Chrono::year_month_weekday expected{Chrono::year(2000), Chrono::February, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::year_month_weekday actual{Chrono::sys_days(Chrono::days(10990))};
CHECK_EQUAL((int)expected.year(), (int)actual.year());
CHECK_EQUAL((unsigned)expected.month(), (unsigned)actual.month());
CHECK_EQUAL((unsigned)expected.weekday().c_encoding(), (unsigned)actual.weekday().c_encoding());
CHECK_EQUAL((unsigned)expected.index(), (unsigned)actual.index());
}
//*************************************************************************
TEST(test_invalid_year_month)
{
Chrono::year_month_weekday ymwd{Chrono::year{32768}, Chrono::January, Chrono::weekday_indexed(Chrono::Thursday, 1)}; // Invalid year
CHECK_FALSE(ymwd.ok()); // Invalid year_month_weekday
}
//*************************************************************************
TEST(test_invalid_month_in_year_month)
{
Chrono::year_month_weekday ymwd{Chrono::year{2000}, Chrono::month{13}, Chrono::weekday_indexed(Chrono::Thursday, 1)}; // Invalid month (13)
CHECK_FALSE(ymwd.ok()); // Invalid year_month_weekday
}
//*************************************************************************
TEST(test_invalid_day_in_year_month)
{
Chrono::year_month_weekday ymwd{Chrono::year{2000}, Chrono::January, Chrono::weekday_indexed(Chrono::Thursday, 6)}; // Invalid day (6)
CHECK_FALSE(ymwd.ok()); // Invalid year_month_weekday
}
//*************************************************************************
TEST(test_to_sys_days)
{
Chrono::year_month_weekday ymwd{Chrono::year(2000), Chrono::February, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::sys_days sd = Chrono::sys_days(ymwd);
CHECK_EQUAL(10990, sd.time_since_epoch().count());
}
//*************************************************************************
TEST(test_year_month_weekday_equality_operator)
{
Chrono::year_month_weekday ym1{Chrono::year(2000), Chrono::January, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::year_month_weekday ym2{Chrono::year(2001), Chrono::January, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::year_month_weekday ym3{Chrono::year(2000), Chrono::February, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::year_month_weekday ym4{Chrono::year(2000), Chrono::January, Chrono::weekday_indexed(Chrono::Friday, 2)};
CHECK_TRUE(ym1 == ym1); // Same year/month/day
CHECK_FALSE(ym1 == ym2); // Different year
CHECK_FALSE(ym1 == ym3); // Different month
CHECK_FALSE(ym1 == ym4); // Different day
}
//*************************************************************************
TEST(test_year_month_weekday_not_equality_operator)
{
Chrono::year_month_weekday ym1{Chrono::year(2000), Chrono::January, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::year_month_weekday ym2{Chrono::year(2001), Chrono::January, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::year_month_weekday ym3{Chrono::year(2000), Chrono::February, Chrono::weekday_indexed(Chrono::Thursday, 1)};
Chrono::year_month_weekday ym4{Chrono::year(2000), Chrono::January, Chrono::weekday_indexed(Chrono::Friday, 2)};
CHECK_FALSE(ym1 != ym1); // Same year/month/day
CHECK_TRUE(ym1 != ym2); // Different year
CHECK_TRUE(ym1 != ym3); // Different month
CHECK_TRUE(ym1 != ym4); // Different day
}
};
}

View File

@ -0,0 +1,107 @@
/******************************************************************************
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_year_month_weekday_last)
{
//*************************************************************************
TEST(test_constructor_with_month_and_day)
{
Chrono::year_month_weekday_last ymwdl{Chrono::year(2000), Chrono::January, Chrono::weekday_last(Chrono::Thursday)};
CHECK_EQUAL(2000, (int)ymwdl.year());
CHECK_EQUAL((unsigned)Chrono::January, (unsigned)ymwdl.month());
CHECK_EQUAL(Chrono::Thursday.c_encoding(), ymwdl.weekday().c_encoding());
using namespace etl::literals::chrono_literals;
}
//*************************************************************************
TEST(test_to_sys_days)
{
Chrono::year_month_weekday_last ymwdl{Chrono::year(2000), Chrono::February, Chrono::weekday_last(Chrono::Thursday)};
Chrono::sys_days sd = Chrono::sys_days(ymwdl);
CHECK_EQUAL(11012, sd.time_since_epoch().count());
}
//*************************************************************************
TEST(test_year_month_weekday_last_equality_operator)
{
Chrono::year_month_weekday_last ym1{Chrono::year(2000), Chrono::January, Chrono::weekday_last(Chrono::Thursday)};
Chrono::year_month_weekday_last ym2{Chrono::year(2001), Chrono::January, Chrono::weekday_last(Chrono::Thursday)};
Chrono::year_month_weekday_last ym3{Chrono::year(2000), Chrono::February, Chrono::weekday_last(Chrono::Thursday)};
Chrono::year_month_weekday_last ym4{Chrono::year(2000), Chrono::January, Chrono::weekday_last(Chrono::Friday)};
CHECK_TRUE(ym1 == ym1); // Same year/month/day
CHECK_FALSE(ym1 == ym2); // Different year
CHECK_FALSE(ym1 == ym3); // Different month
CHECK_FALSE(ym1 == ym4); // Different day
}
//*************************************************************************
TEST(test_year_month_weekday_last_not_equality_operator)
{
Chrono::year_month_weekday_last ym1{Chrono::year(2000), Chrono::January, Chrono::weekday_last(Chrono::Thursday)};
Chrono::year_month_weekday_last ym2{Chrono::year(2001), Chrono::January, Chrono::weekday_last(Chrono::Thursday)};
Chrono::year_month_weekday_last ym3{Chrono::year(2000), Chrono::February, Chrono::weekday_last(Chrono::Thursday)};
Chrono::year_month_weekday_last ym4{Chrono::year(2000), Chrono::January, Chrono::weekday_last(Chrono::Friday)};
CHECK_FALSE(ym1 != ym1); // Same year/month/day
CHECK_TRUE(ym1 != ym2); // Different year
CHECK_TRUE(ym1 != ym3); // Different month
CHECK_TRUE(ym1 != ym4); // Different day
}
};
}

View File

@ -8502,6 +8502,8 @@
<ClCompile Include="..\test_chrono_year_month.cpp" />
<ClCompile Include="..\test_chrono_year_month_day.cpp" />
<ClCompile Include="..\test_chrono_year_month_day_last.cpp" />
<ClCompile Include="..\test_chrono_year_month_weekday.cpp" />
<ClCompile Include="..\test_chrono_year_month_weekday_last.cpp" />
<ClCompile Include="..\test_circular_buffer.cpp" />
<ClCompile Include="..\test_circular_buffer_external_buffer.cpp" />
<ClCompile Include="..\test_circular_iterator.cpp" />
@ -9858,4 +9860,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -3584,6 +3584,12 @@
<ClCompile Include="..\syntax_check\chrono.h.t.cpp">
<Filter>Tests\Syntax Checks\Source</Filter>
</ClCompile>
<ClCompile Include="..\test_chrono_year_month_weekday.cpp">
<Filter>Tests\Chrono</Filter>
</ClCompile>
<ClCompile Include="..\test_chrono_year_month_weekday_last.cpp">
<Filter>Tests\Chrono</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">