#include "common.hh" #include "date.hh" #include #include namespace { // localtime_r doesn't guarantee to call tzset as localtime does. pthread_once_t tzset_called = PTHREAD_ONCE_INIT; } // namespace Date Date::from_format(std::string const& format, std::string const& str, bool local_time) { struct tm tm = {}; tm.tm_isdst = -1; // Must be -1 so that mktime figures it out by itself. auto* end = strptime(str.c_str(), format.c_str(), &tm); if (end && !*end) return local_time ? mktime(&tm) : timegm(&tm); return Date(); } std::string Date::to_format(std::string const& format, bool local_time) const { if (empty() || format.empty()) return std::string(); if (local_time) pthread_once(&tzset_called, tzset); struct tm mem = {}; auto* tm = local_time ? localtime_r(&time_, &mem) : gmtime_r(&time_, &mem); if (!tm) return std::string(); std::string ret; ret.resize(64); while (true) { auto len = strftime(ret.data(), ret.size(), format.c_str(), tm); if (len > 0) { ret.resize(len); return ret; } ret.resize(ret.size() * 2); } } Date Date::day(bool local_time) const { if (empty()) return *this; if (local_time) pthread_once(&tzset_called, tzset); struct tm tm = {}; auto* ret = local_time ? localtime_r(&time_, &tm) : gmtime_r(&time_, &tm); if (!ret) return *this; ret->tm_hour = 0; ret->tm_min = 0; ret->tm_sec = 0; return local_time ? mktime(ret) : timegm(ret); }