108 lines
3.0 KiB
C++
108 lines
3.0 KiB
C++
|
||
#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(¤t_time);
|
||
struct std::tm *timeinfo = std::localtime(¤t_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(×tamp))) {
|
||
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!
|
||
}
|