chrono.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #pragma once
  2. #include <nall/function.hpp>
  3. #include <nall/string.hpp>
  4. namespace nall::chrono {
  5. //passage of time functions (from unknown epoch)
  6. inline auto nanosecond() -> uint64_t {
  7. timespec tv;
  8. clock_gettime(CLOCK_MONOTONIC, &tv);
  9. return tv.tv_sec * 1'000'000'000 + tv.tv_nsec;
  10. }
  11. inline auto microsecond() -> uint64_t { return nanosecond() / 1'000; }
  12. inline auto millisecond() -> uint64_t { return nanosecond() / 1'000'000; }
  13. inline auto second() -> uint64_t { return nanosecond() / 1'000'000'000; }
  14. inline auto benchmark(const function<void ()>& f, uint64_t times = 1) -> void {
  15. auto start = nanosecond();
  16. while(times--) f();
  17. auto end = nanosecond();
  18. print("[chrono::benchmark] ", (double)(end - start) / 1'000'000'000.0, "s\n");
  19. }
  20. //exact date/time functions (from system epoch)
  21. struct timeinfo {
  22. timeinfo(
  23. uint year = 0, uint month = 0, uint day = 0,
  24. uint hour = 0, uint minute = 0, uint second = 0, uint weekday = 0
  25. ) : year(year), month(month), day(day),
  26. hour(hour), minute(minute), second(second), weekday(weekday) {
  27. }
  28. inline explicit operator bool() const { return month; }
  29. uint year; //...
  30. uint month; //1 - 12
  31. uint day; //1 - 31
  32. uint hour; //0 - 23
  33. uint minute; //0 - 59
  34. uint second; //0 - 60
  35. uint weekday; //0 - 6
  36. };
  37. inline auto timestamp() -> uint64_t {
  38. return ::time(nullptr);
  39. }
  40. //0 = failure condition
  41. inline auto timestamp(const string& datetime) -> uint64_t {
  42. static const uint monthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  43. uint64_t timestamp = 0;
  44. if(datetime.match("??????????")) {
  45. return datetime.natural();
  46. }
  47. if(datetime.match("????*")) {
  48. uint year = datetime.slice(0, 4).natural();
  49. if(year < 1970 || year > 2199) return 0;
  50. for(uint y = 1970; y < year && y < 2999; y++) {
  51. uint daysInYear = 365;
  52. if(y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) daysInYear++;
  53. timestamp += daysInYear * 24 * 60 * 60;
  54. }
  55. }
  56. if(datetime.match("????-??*")) {
  57. uint y = datetime.slice(0, 4).natural();
  58. uint month = datetime.slice(5, 2).natural();
  59. if(month < 1 || month > 12) return 0;
  60. for(uint m = 1; m < month && m < 12; m++) {
  61. uint daysInMonth = monthDays[m - 1];
  62. if(m == 2 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) daysInMonth++;
  63. timestamp += daysInMonth * 24 * 60 * 60;
  64. }
  65. }
  66. if(datetime.match("????-??-??*")) {
  67. uint day = datetime.slice(8, 2).natural();
  68. if(day < 1 || day > 31) return 0;
  69. timestamp += (day - 1) * 24 * 60 * 60;
  70. }
  71. if(datetime.match("????-??-?? ??*")) {
  72. uint hour = datetime.slice(11, 2).natural();
  73. if(hour > 23) return 0;
  74. timestamp += hour * 60 * 60;
  75. }
  76. if(datetime.match("????-??-?? ??:??*")) {
  77. uint minute = datetime.slice(14, 2).natural();
  78. if(minute > 59) return 0;
  79. timestamp += minute * 60;
  80. }
  81. if(datetime.match("????-??-?? ??:??:??*")) {
  82. uint second = datetime.slice(17, 2).natural();
  83. if(second > 59) return 0;
  84. timestamp += second;
  85. }
  86. return timestamp;
  87. }
  88. namespace utc {
  89. inline auto timeinfo(uint64_t time = 0) -> chrono::timeinfo {
  90. auto stamp = time ? (time_t)time : (time_t)timestamp();
  91. auto info = gmtime(&stamp);
  92. return {
  93. (uint)info->tm_year + 1900,
  94. (uint)info->tm_mon + 1,
  95. (uint)info->tm_mday,
  96. (uint)info->tm_hour,
  97. (uint)info->tm_min,
  98. (uint)info->tm_sec,
  99. (uint)info->tm_wday
  100. };
  101. }
  102. inline auto year(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).year, 4, '0'); }
  103. inline auto month(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).month, 2, '0'); }
  104. inline auto day(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).day, 2, '0'); }
  105. inline auto hour(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).hour, 2, '0'); }
  106. inline auto minute(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).minute, 2, '0'); }
  107. inline auto second(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).second, 2, '0'); }
  108. inline auto date(uint64_t timestamp = 0) -> string {
  109. auto t = timeinfo(timestamp);
  110. return {pad(t.year, 4, '0'), "-", pad(t.month, 2, '0'), "-", pad(t.day, 2, '0')};
  111. }
  112. inline auto time(uint64_t timestamp = 0) -> string {
  113. auto t = timeinfo(timestamp);
  114. return {pad(t.hour, 2, '0'), ":", pad(t.minute, 2, '0'), ":", pad(t.second, 2, '0')};
  115. }
  116. inline auto datetime(uint64_t timestamp = 0) -> string {
  117. auto t = timeinfo(timestamp);
  118. return {
  119. pad(t.year, 4, '0'), "-", pad(t.month, 2, '0'), "-", pad(t.day, 2, '0'), " ",
  120. pad(t.hour, 2, '0'), ":", pad(t.minute, 2, '0'), ":", pad(t.second, 2, '0')
  121. };
  122. }
  123. }
  124. namespace local {
  125. inline auto timeinfo(uint64_t time = 0) -> chrono::timeinfo {
  126. auto stamp = time ? (time_t)time : (time_t)timestamp();
  127. auto info = localtime(&stamp);
  128. return {
  129. (uint)info->tm_year + 1900,
  130. (uint)info->tm_mon + 1,
  131. (uint)info->tm_mday,
  132. (uint)info->tm_hour,
  133. (uint)info->tm_min,
  134. (uint)info->tm_sec,
  135. (uint)info->tm_wday
  136. };
  137. }
  138. inline auto year(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).year, 4, '0'); }
  139. inline auto month(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).month, 2, '0'); }
  140. inline auto day(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).day, 2, '0'); }
  141. inline auto hour(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).hour, 2, '0'); }
  142. inline auto minute(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).minute, 2, '0'); }
  143. inline auto second(uint64_t timestamp = 0) -> string { return pad(timeinfo(timestamp).second, 2, '0'); }
  144. inline auto date(uint64_t timestamp = 0) -> string {
  145. auto t = timeinfo(timestamp);
  146. return {pad(t.year, 4, '0'), "-", pad(t.month, 2, '0'), "-", pad(t.day, 2, '0')};
  147. }
  148. inline auto time(uint64_t timestamp = 0) -> string {
  149. auto t = timeinfo(timestamp);
  150. return {pad(t.hour, 2, '0'), ":", pad(t.minute, 2, '0'), ":", pad(t.second, 2, '0')};
  151. }
  152. inline auto datetime(uint64_t timestamp = 0) -> string {
  153. auto t = timeinfo(timestamp);
  154. return {
  155. pad(t.year, 4, '0'), "-", pad(t.month, 2, '0'), "-", pad(t.day, 2, '0'), " ",
  156. pad(t.hour, 2, '0'), ":", pad(t.minute, 2, '0'), ":", pad(t.second, 2, '0')
  157. };
  158. }
  159. }
  160. }