tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
year_month_day.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2
3#ifndef TETL_CHRONO_YEAR_MONTH_DAY_HPP
4#define TETL_CHRONO_YEAR_MONTH_DAY_HPP
5
6#include <etl/_chrono/day.hpp>
10#include <etl/_chrono/year.hpp>
13
14namespace etl::chrono {
15
18private:
19 // https://howardhinnant.github.io/date_algorithms.html#civil_from_days
20 [[nodiscard]] static constexpr auto civil_from_days(int32_t z) noexcept -> year_month_day
21 {
22 static_assert(etl::numeric_limits<uint32_t>::digits >= 18, "Not yet ported to a 16 bit unsigned integer");
23 static_assert(etl::numeric_limits<int32_t>::digits >= 20, "Not yet ported to a 16 bit signed integer");
24
25 z += 719468;
26 int32_t const era = (z >= 0 ? z : z - 146096) / 146097;
27 auto const doe = static_cast<uint32_t>(z - era * 146097);
28 uint32_t const yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
29 int32_t const y = static_cast<int32_t>(yoe) + era * 400;
30 uint32_t const doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
31 uint32_t const mp = (5 * doy + 2) / 153;
32 uint32_t const d = doy - (153 * mp + 2) / 5 + 1;
33 uint32_t const m = mp < 10 ? mp + 3 : mp - 9;
34
35 return {
36 chrono::year{static_cast<int>(y) + static_cast<int>(m <= 2)},
37 chrono::month{static_cast<unsigned>(m)},
38 chrono::day{static_cast<unsigned>(d)},
39 };
40 }
41
42 // https://howardhinnant.github.io/date_algorithms.html#days_from_civil
43 [[nodiscard]] static constexpr auto days_from_civil(int32_t y, uint32_t m, uint32_t d) noexcept -> days
44 {
45 static_assert(etl::numeric_limits<uint32_t>::digits >= 18, "Not yet ported to a 16 bit unsigned integer");
46 static_assert(etl::numeric_limits<int32_t>::digits >= 20, "Not yet ported to a 16 bit signed integer");
47
48 y -= static_cast<int32_t>(m <= 2);
49 int32_t const era = (y >= 0 ? y : y - 399) / 400;
50 auto const yoe = static_cast<uint32_t>(y - era * 400); // [0, 399]
51 uint32_t const doy = (153 * (m > 2 ? m - 3 : m + 9) + 2) / 5 + d - 1; // [0, 365]
52 uint32_t const doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
53 return days{era * 146097 + static_cast<int32_t>(doe) - 719468};
54 }
55
56public:
57 year_month_day() = default;
58
59 constexpr year_month_day(chrono::year const& y, chrono::month const& m, chrono::day const& d) noexcept
60 : _y{y}
61 , _m{m}
62 , _d{d}
63 {
64 }
65
66 constexpr year_month_day(year_month_day_last const& ymdl) noexcept
67 : _y{ymdl.year()}
68 , _m{ymdl.month()}
69 , _d{ymdl.day()}
70 {
71 }
72
73 constexpr year_month_day(sys_days const& dp) noexcept
74 : year_month_day{civil_from_days(dp.time_since_epoch().count())}
75 {
76 }
77
78 constexpr explicit year_month_day(local_days const& dp) noexcept
79 : year_month_day{civil_from_days(dp.time_since_epoch().count())}
80 {
81 }
82
83 constexpr auto operator+=(months const& m) noexcept -> year_month_day&;
84 constexpr auto operator-=(months const& m) noexcept -> year_month_day&;
85 constexpr auto operator+=(years const& y) noexcept -> year_month_day&;
86 constexpr auto operator-=(years const& y) noexcept -> year_month_day&;
87
88 [[nodiscard]] constexpr auto year() const noexcept -> chrono::year { return _y; }
89
90 [[nodiscard]] constexpr auto month() const noexcept -> chrono::month { return _m; }
91
92 [[nodiscard]] constexpr auto day() const noexcept -> chrono::day { return _d; }
93
94 [[nodiscard]] constexpr operator sys_days() const noexcept
95 {
96 return sys_days{days_from_civil(int{year()}, unsigned{month()}, unsigned{day()})};
97 }
98
99 [[nodiscard]] constexpr explicit operator local_days() const noexcept
100 {
101 return local_days{static_cast<sys_days>(*this).time_since_epoch()};
102 }
103
104 [[nodiscard]] constexpr auto ok() const noexcept -> bool
105 {
106 if (not year().ok() or not month().ok()) {
107 return false;
108 }
109 return day() >= chrono::day{1} and day() <= detail::last_day_of_month(year(), month());
110 }
111
112private:
113 chrono::year _y;
114 chrono::month _m;
115 chrono::day _d;
116};
117
118[[nodiscard]] constexpr auto operator==(year_month_day const& lhs, year_month_day const& rhs) noexcept -> bool
119{
120 return lhs.year() == rhs.year() and lhs.month() == rhs.month() and lhs.day() == rhs.day();
121}
122
123[[nodiscard]] constexpr auto operator+(chrono::year_month_day const& lhs, chrono::months const& rhs) noexcept
125{
126 auto const ym = year_month{lhs.year(), lhs.month()} + rhs;
127 return {ym.year(), ym.month(), lhs.day()};
128}
129
130[[nodiscard]] constexpr auto operator+(chrono::months const& lhs, chrono::year_month_day const& rhs) noexcept
132{
133 return rhs + lhs;
134}
135
136[[nodiscard]] constexpr auto operator+(chrono::year_month_day const& lhs, chrono::years const& rhs) noexcept
138{
139 return {lhs.year() + rhs, lhs.month(), lhs.day()};
140}
141
142[[nodiscard]] constexpr auto operator+(chrono::years const& lhs, chrono::year_month_day const& rhs) noexcept
144{
145 return rhs + lhs;
146}
147
148[[nodiscard]] constexpr auto operator-(chrono::year_month_day const& lhs, chrono::months const& rhs) noexcept
150{
151 return lhs + -rhs;
152}
153
154[[nodiscard]] constexpr auto operator-(chrono::year_month_day const& lhs, chrono::years const& rhs) noexcept
156{
157 return lhs + -rhs;
158}
159
160constexpr auto year_month_day::operator+=(months const& m) noexcept -> year_month_day&
161{
162 *this = *this + m;
163 return *this;
164}
165
166constexpr auto year_month_day::operator-=(months const& m) noexcept -> year_month_day&
167{
168 *this = *this - m;
169 return *this;
170}
171
172constexpr auto year_month_day::operator+=(years const& y) noexcept -> year_month_day&
173{
174 *this = *this + y;
175 return *this;
176}
177
178constexpr auto year_month_day::operator-=(years const& y) noexcept -> year_month_day&
179{
180 *this = *this - y;
181 return *this;
182}
183
184[[nodiscard]] constexpr auto operator/(year_month const& ym, day const& d) noexcept -> year_month_day
185{
186 return {ym.year(), ym.month(), d};
187}
188
189[[nodiscard]] constexpr auto operator/(year_month const& ym, int d) noexcept -> year_month_day
190{
191 return {ym.year(), ym.month(), day(static_cast<unsigned>(d))};
192}
193
194[[nodiscard]] constexpr auto operator/(year const& y, month_day const& md) noexcept -> year_month_day
195{
196 return {y, md.month(), md.day()};
197}
198
199[[nodiscard]] constexpr auto operator/(int y, month_day const& md) noexcept -> year_month_day
200{
201 return {year{y}, md.month(), md.day()};
202}
203
204[[nodiscard]] constexpr auto operator/(month_day const& md, year const& y) noexcept -> year_month_day
205{
206 return {y, md.month(), md.day()};
207}
208
209[[nodiscard]] constexpr auto operator/(month_day const& md, int y) noexcept -> year_month_day
210{
211 return {year{y}, md.month(), md.day()};
212}
213
214} // namespace etl::chrono
215
216#endif // TETL_CHRONO_YEAR_MONTH_DAY_HPP
local_time< etl::chrono::days > local_days
Definition local_t.hpp:27
Definition abs.hpp:11
constexpr auto operator+(day const &d, days const &ds) noexcept -> day
Definition day.hpp:92
duration< int_least32_t, ratio< 31556952 > > months
Signed integer type of at least 20 bits.
Definition duration.hpp:371
constexpr auto operator==(duration< Rep1, Period1 > const &lhs, duration< Rep2, Period2 > const &rhs) -> bool
Compares two durations. Checks if lhs and rhs are equal, i.e. the number of ticks for the type common...
Definition duration.hpp:299
duration< int_least32_t, ratio< 86400 > > days
Signed integer type of at least 25 bits.
Definition duration.hpp:365
sys_time< chrono::days > sys_days
Definition system_clock.hpp:39
constexpr auto operator/(duration< Rep1, Period1 > const &lhs, duration< Rep2, Period2 > const &rhs) -> common_type_t< Rep1, Rep2 >
Performs basic arithmetic operations between two durations or between a duration and a tick count.
Definition duration.hpp:272
duration< int_least32_t, ratio< 2629746 > > years
Signed integer type of at least 17 bits.
Definition duration.hpp:374
constexpr auto operator-(day const &d, days const &ds) noexcept -> day
Definition day.hpp:102
TETL_BUILTIN_INT32 int32_t
Signed integer type with width of exactly 32 bits.
Definition int_t.hpp:17
TETL_BUILTIN_UINT32 uint32_t
Unsigned integer type with width of exactly 32 bits.
Definition uint_t.hpp:17
The class day represents a day in a month.
Definition day.hpp:20
Definition month_day.hpp:13
The class month represents a month in a year.
Definition month.hpp:21
Definition year_month_day_last.hpp:41
Definition year_month_day.hpp:17
constexpr year_month_day(chrono::year const &y, chrono::month const &m, chrono::day const &d) noexcept
Definition year_month_day.hpp:59
constexpr auto ok() const noexcept -> bool
Definition year_month_day.hpp:104
constexpr year_month_day(sys_days const &dp) noexcept
Definition year_month_day.hpp:73
constexpr auto month() const noexcept -> chrono::month
Definition year_month_day.hpp:90
constexpr year_month_day(local_days const &dp) noexcept
Definition year_month_day.hpp:78
constexpr year_month_day(year_month_day_last const &ymdl) noexcept
Definition year_month_day.hpp:66
constexpr auto year() const noexcept -> chrono::year
Definition year_month_day.hpp:88
constexpr auto operator+=(months const &m) noexcept -> year_month_day &
Definition year_month_day.hpp:160
constexpr auto operator-=(months const &m) noexcept -> year_month_day &
Definition year_month_day.hpp:166
constexpr auto day() const noexcept -> chrono::day
Definition year_month_day.hpp:92
Definition year_month.hpp:11
Definition year.hpp:13
static constexpr int digits
Definition numeric_limits.hpp:24