#pragma once #include #include #include namespace Util { inline bool IsValidYear(int const year) { return year > 1900 && year < 9999; } inline bool IsValidMonth(int const month) { return month > 0 && month < 13; } inline bool IsValidDay(int const day) { return day > 0 && day < 32; } inline long GetEpoch(long year, unsigned month, unsigned day) { year -= month <= 2; const long era = (year >= 0 ? year : year - 399) / 400; const unsigned yoe = static_cast(year - era * 400); // [0, 399] const unsigned doy = (153 * (month + (month > 2 ? -3 : 9)) + 2) / 5 + day - 1; // [0, 365] const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096] // Multiply by the day length in seconds return (era * 146097 + doe - 719468) * (24l * 60l * 60l); } inline long ToEpoch(std::string const & date) { int year, month, day; if(std::sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day) != 3) { return -1; } return GetEpoch(year, month, day); } inline unsigned ToSeconds(unsigned hours, unsigned minutes, unsigned seconds) { return (hours * 60 * 60) + (minutes * 60) + seconds; } inline int ToSecondsFromTimeString(char const * string) { int hour, minute, second; if(std::sscanf(string, "%d:%d:%d", &hour, &minute, &second) != 3) { return -1; } return ToSeconds(hour, minute, second); } inline std::string GetSqliteDate(time_t const epochTime) { auto const dateTime = *std::gmtime(&epochTime); char dateStringBuffer[64]; std::sprintf(dateStringBuffer, "%i-%02i-%02i", dateTime.tm_year + 1900, dateTime.tm_mon + 1, dateTime.tm_mday); return std::string(dateStringBuffer); } inline std::string GetSqliteUtcTime(time_t const epochTime) { auto const dateTime = *std::gmtime(&epochTime); char timeStringBuffer[64]; std::sprintf(timeStringBuffer, "%02i:%02i:%02i", dateTime.tm_hour, dateTime.tm_min, dateTime.tm_sec); return std::string(timeStringBuffer); } class Date { private: unsigned year; unsigned month; unsigned day; public: unsigned Year() const { return year; } unsigned Month() const { return month; } unsigned Day() const { return day; } void AddMonth() { ++month; if(month > 12) { month = 1; ++year; } } void SetDayToEndOfMonth() { day = 31; } bool IsValid() const { return IsValidYear(year) && IsValidMonth(month) && IsValidDay(day); } long ToEpoch() const { return GetEpoch(year, month, day); } bool IsBefore(unsigned const otherYear, unsigned const otherMonth, unsigned const otherDay) const { return (year < otherYear) || (year == otherYear && month < otherMonth) || (year == otherYear && month == otherMonth && day < otherDay); } bool IsBefore(Date const & other) const { return IsBefore(other.year, other.month, other.day); } bool IsAfter(unsigned const otherYear, unsigned const otherMonth, unsigned const otherDay) const { return (year > otherYear) || (year == otherYear && month > otherMonth) || (year == otherYear && month == otherMonth && day > otherDay); } std::string ToISOString() const { char buffer[11]; std::sprintf(buffer, "%04i-%02i-%02i", year, month, day); return std::string(buffer); } bool TryParse(std::string const & date) { Date result; if(sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day) != 3) { result.year = 0; result.month = 0; result.day = 0; return false; } return true; } Date() : year(0), month(0), day(0) { } Date(std::string const & date) : year(0), month(0), day(0) { TryParse(date); } Date(long const epoch) { std::tm dateTime = *std::gmtime(&epoch); year = 1900 + dateTime.tm_year; month = 1 + dateTime.tm_mon; day = dateTime.tm_mday; } static Date UtcNow() { return Date(std::time(nullptr)); } }; }