151 lines
4.4 KiB
C++
151 lines
4.4 KiB
C++
#pragma once
|
|
#include <cstdio>
|
|
#include <ctime>
|
|
#include <string>
|
|
|
|
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<unsigned>(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)); }
|
|
};
|
|
} |