ORIGINAL
Loading...
Searching...
No Matches
zeit.h
Go to the documentation of this file.
1#ifndef ORIGINAL_ZEIT_H
2#define ORIGINAL_ZEIT_H
3#include <cmath>
4#include "config.h"
5#include "comparable.h"
6#include "hash.h"
7#include "printable.h"
8#include "error.h"
9#include <iomanip>
10#ifdef ORIGINAL_COMPILER_GCC
11#include <ctime>
12#endif
13
33namespace original {
40 class time final {
41 public:
44
45 private:
47 static constexpr time_val_type UNIT_FACTOR_BASE = 1;
48
50 static constexpr time_val_type UNIT_FACTOR[] {
51 UNIT_FACTOR_BASE,
52 UNIT_FACTOR_BASE * 1000,
53 UNIT_FACTOR_BASE * 1000 * 1000,
54 UNIT_FACTOR_BASE * 1000 * 1000 * 1000,
55 UNIT_FACTOR_BASE * 1000 * 1000 * 1000 * 60,
56 UNIT_FACTOR_BASE * 1000 * 1000 * 1000 * 60 * 60,
57 UNIT_FACTOR_BASE * 1000 * 1000 * 1000 * 60 * 60 * 24,
58 };
59
60 public:
65 enum class unit {
69 SECOND,
70 MINUTE,
71 HOUR,
72 DAY,
73 };
74
76 static constexpr auto NANOSECOND = unit::NANOSECOND;
78 static constexpr auto MICROSECOND = unit::MICROSECOND;
80 static constexpr auto MILLISECOND = unit::MILLISECOND;
82 static constexpr auto SECOND = unit::SECOND;
84 static constexpr auto MINUTE = unit::MINUTE;
86 static constexpr auto HOUR = unit::HOUR;
88 static constexpr auto DAY = unit::DAY;
89
91 static constexpr time_val_type FACTOR_NANOSECOND = UNIT_FACTOR[static_cast<ul_integer>(NANOSECOND)];
93 static constexpr time_val_type FACTOR_MICROSECOND = UNIT_FACTOR[static_cast<ul_integer>(MICROSECOND)];
95 static constexpr time_val_type FACTOR_MILLISECOND = UNIT_FACTOR[static_cast<ul_integer>(MILLISECOND)];
97 static constexpr time_val_type FACTOR_SECOND = UNIT_FACTOR[static_cast<ul_integer>(SECOND)];
99 static constexpr time_val_type FACTOR_MINUTE = UNIT_FACTOR[static_cast<ul_integer>(MINUTE)];
101 static constexpr time_val_type FACTOR_HOUR = UNIT_FACTOR[static_cast<ul_integer>(HOUR)];
103 static constexpr time_val_type FACTOR_DAY = UNIT_FACTOR[static_cast<ul_integer>(DAY)];
104
106 static constexpr integer DAYS_LEAP_YEAR = 366;
108 static constexpr integer DAYS_COMMON_YEAR = 365;
109
111 static constexpr integer EPOCH_YEAR = 1970;
113 static constexpr integer EPOCH_MONTH = 1;
115 static constexpr integer EPOCH_DAY = 1;
116
118 class point;
120 class UTCTime;
121
131 class duration final
132 : public comparable<duration>,
133 public hashable<duration>,
134 public printable {
135 time_val_type nano_seconds_;
136
137 public:
138 friend class point;
139
141 static const duration ZERO;
142
148 explicit duration(time_val_type val = 0, unit unit = MILLISECOND);
149
150#ifdef ORIGINAL_COMPILER_GCC
158 explicit duration(const timespec& ts);
159#endif
160
162 duration(const duration& other) = default;
163
165 duration& operator=(const duration& other) = default;
166
171 duration(duration&& other) noexcept;
172
178 duration& operator=(duration&& other) noexcept;
179
185 [[nodiscard]] time_val_type value(unit unit = MILLISECOND) const;
186
192 [[nodiscard]] integer compareTo(const duration& other) const override;
193
198 u_integer toHash() const noexcept override;
199
204 std::string className() const override;
205
211 std::string toString(bool enter) const override;
212
213#ifdef ORIGINAL_COMPILER_GCC
219 explicit operator timespec() const;
220
221 timespec toTimespec() const;
222#endif
223
229
235 duration operator++(int postfix);
236
242
248 duration operator--(int postfix);
249
255 duration& operator+=(const duration& other);
256
262 duration& operator-=(const duration& other);
263
270
277
283 duration& operator/=(const duration& other);
284
291 [[nodiscard]] floating div(time_val_type factor, unit unit = MILLISECOND) const;
292
298 [[nodiscard]] floating div(const duration& other) const;
299
305 friend duration operator-(const duration& d);
306
313 friend duration operator+(const duration& lhs, const duration& rhs);
314
321 friend duration operator-(const duration& lhs, const duration& rhs);
322
329 friend duration operator*(const duration& d, time_val_type factor);
330
337 friend duration operator*(time_val_type factor, const duration& d);
338
345 friend duration operator/(const duration& d, time_val_type factor);
346
353 friend duration operator/(const duration& lhs, const duration& rhs);
354
360 friend duration abs(const duration& d);
361 };
362
371 class point final
372 : public comparable<point>,
373 public hashable<point>,
374 public printable {
375 duration nano_since_epoch_;
376
377 public:
378 friend class UTCTime;
379
384 static point now();
385
391 explicit point(time_val_type val = 0, unit unit = MILLISECOND);
392
397 explicit point(duration d);
398
399#ifdef ORIGINAL_COMPILER_GCC
405 explicit point(const timespec& ts);
406#endif
407
413 [[nodiscard]] time_val_type value(unit unit = MILLISECOND) const noexcept;
414
420 [[nodiscard]] integer compareTo(const point& other) const override;
421
426 u_integer toHash() const noexcept override;
427
432 std::string className() const override;
433
439 std::string toString(bool enter) const override;
440
441#ifdef ORIGINAL_COMPILER_GCC
447 explicit operator timespec() const;
448
449 timespec toTimespec() const;
450#endif
451
456 point& operator++();
457
463 point operator++(int postfix);
464
469 point& operator--();
470
476 point operator--(int postfix);
477
483 point& operator+=(const duration& d);
484
490 point& operator-=(const duration& d);
491
498 friend point operator+(const point& p, const duration& d);
499
500 friend point operator+(const duration& d, const point& p);
501
508 friend point operator-(const point& p, const duration& d);
509
516 friend duration operator-(const point& lhs, const point& rhs);
517 };
518
531 class UTCTime final
532 : public comparable<UTCTime>,
533 public hashable<UTCTime>,
534 public printable {
535
536 integer year_{};
537 integer month_{};
538 integer day_{};
539 integer hour_{};
540 integer minute_{};
541 integer second_{};
542
547 enum class calendar : integer {
548 YEAR,
549 MONTH,
550 };
551
556 enum class weekdays : integer {
557 SATURDAY,
558 SUNDAY,
559 MONDAY,
560 TUESDAY,
561 WEDNESDAY,
562 THURSDAY,
563 FRIDAY,
564 };
565
567 static constexpr integer DAYS_OF_MONTH[] {
568 31, 28, 31, 30, 31, 30,
569 31, 31, 30, 31, 30, 31
570 };
571
577 static constexpr bool isValidYear(integer year);
578
584 static constexpr bool isValidMonth(integer month);
585
591 static constexpr bool isValidDay(integer day);
592
602 void set(integer year, integer month, integer day,
603 integer hour, integer minute, integer second);
604
605 public:
606 friend time;
607
609 static constexpr auto SATURDAY = weekdays::SATURDAY;
611 static constexpr auto SUNDAY = weekdays::SUNDAY;
613 static constexpr auto MONDAY = weekdays::MONDAY;
615 static constexpr auto TUESDAY = weekdays::TUESDAY;
617 static constexpr auto WEDNESDAY = weekdays::WEDNESDAY;
619 static constexpr auto THURSDAY = weekdays::THURSDAY;
621 static constexpr auto FRIDAY = weekdays::FRIDAY;
622
624 static constexpr integer DAYS_WEEK = 7;
626 static constexpr integer MONTHS_YEAR = std::size(DAYS_OF_MONTH);
628 static constexpr integer YEARS_CENTURY = 100;
629
631 static const UTCTime EPOCH;
632
637 static UTCTime now();
638
644 static integer localZonedOffset();
645
651 static UTCTime localNow();
652
658 static constexpr bool isLeapYear(integer year);
659
667 static constexpr integer daysOfMonth(integer year, integer month);
668
677 static constexpr weekdays weekday(integer year, integer month, integer day);
678
686 static constexpr bool isValidYMD(integer year, integer month, integer day);
687
695 static constexpr bool isValidHMS(integer hour, integer minute, integer second);
696
707 static constexpr bool isValid(integer year, integer month, integer day,
708 integer hour, integer minute, integer second);
709
714 [[nodiscard]] bool isLeapYear() const;
715
720 [[nodiscard]] weekdays weekday() const;
721
730 explicit UTCTime();
731
743 explicit UTCTime(integer year, integer month, integer day);
744
759 explicit UTCTime(integer year, integer month, integer day,
760 integer hour, integer minute, integer second);
761
772 explicit UTCTime(const point& p);
773
775 UTCTime(const UTCTime& other) = default;
776
778 UTCTime& operator=(const UTCTime& other) = default;
779
784 UTCTime(UTCTime&& other) noexcept;
785
791 UTCTime& operator=(UTCTime&& other) noexcept;
792
803 UTCTime date() const;
804
810 integer value(unit unit) const;
811
817 integer value(calendar calendar) const;
818
825 explicit operator point() const;
826
827 point toPoint() const;
828
834 integer compareTo(const UTCTime& other) const override;
835
840 u_integer toHash() const noexcept override;
841
846 std::string className() const override;
847
853 std::string toString(bool enter) const override;
854
861 friend UTCTime operator+(const UTCTime& t, const duration& d);
862
869 friend UTCTime operator+(const duration& d, const UTCTime& t);
870
877 friend UTCTime operator-(const UTCTime& t, const duration& d);
878
885 friend duration operator-(const UTCTime& lhs, const UTCTime& rhs);
886 };
887
889 static constexpr auto MONTH = UTCTime::calendar::MONTH;
891 static constexpr auto YEAR = UTCTime::calendar::YEAR;
892 };
893
895 inline const time::duration time::duration::ZERO = duration{};
896
897 time::duration nanoseconds(time::time_val_type val = 1);
898
899 time::duration microseconds(time::time_val_type val = 1);
900
901 time::duration milliseconds(time::time_val_type val = 1);
902
903 time::duration seconds(time::time_val_type val = 1);
904
905 time::duration minutes(time::time_val_type val = 1);
906
907 time::duration hours(time::time_val_type val = 1);
908
910
912
914
916
918
920
922
924
926
928
930
932
933 time::duration operator-(const time::point& lhs, const time::point& rhs);
934
937
938 time::UTCTime operator+(const time::UTCTime& t, const time::duration& d);
939
940 time::UTCTime operator+(const time::duration& d, const time::UTCTime& t);
941
942 time::UTCTime operator-(const time::UTCTime& t, const time::duration& d);
943
944 time::duration operator-(const time::UTCTime& lhs, const time::UTCTime& rhs);
945
950 namespace literals {
956 inline time::duration operator""_ns(const unsigned long long val) {
957 return time::duration(static_cast<time::time_val_type>(val), time::NANOSECOND);
958 }
959
965 inline time::duration operator""_us(const unsigned long long val) {
966 return time::duration(static_cast<time::time_val_type>(val), time::MICROSECOND);
967 }
968
974 inline time::duration operator""_ms(const unsigned long long val) {
975 return time::duration(static_cast<time::time_val_type>(val), time::MILLISECOND);
976 }
977
983 inline time::duration operator""_s(const unsigned long long val) {
984 return time::duration(static_cast<time::time_val_type>(val), time::SECOND);
985 }
986
992 inline time::duration operator""_min(const unsigned long long val) {
993 return time::duration(static_cast<time::time_val_type>(val), time::MINUTE);
994 }
995
1001 inline time::duration operator""_h(const unsigned long long val) {
1002 return time::duration(static_cast<time::time_val_type>(val), time::HOUR);
1003 }
1004
1010 inline time::duration operator""_d(const unsigned long long val) {
1011 return time::duration(static_cast<time::time_val_type>(val), time::DAY);
1012 }
1013
1019 inline time::duration operator""_ns(const long double val) {
1020 return time::duration(std::llround(val * time::FACTOR_NANOSECOND), time::NANOSECOND);
1021 }
1022
1028 inline time::duration operator""_us(const long double val) {
1029 return time::duration(std::llround(val * time::FACTOR_MICROSECOND), time::NANOSECOND);
1030 }
1031
1037 inline time::duration operator""_ms(const long double val) {
1038 return time::duration(std::llround(val * time::FACTOR_MILLISECOND), time::NANOSECOND);
1039 }
1040
1046 inline time::duration operator""_s(const long double val) {
1047 return time::duration(std::llround(val * time::FACTOR_SECOND), time::NANOSECOND);
1048 }
1049
1055 inline time::duration operator""_min(const long double val) {
1056 return time::duration(std::llround(val * time::FACTOR_MINUTE), time::NANOSECOND);
1057 }
1058
1064 inline time::duration operator""_h(const long double val) {
1065 return time::duration(std::llround(val * time::FACTOR_HOUR), time::NANOSECOND);
1066 }
1067
1073 inline time::duration operator""_d(const long double val) {
1074 return time::duration(std::llround(val * time::FACTOR_DAY), time::NANOSECOND);
1075 }
1076 }
1077}
1078
1080 switch (unit) {
1081 case unit::DAY:
1082 this->nano_seconds_ = FACTOR_DAY * val;
1083 break;
1084 case unit::HOUR:
1085 this->nano_seconds_ = FACTOR_HOUR * val;
1086 break;
1087 case unit::MINUTE:
1088 this->nano_seconds_ = FACTOR_MINUTE * val;
1089 break;
1090 case unit::SECOND:
1091 this->nano_seconds_ = FACTOR_SECOND * val;
1092 break;
1093 case unit::MILLISECOND:
1094 this->nano_seconds_ = FACTOR_MILLISECOND * val;
1095 break;
1096 case unit::MICROSECOND:
1097 this->nano_seconds_ = FACTOR_MICROSECOND * val;
1098 break;
1099 case unit::NANOSECOND:
1100 this->nano_seconds_ = FACTOR_NANOSECOND * val;
1101 break;
1102 default:
1103 throw valueError("Invalid time unit specified for duration construction");
1104 }
1105}
1106
1107#ifdef ORIGINAL_COMPILER_GCC
1108inline original::time::duration::duration(const timespec& ts)
1109 : nano_seconds_(ts.tv_sec * FACTOR_SECOND + ts.tv_nsec) {}
1110#endif
1111
1113 this->operator=(std::move(other));
1114}
1115
1118 if (this == &other)
1119 return *this;
1120
1121 this->nano_seconds_ = other.nano_seconds_;
1122 other.nano_seconds_ = 0;
1123 return *this;
1124}
1125
1128 time_val_type val = this->nano_seconds_;
1129 switch (unit) {
1130 case unit::DAY:
1131 val /= FACTOR_DAY;
1132 break;
1133 case unit::HOUR:
1134 val /= FACTOR_HOUR;
1135 break;
1136 case unit::MINUTE:
1137 val /= FACTOR_MINUTE;
1138 break;
1139 case unit::SECOND:
1140 val /= FACTOR_SECOND;
1141 break;
1142 case unit::MILLISECOND:
1143 val /= FACTOR_MILLISECOND;
1144 break;
1145 case unit::MICROSECOND:
1146 val /= FACTOR_MICROSECOND;
1147 break;
1148 case unit::NANOSECOND:
1149 val /= FACTOR_NANOSECOND;
1150 break;
1151 default:
1152 throw valueError("Invalid time unit specified for duration value conversion");
1153 }
1154 return val;
1155}
1156
1157inline original::integer
1159 if (this->nano_seconds_ == other.nano_seconds_)
1160 return 0;
1161 return this->nano_seconds_ > other.nano_seconds_ ? 1 : -1;
1162}
1163
1166 return hash<time_val_type>::hashFunc(this->nano_seconds_);
1167}
1168
1169inline std::string original::time::duration::className() const {
1170 return "time::duration";
1171}
1172
1173inline std::string original::time::duration::toString(const bool enter) const {
1174 std::stringstream ss;
1175 ss << "(" << this->className() << " " << this->nano_seconds_ << "ns)";
1176 if (enter)
1177 ss << "\n";
1178 return ss.str();
1179}
1180
1181#ifdef ORIGINAL_COMPILER_GCC
1182inline original::time::duration::operator timespec() const
1183{
1184 auto nanoseconds = this->value(NANOSECOND);
1185 const auto seconds = nanoseconds / FACTOR_SECOND;
1186 nanoseconds %= FACTOR_SECOND;
1187 return timespec{seconds, static_cast<long>(nanoseconds)}; //NOLINT: The remaining nanosecond value is within the range of type long.
1188}
1189
1190inline timespec original::time::duration::toTimespec() const
1191{
1192 return static_cast<timespec>(*this);
1193}
1194#endif
1195
1198 this->nano_seconds_ += 1;
1199 return *this;
1200}
1201
1204 duration res{*this};
1205 this->nano_seconds_ += 1;
1206 return res;
1207}
1208
1211 this->nano_seconds_ -= 1;
1212 return *this;
1213}
1214
1217 duration res{*this};
1218 this->nano_seconds_ -= 1;
1219 return res;
1220}
1221
1224 this->nano_seconds_ += other.nano_seconds_;
1225 return *this;
1226}
1227
1230 this->nano_seconds_ -= other.nano_seconds_;
1231 return *this;
1232}
1233
1236 this->nano_seconds_ *= factor;
1237 return *this;
1238}
1239
1242 this->nano_seconds_ /= factor;
1243 return *this;
1244}
1245
1248 this->nano_seconds_ /= other.nano_seconds_;
1249 return *this;
1250}
1251
1252inline original::floating
1254 return this->div(duration{factor, unit});
1255}
1256
1257inline original::floating
1259 return static_cast<floating>(this->nano_seconds_) / static_cast<floating>(other.nano_seconds_);
1260}
1261
1263original::nanoseconds(const time::time_val_type val) {
1264 return time::duration{val, time::NANOSECOND};
1265}
1266
1268original::microseconds(const time::time_val_type val) {
1269 return time::duration{val, time::MICROSECOND};
1270}
1271
1273original::milliseconds(const time::time_val_type val) {
1274 return time::duration{val, time::MILLISECOND};
1275}
1276
1278original::seconds(const time::time_val_type val) {
1279 return time::duration{val, time::SECOND};
1280}
1281
1283original::minutes(const time::time_val_type val) {
1284 return time::duration{val, time::MINUTE};
1285}
1286
1288original::hours(const time::time_val_type val) {
1289 return time::duration{val, time::HOUR};
1290}
1291
1293original::days(const time::time_val_type val) {
1294 return time::duration{val, time::DAY};
1295}
1296
1299 time::duration res{d};
1300 res.nano_seconds_ = -res.nano_seconds_;
1301 return res;
1302}
1303
1306 time::duration d{lhs};
1307 d += rhs;
1308 return d;
1309}
1310
1313 time::duration d{lhs};
1314 d -= rhs;
1315 return d;
1316}
1317
1320 time::duration res{d};
1321 res *= factor;
1322 return res;
1323}
1324
1327 return d * factor;
1328}
1329
1332 time::duration res{d};
1333 res /= factor;
1334 return res;
1335}
1336
1339 time::duration d{lhs};
1340 d /= rhs;
1341 return d;
1342}
1343
1346 time::time_val_type val = d.nano_seconds_;
1347 val = val < 0 ? -val : val;
1348 return time::duration{val, time::NANOSECOND};
1349}
1350
1353#if ORIGINAL_COMPILER_GCC || (ORIGINAL_COMPILER_CLANG && ORIGINAL_PLATFORM_LINUX)
1354 timespec ts{};
1355 clock_gettime(CLOCK_REALTIME, &ts);
1356 return point{ts};
1357#elif ORIGINAL_PLATFORM_APPLE
1358 struct timeval tv;
1359 gettimeofday(&tv, nullptr);
1360 time_val_type ns = tv.tv_sec * FACTOR_SECOND + tv.tv_usec * FACTOR_MICROSECOND;
1361 return point(ns, NANOSECOND);
1362#else
1363 // Other implements not complete
1364 return point();
1365#endif
1366}
1367
1369 : nano_since_epoch_(val, unit) {}
1370
1372 : nano_since_epoch_(std::move(d)) {}
1373
1374#ifdef ORIGINAL_COMPILER_GCC
1375inline original::time::point::point(const timespec& ts)
1376 : nano_since_epoch_(ts) {}
1377#endif
1378
1381 return this->nano_since_epoch_.value(unit);
1382}
1383
1384inline original::integer
1386 return this->nano_since_epoch_.compareTo(other.nano_since_epoch_);
1387}
1388
1391 return this->nano_since_epoch_.toHash();
1392}
1393
1394inline std::string original::time::point::className() const {
1395 return "time::point";
1396}
1397
1398inline std::string
1399original::time::point::toString(const bool enter) const {
1400 std::stringstream ss;
1401 ss << "(" << this->className() << " " << this->nano_since_epoch_.nano_seconds_ << ")";
1402 if (enter)
1403 ss << "\n";
1404 return ss.str();
1405}
1406
1407#ifdef ORIGINAL_COMPILER_GCC
1408inline original::time::point::operator timespec() const
1409{
1410 return static_cast<timespec>(this->nano_since_epoch_);
1411}
1412
1413inline timespec original::time::point::toTimespec() const
1414{
1415 return static_cast<timespec>(*this);
1416}
1417#endif
1418
1421 ++this->nano_since_epoch_;
1422 return *this;
1423}
1424
1427 point res{*this};
1428 ++this->nano_since_epoch_;
1429 return res;
1430}
1431
1434 --this->nano_since_epoch_;
1435 return *this;
1436}
1437
1440 point res{*this};
1441 --this->nano_since_epoch_;
1442 return res;
1443}
1444
1447 this->nano_since_epoch_ += d;
1448 return *this;
1449}
1450
1453 this->nano_since_epoch_ -= d;
1454 return *this;
1455}
1456
1459 time::point res{p};
1460 res -= d;
1461 return res;
1462}
1463
1466 return lhs.nano_since_epoch_ - rhs.nano_since_epoch_;
1467}
1468
1471 time::point res{p};
1472 res += d;
1473 return res;
1474}
1475
1477original::operator+(const time::duration &d, const time::point &p) {
1478 return p + d;
1479}
1480
1481constexpr bool
1482original::time::UTCTime::isValidYear(const integer year) {
1483 return 0 <= year;
1484}
1485
1486constexpr bool
1487original::time::UTCTime::isValidMonth(const integer month) {
1488 return 1 <= month && month <= 12;
1489}
1490
1491constexpr bool
1492original::time::UTCTime::isValidDay(const integer day) {
1493 return 1 <= day && day <= 31;
1494}
1495
1496inline void original::time::UTCTime::set(const integer year, const integer month, const integer day,
1497 const integer hour, const integer minute, const integer second) {
1498 this->year_ = year;
1499 this->month_ = month;
1500 this->day_ = day;
1501 this->hour_ = hour;
1502 this->minute_ = minute;
1503 this->second_ = second;
1504}
1505
1510
1511inline original::integer
1513 integer offset_seconds = 0;
1514#if ORIGINAL_COMPILER_GCC
1515 integer t = std::time(nullptr);
1516 tm local_tm{};
1517#if ORIGINAL_PLATFORM_WINDOWS
1518 localtime_s(&local_tm, &t);
1519#else
1520 localtime_r(&t, &local_tm);
1521#endif
1522
1523 tm utc_tm{};
1524#if ORIGINAL_PLATFORM_WINDOWS
1525 gmtime_s(&utc_tm, &t);
1526#else
1527 gmtime_r(&t, &utc_tm);
1528#endif
1529
1530 offset_seconds = static_cast<integer>(difftime(mktime(&local_tm), mktime(&utc_tm)));
1531#else
1532 TIME_ZONE_INFORMATION tz_info;
1533 DWORD result = GetTimeZoneInformation(&tz_info);
1534 if (result != TIME_ZONE_ID_INVALID) {
1535 offset_seconds = -tz_info.Bias * (FACTOR_MINUTE / FACTOR_SECOND);
1536 if (result == TIME_ZONE_ID_DAYLIGHT) {
1537 offset_seconds -= tz_info.DaylightBias * (FACTOR_MINUTE / FACTOR_SECOND);
1538 }
1539 }
1540#endif
1541 return offset_seconds / (FACTOR_HOUR / FACTOR_SECOND);
1542}
1543
1546 return now() + duration{localZonedOffset(), HOUR};
1547}
1548
1549constexpr bool
1551 if (!isValidYear(year))
1552 return false;
1553 return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
1554}
1555
1556constexpr original::integer
1558 if (!isValidYear(year) || !isValidMonth(month))
1559 throw valueError();
1560
1561 if (month == 2 && isLeapYear(year)){
1562 return DAYS_OF_MONTH[month - 1] + 1;
1563 }
1564 return DAYS_OF_MONTH[month - 1];
1565}
1566
1567constexpr original::time::UTCTime::weekdays
1568original::time::UTCTime::weekday(const integer year, const integer month, const integer day) {
1569 if (!isValidYMD(year, month, day))
1570 throw valueError("Invalid date for weekday calculation: " +
1571 formatString(year) + "-" + formatString(month) + "-" + formatString(day));
1572
1573 integer corrected_year, corrected_month;
1574 if (month == 1 || month == 2){
1575 corrected_year = year - 1;
1576 corrected_month = MONTHS_YEAR + month;
1577 } else {
1578 corrected_year = year;
1579 corrected_month = month;
1580 }
1581 const integer century = corrected_year / YEARS_CENTURY;
1582 const integer years_in_century = corrected_year % YEARS_CENTURY;
1583
1584 return static_cast<weekdays>((
1585 day +
1586 13 * (corrected_month + 1) / 5 +
1587 years_in_century +
1588 years_in_century / 4 +
1589 century / 4 +
1590 5 * century
1591 ) % DAYS_WEEK);
1592}
1593
1594constexpr bool
1595original::time::UTCTime::isValidYMD(const integer year, const integer month, const integer day) {
1596 if (!isValidYear(year) || !isValidMonth(month) || !isValidDay(day))
1597 return false;
1598
1599 return day <= daysOfMonth(year, month);
1600}
1601
1602constexpr bool
1603original::time::UTCTime::isValidHMS(const integer hour, const integer minute, const integer second) {
1604 return 0 <= hour && hour <= 23 &&
1605 0 <= minute && minute <= 59 &&
1606 0 <= second && second <= 59;
1607}
1608
1609constexpr bool
1610original::time::UTCTime::isValid(const integer year, const integer month, const integer day,
1611 const integer hour, const integer minute, const integer second) {
1612 return isValidYMD(year, month, day) && isValidHMS(hour, minute, second);
1613}
1614
1616 return isLeapYear(this->year_);
1617}
1618
1619inline original::time::UTCTime::weekdays
1621 return weekday(this->year_, this->month_, this->day_);
1622}
1623
1626
1627inline original::time::UTCTime::UTCTime(const integer year, const integer month, const integer day)
1628 : UTCTime(year, month, day, 0, 0, 0) {}
1629
1630inline original::time::UTCTime::UTCTime(const integer year, const integer month, const integer day,
1631 const integer hour, const integer minute, const integer second) {
1632 if (!isValid(year, month, day, hour, minute, second))
1633 throw valueError("Invalid UTC time parameters: " +
1634 formatString(year) + "-" + formatString(month) + "-" + formatString(day) + " " +
1635 formatString(hour) + ":" + formatString(minute) + ":" + formatString(second));
1636
1637 this->set(year, month, day, hour, minute, second);
1638}
1639
1641 const auto nano_seconds = p.value(NANOSECOND);
1642
1643 integer second = nano_seconds / FACTOR_SECOND;
1644
1645 integer minute = second / (FACTOR_MINUTE / FACTOR_SECOND);
1646 second %= (FACTOR_MINUTE / FACTOR_SECOND);
1647
1648 integer hour = minute / (FACTOR_HOUR / FACTOR_MINUTE);
1649 minute %= (FACTOR_HOUR / FACTOR_MINUTE);
1650
1651 integer day = hour / (FACTOR_DAY / FACTOR_HOUR);
1652 hour %= (FACTOR_DAY / FACTOR_HOUR);
1653
1654 integer year = EPOCH_YEAR;
1655 while (true){
1656 const integer days_in_year = isLeapYear(year) ? DAYS_LEAP_YEAR : DAYS_COMMON_YEAR;
1657 if (day < days_in_year){
1658 break;
1659 }
1660
1661 day -= days_in_year;
1662 year += 1;
1663 }
1664
1665 integer month = 1;
1666 while (true){
1667 const integer dim = daysOfMonth(year, month);
1668 if (day < dim){
1669 break;
1670 }
1671
1672 day -= dim;
1673 month += 1;
1674 }
1675
1676 day += 1;
1677
1678 this->set(year, month, day, hour, minute, second);
1679}
1680
1682 this->operator=(std::move(other));
1683}
1684
1687 if (this == &other)
1688 return *this;
1689
1690 this->set(other.year_, other.month_, other.day_,
1691 other.hour_, other.minute_, other.second_);
1692 other.set(EPOCH_YEAR, EPOCH_MONTH, EPOCH_DAY, 0, 0, 0);
1693 return *this;
1694}
1695
1697{
1698 return UTCTime{this->year_, this->month_, this->day_};
1699}
1700
1701inline original::integer
1703 switch (unit) {
1704 case SECOND:
1705 return this->second_;
1706 case MINUTE:
1707 return this->minute_;
1708 case HOUR:
1709 return this->hour_;
1710 case DAY:
1711 return this->day_;
1712 default:
1713 throw valueError("Invalid time unit for UTCTime value access");
1714 }
1715}
1716
1717inline original::integer
1718original::time::UTCTime::value(const calendar calendar) const {
1719 switch (calendar) {
1720 case MONTH:
1721 return this->month_;
1722 case YEAR:
1723 return this->year_;
1724 default:
1725 throw valueError("Invalid calendar component for UTCTime value access");
1726 }
1727}
1728
1729inline original::time::UTCTime::operator point() const {
1730 time_val_type total_days = 0;
1731
1732 for (integer year = EPOCH_YEAR; year < this->year_; ++year) {
1733 total_days += isLeapYear(year) ? DAYS_LEAP_YEAR : DAYS_COMMON_YEAR;
1734 }
1735
1736 for (integer month = 1; month < this->month_; ++month) {
1737 total_days += daysOfMonth(this->year_, month);
1738 }
1739
1740 total_days += this->day_ - 1;
1741
1742 time_val_type total_seconds = total_days * (FACTOR_DAY / FACTOR_SECOND);
1743 total_seconds += this->hour_ * (FACTOR_HOUR / FACTOR_SECOND);
1744 total_seconds += this->minute_ * (FACTOR_MINUTE / FACTOR_SECOND);
1745 total_seconds += this->second_;
1746
1747 return point{total_seconds, SECOND};
1748}
1749
1750inline original::time::point original::time::UTCTime::toPoint() const
1751{
1752 return static_cast<point>(*this);
1753}
1754
1755inline original::integer
1757 if (this->year_ != other.year_)
1758 return this->year_ > other.year_ ? 1 : -1;
1759 if (this->month_ != other.month_)
1760 return this->month_ > other.month_ ? 1 : -1;
1761 if (this->day_ != other.day_)
1762 return this->day_ > other.day_ ? 1 : -1;
1763 if (this->hour_ != other.hour_)
1764 return this->hour_ > other.hour_ ? 1 : -1;
1765 if (this->minute_ != other.minute_)
1766 return this->minute_ > other.minute_ ? 1 : -1;
1767 if (this->second_ != other.second_)
1768 return this->second_ > other.second_ ? 1 : -1;
1769 return 0;
1770}
1771
1774 u_integer seed = 0;
1775 hash<UTCTime>::hashCombine(seed, this->year_, this->month_, this->day_,
1776 this-> hour_, this->minute_, this->second_);
1777 return seed;
1778}
1779
1780inline std::string original::time::UTCTime::className() const {
1781 return "time::UTCTime";
1782}
1783
1784inline std::string original::time::UTCTime::toString(const bool enter) const {
1785 std::stringstream ss;
1786 ss << "(" << this->className() << " "
1787 << this->year_ << "-"
1788 << std::setw(2) << std::setfill('0') << this->month_ << "-"
1789 << std::setw(2) << std::setfill('0') << this->day_ << " "
1790 << std::setw(2) << std::setfill('0') << this->hour_ << ":"
1791 << std::setw(2) << std::setfill('0') << this->minute_ << ":"
1792 << std::setw(2) << std::setfill('0') << this->second_ << ")";
1793 if (enter)
1794 ss << "\n";
1795 return ss.str();
1796}
1797
1800 return time::UTCTime{static_cast<time::point>(t) - d};
1801}
1802
1805 return static_cast<time::point>(lhs) - static_cast<time::point>(rhs);
1806}
1807
1810 return time::UTCTime{static_cast<time::point>(t) + d};
1811}
1812
1815 return t + d;
1816}
1817
1818#endif //ORIGINAL_ZEIT_H
Base class for comparable objects.
Definition comparable.h:31
Forward declaration of hash class template.
Definition hash.h:92
static u_integer hashFunc(const T &t) noexcept
Default hash function fallback.
Forward declaration of hashable interface template.
Definition hash.h:240
Base class providing polymorphic string conversion capabilities.
Definition printable.h:39
Abstract base class for unique element containers.
Definition set.h:44
Represents a UTC calendar date and time.
Definition zeit.h:534
static UTCTime localNow()
Returns the current local time as UTCTime.
Definition zeit.h:1545
static constexpr bool isValidYMD(integer year, integer month, integer day)
Checks if year-month-day is valid.
Definition zeit.h:1595
static integer localZonedOffset()
Returns the system's local timezone offset in hours from UTC.
Definition zeit.h:1512
std::string toString(bool enter) const override
Converts UTCTime to string representation (YYYY-MM-DD HH:MM:SS)
Definition zeit.h:1784
static constexpr auto FRIDAY
Constant for Friday.
Definition zeit.h:621
static constexpr bool isValidHMS(integer hour, integer minute, integer second)
Checks if hour-minute-second is valid.
Definition zeit.h:1603
static constexpr auto SATURDAY
Constant for Saturday.
Definition zeit.h:609
static constexpr integer YEARS_CENTURY
Years in a century.
Definition zeit.h:628
static constexpr integer MONTHS_YEAR
Months in a year.
Definition zeit.h:626
friend UTCTime operator+(const UTCTime &t, const duration &d)
Adds duration to UTCTime.
bool isLeapYear() const
Checks if this year is a leap year.
Definition zeit.h:1615
static constexpr integer daysOfMonth(integer year, integer month)
Gets days in specified month.
Definition zeit.h:1557
static constexpr auto MONDAY
Constant for Monday.
Definition zeit.h:613
integer compareTo(const UTCTime &other) const override
Compares this UTCTime to another.
Definition zeit.h:1756
static constexpr auto TUESDAY
Constant for Tuesday.
Definition zeit.h:615
static constexpr integer DAYS_WEEK
Days in a week.
Definition zeit.h:624
static constexpr auto WEDNESDAY
Constant for Wednesday.
Definition zeit.h:617
UTCTime & operator=(const UTCTime &other)=default
Default copy assignment.
static const UTCTime EPOCH
Epoch time constant (1970-01-01 00:00:00)
Definition zeit.h:631
weekdays weekday() const
Gets weekday for this date.
Definition zeit.h:1620
UTCTime(const UTCTime &other)=default
Default copy constructor.
UTCTime date() const
Returns a new UTCTime object containing only the calendar date.
Definition zeit.h:1696
std::string className() const override
Gets the class name.
Definition zeit.h:1780
u_integer toHash() const noexcept override
Computes hash value for this UTCTime.
Definition zeit.h:1773
static constexpr auto THURSDAY
Constant for Thursday.
Definition zeit.h:619
friend UTCTime operator-(const UTCTime &t, const duration &d)
Subtracts duration from UTCTime.
integer value(unit unit) const
Gets time component value.
Definition zeit.h:1702
static constexpr bool isValid(integer year, integer month, integer day, integer hour, integer minute, integer second)
Checks if full date-time is valid.
Definition zeit.h:1610
UTCTime()
Constructs a UTCTime object representing the epoch (1970-01-01 00:00:00 UTC)
Definition zeit.h:1624
static constexpr auto SUNDAY
Constant for Sunday.
Definition zeit.h:611
static UTCTime now()
Gets current UTC time.
Definition zeit.h:1507
Represents a time duration with nanosecond precision.
Definition zeit.h:134
duration & operator*=(time_val_type factor)
Multiplies duration by a factor.
Definition zeit.h:1235
friend duration operator*(time_val_type factor, const duration &d)
Multiplication operator (factor * duration)
duration(const duration &other)=default
Default copy constructor.
duration & operator+=(const duration &other)
Adds another duration to this one.
Definition zeit.h:1223
u_integer toHash() const noexcept override
Computes hash value for this duration.
Definition zeit.h:1165
friend duration operator/(const duration &lhs, const duration &rhs)
Division operator (duration / duration)
time_val_type value(unit unit=MILLISECOND) const
Gets the duration value in specified units.
Definition zeit.h:1127
std::string className() const override
Gets the class name.
Definition zeit.h:1169
friend duration operator/(const duration &d, time_val_type factor)
Division operator (duration / factor)
duration(time_val_type val=0, unit unit=MILLISECOND)
Constructs a duration with given value and unit.
Definition zeit.h:1079
floating div(time_val_type factor, unit unit=MILLISECOND) const
Floating-point division by a factor.
Definition zeit.h:1253
duration & operator++()
Prefix increment (adds 1 nanosecond)
Definition zeit.h:1197
std::string toString(bool enter) const override
Converts duration to string representation.
Definition zeit.h:1173
friend duration operator-(const duration &d)
Negation operator.
integer compareTo(const duration &other) const override
Compares this duration to another.
Definition zeit.h:1158
static const duration ZERO
Zero duration constant.
Definition zeit.h:141
friend duration operator*(const duration &d, time_val_type factor)
Multiplication operator (duration * factor)
friend duration operator+(const duration &lhs, const duration &rhs)
Addition operator.
friend duration abs(const duration &d)
Absolute value of duration.
duration & operator/=(time_val_type factor)
Divides duration by a factor.
Definition zeit.h:1241
duration & operator-=(const duration &other)
Subtracts another duration from this one.
Definition zeit.h:1229
duration & operator--()
Prefix decrement (subtracts 1 nanosecond)
Definition zeit.h:1210
duration & operator=(const duration &other)=default
Default copy assignment.
friend duration operator-(const duration &lhs, const duration &rhs)
Subtraction operator.
Represents a point in time with nanosecond precision.
Definition zeit.h:374
static point now()
Gets current time point.
Definition zeit.h:1352
time_val_type value(unit unit=MILLISECOND) const noexcept
Gets time value in specified units.
Definition zeit.h:1380
std::string className() const override
Gets the class name.
Definition zeit.h:1394
friend point operator-(const point &p, const duration &d)
Subtracts duration from time point.
point & operator--()
Prefix decrement (subtracts 1 nanosecond)
Definition zeit.h:1433
point & operator++()
Prefix increment (adds 1 nanosecond)
Definition zeit.h:1420
point(time_val_type val=0, unit unit=MILLISECOND)
Constructs time point from value and unit.
Definition zeit.h:1368
point & operator-=(const duration &d)
Subtracts duration from time point.
Definition zeit.h:1452
std::string toString(bool enter) const override
Converts time point to string representation.
Definition zeit.h:1399
friend point operator+(const point &p, const duration &d)
Adds duration to time point.
point & operator+=(const duration &d)
Adds duration to time point.
Definition zeit.h:1446
u_integer toHash() const noexcept override
Computes hash value for this time point.
Definition zeit.h:1390
integer compareTo(const point &other) const override
Compares this time point to another.
Definition zeit.h:1385
friend duration operator-(const point &lhs, const point &rhs)
Computes duration between two time points.
Namespace-like class containing time-related utilities.
Definition zeit.h:40
static constexpr time_val_type FACTOR_MILLISECOND
Conversion factor for milliseconds.
Definition zeit.h:95
static constexpr auto NANOSECOND
Constant for nanosecond unit.
Definition zeit.h:76
static constexpr integer EPOCH_DAY
Epoch day (Unix epoch)
Definition zeit.h:115
static constexpr auto DAY
Constant for day unit.
Definition zeit.h:88
static constexpr auto HOUR
Constant for hour unit.
Definition zeit.h:86
static constexpr auto YEAR
Constant for year calendar component.
Definition zeit.h:891
static constexpr integer EPOCH_MONTH
Epoch month (Unix epoch)
Definition zeit.h:113
static constexpr auto MILLISECOND
Constant for millisecond unit.
Definition zeit.h:80
static constexpr auto MINUTE
Constant for minute unit.
Definition zeit.h:84
static constexpr time_val_type FACTOR_NANOSECOND
Conversion factor for nanoseconds.
Definition zeit.h:91
unit
Time units supported by the library.
Definition zeit.h:65
@ MILLISECOND
Milliseconds (1e-3 seconds)
@ MINUTE
Minutes (60 seconds)
@ MICROSECOND
Microseconds (1e-6 seconds)
@ DAY
Days (86400 seconds)
@ HOUR
Hours (3600 seconds)
@ NANOSECOND
Nanoseconds (1e-9 seconds)
static constexpr auto SECOND
Constant for second unit.
Definition zeit.h:82
static constexpr time_val_type FACTOR_DAY
Conversion factor for days.
Definition zeit.h:103
static constexpr integer DAYS_COMMON_YEAR
Days in a common year.
Definition zeit.h:108
static constexpr auto MICROSECOND
Constant for microsecond unit.
Definition zeit.h:78
static constexpr time_val_type FACTOR_MINUTE
Conversion factor for minutes.
Definition zeit.h:99
integer time_val_type
Type used for storing time values.
Definition zeit.h:43
static constexpr integer DAYS_LEAP_YEAR
Days in a leap year.
Definition zeit.h:106
static constexpr time_val_type FACTOR_SECOND
Conversion factor for seconds.
Definition zeit.h:97
static constexpr time_val_type FACTOR_HOUR
Conversion factor for hours.
Definition zeit.h:101
static constexpr integer EPOCH_YEAR
Epoch year (Unix epoch)
Definition zeit.h:111
static constexpr time_val_type FACTOR_MICROSECOND
Conversion factor for microseconds.
Definition zeit.h:93
static constexpr auto MONTH
Constant for month calendar component.
Definition zeit.h:889
Exception for invalid parameter values.
Definition error.h:150
Interface for objects that can be compared.
Platform-independent type definitions and compiler/platform detection.
Custom exception classes and callback validation utilities.
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:263
double floating
Double-precision floating-point type.
Definition config.h:283
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:254
std::uint64_t ul_integer
64-bit unsigned integer type
Definition config.h:274
Provides a generic hashing utility and interface for hashable types.
User-defined literals for time durations.
Main namespace for the project Original.
Definition algorithms.h:21
auto operator+(const iterator< T > &it, integer steps) -> iterator< T > *
Adds a number of steps to the iterator's current position and returns a new iterator.
auto operator-(const iterator< T > &it, integer steps) -> iterator< T > *
Subtracts a number of steps from the iterator's current position and returns a new iterator.
TYPE abs(TYPE a)
Returns the absolute value of a given number.
time::duration operator*(const time::duration &d, time::time_val_type factor)
Definition zeit.h:1319
time::duration operator/(const time::duration &d, time::time_val_type factor)
Definition zeit.h:1331
Interface for polymorphic string formatting and output.