Embedded Template Library 1.0
Loading...
Searching...
No Matches
year_month_weekday.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2025 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_IN_CHRONO_H
32 #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H
33#endif
34
35namespace etl
36{
37 namespace chrono
38 {
39 //*************************************************************************
41 //*************************************************************************
43 {
44 public:
45
46 //*************************************************************************
48 //*************************************************************************
49 ETL_CONSTEXPR year_month_weekday()
50 : y()
51 , m()
52 , wdi()
53 {
54 }
55
56 //*************************************************************************
58 //*************************************************************************
59 ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::year& y_,
60 const etl::chrono::month& m_,
61 const etl::chrono::weekday_indexed& wdi_) ETL_NOEXCEPT
62 : y(y_)
63 , m(m_)
64 , wdi(wdi_)
65 {
66 }
67
68 //*************************************************************************
70 //*************************************************************************
71 ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::sys_days& sd) ETL_NOEXCEPT
72 {
73 // Extract year, month, and day
75
76 etl::chrono::year yr = ymd.year();
77 etl::chrono::month mth = ymd.month();
78 etl::chrono::day dy = ymd.day();
79
80 // Get the weekday from sys_days
82
83 // Count how many times this weekday has occurred in the month so far
84 // We walk backward from the given day in steps of 7 days
85 unsigned index = 1;
86
87 for (int offset = static_cast<int>(dy) - 7; offset > 0; offset -= 7)
88 {
89 ++index;
90 }
91
92 y = yr;
93 m = mth;
95 }
96
97 //*************************************************************************
99 //*************************************************************************
100 ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::local_days& ld) ETL_NOEXCEPT
101 {
102 year_month_weekday ymwd(sys_days(ld.time_since_epoch()));
103
104 y = ymwd.year();
105 m = ymwd.month();
106 wdi = ymwd.weekday_indexed();
107 }
108
109 //*************************************************************************
111 //*************************************************************************
112 ETL_NODISCARD
113 ETL_CONSTEXPR14 etl::chrono::year year() const ETL_NOEXCEPT
114 {
115 return y;
116 }
117
118 //*************************************************************************
120 //*************************************************************************
121 ETL_NODISCARD
122 ETL_CONSTEXPR14 etl::chrono::month month() const ETL_NOEXCEPT
123 {
124 return m;
125 }
126
127 //*************************************************************************
129 //*************************************************************************
130 ETL_NODISCARD
131 ETL_CONSTEXPR14 etl::chrono::weekday weekday() const ETL_NOEXCEPT
132 {
133 return wdi.weekday();
134 }
135
136 //*************************************************************************
138 //*************************************************************************
139 ETL_NODISCARD
140 ETL_CONSTEXPR14 unsigned index() const ETL_NOEXCEPT
141 {
142 return wdi.index();
143 }
144
145 //*************************************************************************
147 //*************************************************************************
148 ETL_NODISCARD
149 ETL_CONSTEXPR14 etl::chrono::weekday_indexed weekday_indexed() const ETL_NOEXCEPT
150 {
151 return wdi;
152 }
153
154 //*************************************************************************
156 //*************************************************************************
157 ETL_NODISCARD
158 ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT
159 {
160 return y.ok() && m.ok() && wdi.ok();
161 }
162
163 //***********************************************************************
165 //***********************************************************************
166 ETL_NODISCARD
167 ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
168 {
169 if (ok())
170 {
172 etl::chrono::year_month_day ymd{ ymwd.year(), ymwd.month(), etl::chrono::day(1) };
173
174 etl::chrono::sys_days sd = ymd;
175
176 unsigned int target_wd = ymwd.weekday().c_encoding();
177 unsigned int target_index = ymwd.index();
178
179 etl::chrono::weekday first_weekday(static_cast<int>(sd.time_since_epoch().count()));
180
181 int first_wd = first_weekday.c_encoding();
182 int offset = (target_wd - first_wd + 7) % 7;
183 int day_of_month = offset + static_cast<int>(target_index - 1) * 7;
184
185 etl::chrono::year_month_day result(year(), month(), etl::chrono::day(day_of_month));
186
187 return etl::chrono::sys_days(result);
188 }
189 else
190 {
191 return etl::chrono::sys_days();
192 }
193 }
194
195 //***********************************************************************
197 //***********************************************************************
198 ETL_NODISCARD
199 ETL_CONSTEXPR14 operator etl::chrono::local_days() const ETL_NOEXCEPT
200 {
201 return local_days(sys_days(*this).time_since_epoch());
202 }
203
204 private:
205
209 };
210
211 //*************************************************************************
213 //*************************************************************************
214 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::year_month_weekday& ymwd,
215 const etl::chrono::years& dy) ETL_NOEXCEPT
216 {
217 return etl::chrono::year_month_weekday(ymwd.year() + dy, ymwd.month(), ymwd.weekday_indexed());
218 }
219
220 //*************************************************************************
222 //*************************************************************************
223 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::years& dy,
224 const etl::chrono::year_month_weekday& ymwd) ETL_NOEXCEPT
225 {
226 return etl::chrono::year_month_weekday(ymwd.year() + dy, ymwd.month(), ymwd.weekday_indexed());
227 }
228
229 //*************************************************************************
231 //*************************************************************************
232 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::year_month_weekday& ymwd,
233 const etl::chrono::months& dm) ETL_NOEXCEPT
234 {
235 return etl::chrono::year_month_weekday(ymwd.year(), ymwd.month() + dm, ymwd.weekday_indexed());
236 }
237
238 //*************************************************************************
240 //*************************************************************************
241 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::months& dm,
242 const etl::chrono::year_month_weekday& ymwd) ETL_NOEXCEPT
243 {
244 return etl::chrono::year_month_weekday(ymwd.year(), ymwd.month() + dm, ymwd.weekday_indexed());
245 }
246
247 //*************************************************************************
249 //*************************************************************************
250 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator -(const etl::chrono::year_month_weekday& ymwd,
251 const etl::chrono::years& dy) ETL_NOEXCEPT
252 {
253 return etl::chrono::year_month_weekday(ymwd.year() - dy, ymwd.month(), ymwd.weekday_indexed());
254 }
255
256 //*************************************************************************
258 //*************************************************************************
259 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator -(const etl::chrono::year_month_weekday& ymwd,
260 const etl::chrono::months& dm) ETL_NOEXCEPT
261 {
262 return etl::chrono::year_month_weekday(ymwd.year(), ymwd.month() - dm, ymwd.weekday_indexed());
263 }
264
265 //*************************************************************************
267 //*************************************************************************
268 inline ETL_CONSTEXPR14 bool operator ==(const etl::chrono::year_month_weekday& lhs,
269 const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT
270 {
271 return (lhs.year() == rhs.year()) &&
272 (lhs.month() == rhs.month()) &&
273 (lhs.weekday() == rhs.weekday());
274 }
275
276 //*************************************************************************
278 //*************************************************************************
279 inline ETL_CONSTEXPR14 bool operator !=(const etl::chrono::year_month_weekday& lhs,
280 const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT
281 {
282 return !(lhs == rhs);
283 }
284
285 //*************************************************************************
287 //*************************************************************************
289 {
290 public:
291
292 //*************************************************************************
294 //*************************************************************************
295 ETL_CONSTEXPR14 year_month_weekday_last(const etl::chrono::year& y_,
296 const etl::chrono::month& m_,
297 const etl::chrono::weekday_last& wdl_) ETL_NOEXCEPT
298 : y(y_)
299 , m(m_)
300 , wdl(wdl_)
301 {
302 }
303
304 //*************************************************************************
306 //*************************************************************************
307 ETL_NODISCARD
308 ETL_CONSTEXPR14 etl::chrono::year year() const ETL_NOEXCEPT
309 {
310 return y;
311 }
312
313 //*************************************************************************
315 //*************************************************************************
316 ETL_NODISCARD
317 ETL_CONSTEXPR14 etl::chrono::month month() const ETL_NOEXCEPT
318 {
319 return m;
320 }
321
322 //*************************************************************************
324 //*************************************************************************
325 ETL_NODISCARD
326 ETL_CONSTEXPR14 etl::chrono::weekday weekday() const ETL_NOEXCEPT
327 {
328 return wdl.weekday();
329 }
330
331 //*************************************************************************
333 //*************************************************************************
334 ETL_NODISCARD
335 ETL_CONSTEXPR14 etl::chrono::weekday_last weekday_last() const ETL_NOEXCEPT
336 {
337 return wdl;
338 }
339
340 //*************************************************************************
342 //*************************************************************************
343 ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last& operator +=(const etl::chrono::years& dy) ETL_NOEXCEPT
344 {
345 y += dy;
346
347 return *this;
348 }
349
350 //*************************************************************************
352 //*************************************************************************
353 ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last& operator +=(const etl::chrono::months& dm) ETL_NOEXCEPT
354 {
355 m += dm;
356
357 return *this;
358 }
359
360 //*************************************************************************
362 //*************************************************************************
363 ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last& operator -=(const etl::chrono::years& dy) ETL_NOEXCEPT
364 {
365 y -= dy;
366
367 return *this;
368 }
369
370 //*************************************************************************
372 //*************************************************************************
373 ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last& operator -=(const etl::chrono::months& dm) ETL_NOEXCEPT
374 {
375 m -= dm;
376
377 return *this;
378 }
379
380 //*************************************************************************
382 //*************************************************************************
383 ETL_NODISCARD
384 ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
385 {
386 // Get the last day of the month
388 etl::chrono::day last_day = ymdl.day();
389
390 // Walk backward from the last day to find the last occurrence of the target weekday
391 unsigned d = static_cast<unsigned>(last_day);
392
393 for (; d >= 1; --d)
394 {
396 etl::chrono::sys_days ymd_sys_days = static_cast<etl::chrono::sys_days>(ymd);
397 etl::chrono::weekday wd(static_cast<int>(ymd_sys_days.time_since_epoch().count()));
398
399 if (wd == weekday())
400 {
401 return ymd_sys_days;
402 }
403 }
404
405 // If not found (should not happen for valid input), return epoch
406 return etl::chrono::sys_days();
407 }
408
409 //*************************************************************************
411 //*************************************************************************
412 ETL_NODISCARD
413 ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT
414 {
415 return local_days(sys_days(*this).time_since_epoch());
416 }
417
418 private:
419
423 };
424
425 //*************************************************************************
427 //*************************************************************************
429 const etl::chrono::years& dy) ETL_NOEXCEPT
430 {
431 return etl::chrono::year_month_weekday_last(ymwdl.year() + dy, ymwdl.month(), ymwdl.weekday_last());
432 }
433
434 //*************************************************************************
436 //*************************************************************************
437 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator +(const etl::chrono::years& dy,
438 const etl::chrono::year_month_weekday_last& ymwdl) ETL_NOEXCEPT
439 {
440 return etl::chrono::year_month_weekday_last(ymwdl.year() + dy, ymwdl.month(), ymwdl.weekday_last());
441 }
442
443 //*************************************************************************
445 //*************************************************************************
447 const etl::chrono::months& dm) ETL_NOEXCEPT
448 {
449 return etl::chrono::year_month_weekday_last(ymwdl.year(), ymwdl.month() + dm, ymwdl.weekday_last());
450 }
451
452 //*************************************************************************
454 //*************************************************************************
455 inline ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator +(const etl::chrono::months& dm,
456 const etl::chrono::year_month_weekday_last& ymwdl) ETL_NOEXCEPT
457 {
458 return etl::chrono::year_month_weekday_last(ymwdl.year(), ymwdl.month() + dm, ymwdl.weekday_last());
459 }
460
461 //*************************************************************************
463 //*************************************************************************
465 const etl::chrono::years& dy) ETL_NOEXCEPT
466 {
467 return etl::chrono::year_month_weekday_last(ymwdl.year() - dy, ymwdl.month(), ymwdl.weekday_last());
468 }
469
470 //*************************************************************************
472 //*************************************************************************
474 const etl::chrono::months& dm) ETL_NOEXCEPT
475 {
476 return etl::chrono::year_month_weekday_last(ymwdl.year(), ymwdl.month() - dm, ymwdl.weekday_last());
477 }
478
479 //*************************************************************************
481 //*************************************************************************
482 inline ETL_CONSTEXPR14 bool operator ==(const etl::chrono::year_month_weekday_last& lhs,
483 const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT
484 {
485 return (lhs.year() == rhs.year()) &&
486 (lhs.month() == rhs.month()) &&
487 (lhs.weekday() == rhs.weekday());
488 }
489
490 //*************************************************************************
492 //*************************************************************************
493 inline ETL_CONSTEXPR14 bool operator !=(const etl::chrono::year_month_weekday_last& lhs,
494 const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT
495 {
496 return !(lhs == rhs);
497 }
498 }
499
500 //*************************************************************************
502 //*************************************************************************
503#if ETL_USING_8BIT_TYPES
504 template <>
505 struct hash<etl::chrono::year_month_weekday>
506 {
507 size_t operator()(const etl::chrono::year_month_weekday& ymwd) const
508 {
509 etl::chrono::year::rep y = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(ymwd.year()));
510 etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(ymwd.month()));
511 unsigned int wd = ymwd.weekday().c_encoding();
512
513 uint8_t buffer[sizeof(y) + sizeof(m) + sizeof(wd)];
514
515 memcpy(buffer, &y, sizeof(y));
516 memcpy(buffer + sizeof(y), &m, sizeof(m));
517 memcpy(buffer + sizeof(y) + sizeof(m), &wd, sizeof(wd));
518
519 return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(y) + sizeof(m) + sizeof(wd));
520 }
521 };
522#endif
523
524 //*************************************************************************
526 //*************************************************************************
527#if ETL_USING_8BIT_TYPES
528 template <>
529 struct hash<etl::chrono::year_month_weekday_last>
530 {
531 size_t operator()(const etl::chrono::year_month_weekday_last& ymwdl) const
532 {
533 etl::chrono::year::rep y = static_cast<etl::chrono::year::rep>(static_cast<unsigned>(ymwdl.year()));
534 etl::chrono::month::rep m = static_cast<etl::chrono::month::rep>(static_cast<unsigned>(ymwdl.month()));
535 unsigned int wd = ymwdl.weekday().c_encoding();
536
537 uint8_t buffer[sizeof(y) + sizeof(m) + sizeof(wd)];
538
539 memcpy(buffer, &y, sizeof(y));
540 memcpy(buffer + sizeof(y), &m, sizeof(m));
541 memcpy(buffer + sizeof(y) + sizeof(m), &wd, sizeof(wd));
542
543 return etl::private_hash::generic_hash<size_t>(buffer, buffer + sizeof(y) + sizeof(m) + sizeof(wd));
544 }
545 };
546#endif
547}
548
day
Definition day.h:43
Spaceship operator.
Definition month_day.h:215
month
Definition month.h:54
ETL_NODISCARD ETL_CONSTEXPR14 duration time_since_epoch() const ETL_NOEXCEPT
Returns a duration representing the amount of time between this and the clock's epoch.
Definition time_point.h:100
weekday_indexed
Definition weekday.h:344
weekday_last
Definition weekday.h:439
weekday
Definition weekday.h:54
ETL_NODISCARD ETL_CONSTEXPR14 unsigned c_encoding() const ETL_NOEXCEPT
Get the C encoding of the weekday.
Definition weekday.h:212
ETL_CONSTEXPR weekday() ETL_NOEXCEPT
Default constructor.
Definition weekday.h:60
Spaceship operator.
Definition year_month_day.h:473
year_month_day
Definition year_month_day.h:45
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::month month() const ETL_NOEXCEPT
Returns the month.
Definition year_month_day.h:150
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::day day() const ETL_NOEXCEPT
Returns the day.
Definition year_month_day.h:159
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::year year() const ETL_NOEXCEPT
Returns the year.
Definition year_month_day.h:141
year_month_weekday_last
Definition year_month_weekday.h:289
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::weekday weekday() const ETL_NOEXCEPT
Returns the weekday.
Definition year_month_weekday.h:326
ETL_CONSTEXPR14 year_month_weekday_last(const etl::chrono::year &y_, const etl::chrono::month &m_, const etl::chrono::weekday_last &wdl_) ETL_NOEXCEPT
Construct from year, month, weekday_last.
Definition year_month_weekday.h:295
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::weekday_last weekday_last() const ETL_NOEXCEPT
Returns the weekday_last.
Definition year_month_weekday.h:335
ETL_NODISCARD ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
Converts to etl::chrono::sys_days.
Definition year_month_weekday.h:384
ETL_NODISCARD ETL_CONSTEXPR14 operator etl::chrono::local_days() const ETL_NOEXCEPT
Converts to etl::chrono::local_days.
Definition year_month_weekday.h:413
ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last & operator-=(const etl::chrono::years &dy) ETL_NOEXCEPT
Subtracts etl::chrono::years.
Definition year_month_weekday.h:363
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::month month() const ETL_NOEXCEPT
Returns the month.
Definition year_month_weekday.h:317
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::year year() const ETL_NOEXCEPT
Returns the year.
Definition year_month_weekday.h:308
ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last & operator+=(const etl::chrono::years &dy) ETL_NOEXCEPT
Adds etl::chrono::years.
Definition year_month_weekday.h:343
year_month_weekday
Definition year_month_weekday.h:43
ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::year &y_, const etl::chrono::month &m_, const etl::chrono::weekday_indexed &wdi_) ETL_NOEXCEPT
Construct from month, day, and weekday_indexed.
Definition year_month_weekday.h:59
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::weekday weekday() const ETL_NOEXCEPT
Returns the weekday.
Definition year_month_weekday.h:131
ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::sys_days &sd) ETL_NOEXCEPT
Construct from sys_days.
Definition year_month_weekday.h:71
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::year year() const ETL_NOEXCEPT
Returns the year.
Definition year_month_weekday.h:113
ETL_NODISCARD ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT
Converts to etl::chrono::sys_days.
Definition year_month_weekday.h:167
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::weekday_indexed weekday_indexed() const ETL_NOEXCEPT
Returns the weekday_indexed.
Definition year_month_weekday.h:149
ETL_CONSTEXPR14 year_month_weekday(const etl::chrono::local_days &ld) ETL_NOEXCEPT
Construct from local_days.
Definition year_month_weekday.h:100
ETL_NODISCARD ETL_CONSTEXPR14 operator etl::chrono::local_days() const ETL_NOEXCEPT
Converts to etl::chrono::local_days.
Definition year_month_weekday.h:199
ETL_NODISCARD ETL_CONSTEXPR14 unsigned index() const ETL_NOEXCEPT
Returns the weekday index.
Definition year_month_weekday.h:140
ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::month month() const ETL_NOEXCEPT
Returns the month.
Definition year_month_weekday.h:122
ETL_NODISCARD ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT
Returns true if the year/month/day is valid.
Definition year_month_weekday.h:158
ETL_CONSTEXPR year_month_weekday()
Default constructor.
Definition year_month_weekday.h:49
year
Definition year.h:43
bitset_ext
Definition absolute.h:39