datetime.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #pragma once
  2. #include <util/generic/algorithm.h>
  3. #include <util/generic/string.h>
  4. #include <util/generic/yexception.h>
  5. #include <util/generic/ymath.h>
  6. #include <util/datetime/base.h>
  7. #include <cstdlib>
  8. #include <time.h>
  9. namespace NDatetime {
  10. extern const ui32 MonthDays[2][12]; // !leapYear; !!leapYear
  11. extern const ui32 MonthDaysNewYear[2][13]; // !leapYear; !!leapYear
  12. inline ui32 YearDaysAD(ui32 year) {
  13. year = Max<ui32>(year, 1) - 1; //1 AD comes straight after 1 BC, no 0 AD
  14. return year * 365 + year / 4 - year / 100 + year / 400;
  15. }
  16. inline bool LeapYearAD(ui32 year) {
  17. return (!(year % 4) && (year % 100)) || !(year % 400);
  18. }
  19. inline ui32 YDayFromMonthAndDay(ui32 month /*0 - based*/, ui32 mday /*1 - based*/, bool isleap) {
  20. return MonthDaysNewYear[isleap][Min(month, (ui32)11u)] + mday - 1;
  21. }
  22. void YDayToMonthAndDay(ui32 yday /*0 - based*/, bool isleap, ui32* month /*0 - based*/, ui32* mday /*1 - based*/);
  23. struct TSimpleTM {
  24. enum EField {
  25. F_NONE = 0,
  26. F_SEC,
  27. F_MIN,
  28. F_HOUR,
  29. F_DAY,
  30. F_MON,
  31. F_YEAR
  32. };
  33. i32 GMTOff = 0; // -43200 - 50400 seconds
  34. ui16 Year = 0; // from 1900
  35. ui16 YDay = 0; // 0-365
  36. ui8 Mon = 0; // 0-11
  37. ui8 MDay = 0; // 1-31
  38. ui8 WDay = 0; // 0-6
  39. ui8 Hour = 0; // 0-23
  40. ui8 Min = 0; // 0-59
  41. ui8 Sec = 0; // 0-60 - doesn't care for leap seconds. Most of the time it's ok.
  42. i8 IsDst = 0; // -1/0/1
  43. bool IsLeap = false;
  44. public:
  45. static TSimpleTM New(time_t t = 0, i32 gmtoff = 0, i8 isdst = 0);
  46. static TSimpleTM NewLocal(time_t = 0);
  47. static TSimpleTM New(const struct tm&);
  48. static TSimpleTM CurrentUTC();
  49. TSimpleTM() = default;
  50. TSimpleTM(ui32 year, ui32 mon, ui32 day, ui32 h = 0, ui32 m = 0, ui32 s = 0) {
  51. Zero(*this);
  52. SetRealDate(year, mon, day, h, m, s);
  53. }
  54. // keeps the object consistent
  55. TSimpleTM& Add(EField f, i32 amount = 1);
  56. TString ToString(const char* fmt = "%a, %d %b %Y %H:%M:%S %z") const;
  57. TSimpleTM& ToUTC() {
  58. return *this = New(AsTimeT());
  59. }
  60. bool IsUTC() const {
  61. return !IsDst && !GMTOff;
  62. }
  63. time_t AsTimeT() const;
  64. operator time_t() const {
  65. return AsTimeT();
  66. }
  67. struct tm AsStructTmLocal() const;
  68. struct tm AsStructTmUTC() const;
  69. operator struct tm() const {
  70. return AsStructTmLocal();
  71. }
  72. ui32 RealYear() const {
  73. return ui32(Year + 1900);
  74. }
  75. ui32 RealMonth() const {
  76. return ui32(Mon + 1);
  77. }
  78. TSimpleTM& SetRealDate(ui32 year, ui32 mon, ui32 mday, ui32 hour = -1, ui32 min = -1, ui32 sec = -1, i32 isdst = 0);
  79. // regenerates all fields from Year, MDay, Hour, Min, Sec, IsDst, GMTOffset
  80. TSimpleTM& RegenerateFields();
  81. friend bool operator==(const TSimpleTM& a, const TSimpleTM& b) {
  82. return a.AsTimeT() == b.AsTimeT();
  83. }
  84. friend bool operator==(const TSimpleTM& s, const struct tm& t) {
  85. return s == New(t);
  86. }
  87. friend bool operator==(const struct tm& t, const TSimpleTM& s) {
  88. return s == t;
  89. }
  90. friend bool operator!=(const TSimpleTM& a, const TSimpleTM& b) {
  91. return !(a == b);
  92. }
  93. friend bool operator!=(const TSimpleTM& s, const struct tm& t) {
  94. return !(s == t);
  95. }
  96. friend bool operator!=(const struct tm& t, const TSimpleTM& s) {
  97. return s != t;
  98. }
  99. };
  100. }
  101. inline TString date2str(const time_t date) {
  102. struct tm dateTm;
  103. memset(&dateTm, 0, sizeof(dateTm));
  104. localtime_r(&date, &dateTm);
  105. char buf[9];
  106. strftime(buf, sizeof(buf), "%Y%m%d", &dateTm);
  107. return TString(buf);
  108. }
  109. inline time_t str2date(const TString& dateStr) {
  110. struct tm dateTm;
  111. memset(&dateTm, 0, sizeof(tm));
  112. strptime(dateStr.data(), "%Y%m%d", &dateTm);
  113. return mktime(&dateTm);
  114. }
  115. // checks whether time2 > time1 and close enough to it
  116. inline bool AreTimesSeqAndClose(time_t time1, time_t time2, time_t closeInterval = 10) {
  117. return (time2 - time1) <= closeInterval;
  118. }
  119. // checks whether time2 and time1 are close enough
  120. inline bool AreTimesClose(time_t time1, time_t time2, time_t closeInterval = 10) {
  121. return std::abs(time2 - time1) <= closeInterval;
  122. }
  123. ////////////////////////////////
  124. struct TMonth {
  125. ui16 Year;
  126. ui8 Month;
  127. TMonth(ui16 year = 0, ui8 month = 0)
  128. : Year(year)
  129. , Month(month)
  130. {
  131. }
  132. TMonth operator-(ui16 n) {
  133. if (n <= Month) {
  134. return TMonth(Year, Month - (ui8)n);
  135. } else {
  136. n -= Month;
  137. return (n % 12) ? TMonth(Year - 1 - (n / 12), 12 - (n % 12)) : TMonth(Year - (n / 12), 0);
  138. }
  139. }
  140. };
  141. Y_DECLARE_PODTYPE(NDatetime::TSimpleTM);