diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/draft/datetime.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/draft/datetime.h')
-rw-r--r-- | util/draft/datetime.h | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/util/draft/datetime.h b/util/draft/datetime.h new file mode 100644 index 0000000000..8a387ea6f1 --- /dev/null +++ b/util/draft/datetime.h @@ -0,0 +1,184 @@ +#pragma once + +#include <util/generic/algorithm.h> +#include <util/generic/string.h> +#include <util/generic/yexception.h> +#include <util/generic/ymath.h> +#include <util/datetime/base.h> + +#include <cstdlib> + +#include <time.h> + +namespace NDatetime { + extern const ui32 MonthDays[2][12]; // !leapYear; !!leapYear + extern const ui32 MonthDaysNewYear[2][13]; // !leapYear; !!leapYear + + inline ui32 YearDaysAD(ui32 year) { + year = Max<ui32>(year, 1) - 1; //1 AD comes straight after 1 BC, no 0 AD + return year * 365 + year / 4 - year / 100 + year / 400; + } + + inline bool LeapYearAD(ui32 year) { + return (!(year % 4) && (year % 100)) || !(year % 400); + } + + inline ui32 YDayFromMonthAndDay(ui32 month /*0 - based*/, ui32 mday /*1 - based*/, bool isleap) { + return MonthDaysNewYear[isleap][Min(month, (ui32)11u)] + mday - 1; + } + + void YDayToMonthAndDay(ui32 yday /*0 - based*/, bool isleap, ui32* month /*0 - based*/, ui32* mday /*1 - based*/); + + struct TSimpleTM { + enum EField { + F_NONE = 0, + F_SEC, + F_MIN, + F_HOUR, + F_DAY, + F_MON, + F_YEAR + }; + + i32 GMTOff = 0; // -43200 - 50400 seconds + ui16 Year = 0; // from 1900 + ui16 YDay = 0; // 0-365 + ui8 Mon = 0; // 0-11 + ui8 MDay = 0; // 1-31 + ui8 WDay = 0; // 0-6 + ui8 Hour = 0; // 0-23 + ui8 Min = 0; // 0-59 + ui8 Sec = 0; // 0-60 - doesn't care for leap seconds. Most of the time it's ok. + i8 IsDst = 0; // -1/0/1 + bool IsLeap = false; + + public: + static TSimpleTM New(time_t t = 0, i32 gmtoff = 0, i8 isdst = 0); + static TSimpleTM NewLocal(time_t = 0); + + static TSimpleTM New(const struct tm&); + + static TSimpleTM CurrentUTC(); + + TSimpleTM() = default; + + TSimpleTM(ui32 year, ui32 mon, ui32 day, ui32 h = 0, ui32 m = 0, ui32 s = 0) { + Zero(*this); + SetRealDate(year, mon, day, h, m, s); + } + + // keeps the object consistent + TSimpleTM& Add(EField f, i32 amount = 1); + + TString ToString(const char* fmt = "%a, %d %b %Y %H:%M:%S %z") const; + + TSimpleTM& ToUTC() { + return *this = New(AsTimeT()); + } + + bool IsUTC() const { + return !IsDst && !GMTOff; + } + + time_t AsTimeT() const; + + operator time_t() const { + return AsTimeT(); + }; + + struct tm AsStructTmLocal() const; + + struct tm AsStructTmUTC() const; + + operator struct tm() const { + return AsStructTmLocal(); + } + + ui32 RealYear() const { + return ui32(Year + 1900); + } + + ui32 RealMonth() const { + return ui32(Mon + 1); + } + + TSimpleTM& SetRealDate(ui32 year, ui32 mon, ui32 mday, ui32 hour = -1, ui32 min = -1, ui32 sec = -1, i32 isdst = 0); + + // regenerates all fields from Year, MDay, Hour, Min, Sec, IsDst, GMTOffset + TSimpleTM& RegenerateFields(); + + friend bool operator==(const TSimpleTM& a, const TSimpleTM& b) { + return a.AsTimeT() == b.AsTimeT(); + } + + friend bool operator==(const TSimpleTM& s, const struct tm& t) { + return s == New(t); + } + + friend bool operator==(const struct tm& t, const TSimpleTM& s) { + return s == t; + } + + friend bool operator!=(const TSimpleTM& a, const TSimpleTM& b) { + return !(a == b); + } + + friend bool operator!=(const TSimpleTM& s, const struct tm& t) { + return !(s == t); + } + + friend bool operator!=(const struct tm& t, const TSimpleTM& s) { + return s != t; + } + }; +} + +inline TString date2str(const time_t date) { + struct tm dateTm; + memset(&dateTm, 0, sizeof(dateTm)); + localtime_r(&date, &dateTm); + char buf[9]; + strftime(buf, sizeof(buf), "%Y%m%d", &dateTm); + return TString(buf); +} + +inline time_t str2date(const TString& dateStr) { + struct tm dateTm; + memset(&dateTm, 0, sizeof(tm)); + strptime(dateStr.data(), "%Y%m%d", &dateTm); + return mktime(&dateTm); +} + +// checks whether time2 > time1 and close enough to it +inline bool AreTimesSeqAndClose(time_t time1, time_t time2, time_t closeInterval = 10) { + return (time2 - time1) <= closeInterval; +} + +// checks whether time2 and time1 are close enough +inline bool AreTimesClose(time_t time1, time_t time2, time_t closeInterval = 10) { + return std::abs(time2 - time1) <= closeInterval; +} + +//////////////////////////////// + +struct TMonth { + ui16 Year; + ui8 Month; + + TMonth(ui16 year = 0, ui8 month = 0) + : Year(year) + , Month(month) + { + } + + TMonth operator-(ui16 n) { + if (n <= Month) { + return TMonth(Year, Month - (ui8)n); + } else { + n -= Month; + return (n % 12) ? TMonth(Year - 1 - (n / 12), 12 - (n % 12)) : TMonth(Year - (n / 12), 0); + } + } +}; + +Y_DECLARE_PODTYPE(NDatetime::TSimpleTM); |