Files

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)); }
};
}