usql/ml_date.cpp

108 lines
3.0 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ml_date.h"
#include <cstring>
long now() { // get-universal-time
time_t t = std::time(nullptr);
auto now = static_cast<long int>(t);
return now;
}
long get_gmt_localtime_offset() {
std::time_t current_time;
std::time(&current_time);
struct std::tm *timeinfo = std::localtime(&current_time);
long offset = timeinfo->tm_gmtoff;
return offset;
}
std::string date_to_string(const long datetime, const std::string& format) {
// std::locale::global(std::locale("en-US.UTF8"));
time_t timestamp = datetime;
char mbstr[128];
if (std::strftime(mbstr, sizeof(mbstr), format.c_str(), std::gmtime(&timestamp))) {
std::string result = {mbstr};
return result;
}
throw std::runtime_error("date_to_string, invalid date string or format (" + std::to_string(datetime) + ", " + format + ")" );
}
time_t time_to_epoch ( const struct tm *ltm, int utcdiff ) {
const int mon_days [] = {0, 31, 31+28, 31+28+31,
31+28+31+30, 31+28+31+30+31, 31+28+31+30+31+30,
31+28+31+30+31+30+31, 31+28+31+30+31+30+31+31, 31+28+31+30+31+30+31+31+30,
31+28+31+30+31+30+31+31+30+31, 31+28+31+30+31+30+31+31+30+31+30, 31+28+31+30+31+30+31+31+30+31+30+31};
long tyears, tdays, leaps, utc_hrs;
tyears = ltm->tm_year - 70 ; // tm->tm_year is from 1900.
leaps = (tyears + 2) / 4;
// no of next two lines until year 2100.
//int i = (ltm->tm_year 100) / 100;
//leaps -= ( (i/4)*3 + i%4 );
tdays = mon_days[ltm->tm_mon];
tdays += ltm->tm_mday-1; // days of month passed.
tdays = tdays + (tyears * 365) + leaps;
utc_hrs = ltm->tm_hour + utcdiff/3600; // for your time zone.
return (tdays * 86400) + (utc_hrs * 3600) + (ltm->tm_min * 60) + ltm->tm_sec;
}
long string_to_date(const std::string &datestr, const std::string &format) {
// format for example "%d.%m.%Y";
struct tm tm{};
memset(&tm, 0, sizeof(tm));
if (strptime(datestr.c_str(), format.c_str(), &tm)) {
time_t curTime;
struct tm * timeinfo;
time(&curTime );
timeinfo = std::gmtime(&curTime);
timeinfo->tm_year = tm.tm_year;
timeinfo->tm_mon = tm.tm_mon;
timeinfo->tm_mday = tm.tm_mday;
timeinfo->tm_hour = tm.tm_hour;
timeinfo->tm_min = tm.tm_min;
timeinfo->tm_sec = tm.tm_sec;
return time_to_epoch(timeinfo, 0);
}
throw std::runtime_error("string_to_date, invalid date string or format (" + datestr + ", " + format + ")" );
}
long add_to_date(const long datetime, const int quantity, const std::string &part) {
// part is one of 'year', 'month', 'day', 'hour', 'minute' or 'second'
// very basic implementation, just for now - no timezones DST etc
time_t base = datetime;
struct tm *tm = localtime(&base);
if (part == "year") {
tm->tm_year += quantity;
} else if (part == "month") {
tm->tm_mon += quantity;
} else if (part == "day") {
tm->tm_mday += quantity;
} else if (part == "hour") {
tm->tm_hour += quantity;
} else if (part == "minute") {
tm->tm_min += quantity;
} else if (part == "second") {
tm->tm_sec += quantity;
} else {
throw std::runtime_error("add_to_date, part to add (" + part + ")" );
}
return mktime(tm); // mktime is quite slow!
}