#include "DateTime.h" #include #include #include void DateTime::UpdateDT() { namespace ch = std::chrono; auto tp = ch::system_clock::from_time_t(storage); try { // C++20 时区感知:将系统时间转换为本地时间 auto local_tp = ch::current_zone()->to_local(tp); auto dp = ch::floor(local_tp); ch::year_month_day ymd { dp }; ch::hh_mm_ss hms { local_tp - dp }; sep_time.year = static_cast(ymd.year()); sep_time.month = static_cast(ymd.month()); sep_time.day = static_cast(ymd.day()); sep_time.hour = hms.hours().count(); sep_time.minute = hms.minutes().count(); sep_time.second = static_cast(hms.seconds().count()); } catch (...) { // 备用方案:如果系统未配置或不支持本地时区数据库,平滑降级到传统安全实现 std::tm ptm {}; #ifdef _WIN32 localtime_s(&ptm, &storage); #else localtime_r(&storage, &ptm); #endif sep_time.year = ptm.tm_year + 1900; sep_time.month = ptm.tm_mon + 1; sep_time.day = ptm.tm_mday; sep_time.hour = ptm.tm_hour; sep_time.minute = ptm.tm_min; sep_time.second = ptm.tm_sec; } } time_t DateTime::FormatConvert(int year, int month, int day, int hour, int minute, int second) { namespace ch = std::chrono; try { ch::year_month_day ymd { ch::year{year}, ch::month{static_cast(month)}, ch::day{static_cast(day)} }; if (!ymd.ok()) return 0; auto local_tp = ch::local_days { ymd } + ch::hours { hour } + ch::minutes { minute } + ch::seconds { second }; // 将本地时间根据当前系统时区转换为系统标准时间(UTC) return ch::system_clock::to_time_t(ch::current_zone()->to_sys(local_tp)); } catch (...) { std::tm stm {}; stm.tm_year = year - 1900; stm.tm_mon = month - 1; stm.tm_mday = day; stm.tm_hour = hour; stm.tm_min = minute; stm.tm_sec = second; stm.tm_isdst = -1; return ::mktime(&stm); } } time_t DateTime::SpanedSeconds(Span sp) { namespace ch = std::chrono; auto total = ch::days { sp.days } + ch::hours { sp.hours } + ch::minutes { sp.minutes } + ch::seconds { sp.seconds }; return ch::duration_cast(total).count(); } DateTime::Span DateTime::ToSpan(time_t tim) { // 修复了原代码中天数数额赋给秒、余数计算混乱的 Bug namespace ch = std::chrono; ch::seconds total_secs { tim }; auto d = ch::duration_cast(total_secs); total_secs -= d; auto h = ch::duration_cast(total_secs); total_secs -= h; auto m = ch::duration_cast(total_secs); total_secs -= m; Span sp; sp.days = static_cast(d.count()); sp.hours = static_cast(h.count()); sp.minutes = static_cast(m.count()); sp.seconds = static_cast(total_secs.count()); return sp; } DateTime::DateTime() { storage = ::time(nullptr); UpdateDT(); } DateTime::DateTime(time_t t) { storage = t; UpdateDT(); } DateTime::DateTime(const tm& stm) { storage = ::mktime(const_cast(&stm)); UpdateDT(); } DateTime::DateTime(const Full& ftm) { storage = FormatConvert(ftm.year, ftm.month, ftm.day, ftm.hour, ftm.minute, ftm.second); UpdateDT(); } DateTime::DateTime(int year, int month, int day, int hour, int minute, int second) { storage = FormatConvert(year, month, day, hour, minute, second); UpdateDT(); } DateTime::DateTime(const DateTime& obj) { storage = obj.storage; sep_time = obj.sep_time; } DateTime DateTime::Now() { return DateTime(::time(nullptr)); } time_t DateTime::GetTimeStamp() const { return storage; } int DateTime::GetYear() const { return sep_time.year; } int DateTime::GetMonth() const { return sep_time.month; } int DateTime::GetDay() const { return sep_time.day; } int DateTime::GetHour() const { return sep_time.hour; } int DateTime::GetMinute() const { return sep_time.minute; } int DateTime::GetSecond() const { return sep_time.second; } DateTime::Full DateTime::GetFullDateTime() const { return sep_time; } std::string DateTime::Format(std::string fmt_str) { namespace ch = std::chrono; try { // 1. 获取系统标准时间点 auto tp = ch::system_clock::from_time_t(storage); // 2. 转换为本地时间点 auto local_tp = ch::current_zone()->to_local(tp); // 3. 截断到秒级精度(防止打印出纳秒/微秒的小数点),并获取 C++20 支持格式化的强类型 auto local_secs = ch::floor(local_tp); // 4. 组装 C++20 chrono 格式化字符串并执行 std::string chrono_fmt = "{:" + fmt_str + "}"; return std::vformat(chrono_fmt, std::make_format_args(local_secs)); } catch (...) { // 如果 C++20 运行时时区数据库不可用,或者 fmt_str 包含不兼容的传统旧语法,平滑降级 size_t size = (fmt_str.size() * 2) + 10; auto recv = std::make_unique(size); std::tm suctm = static_cast(*this); size_t ret = ::strftime(recv.get(), size, fmt_str.c_str(), &suctm); while (ret == 0) { size *= 2; recv = std::make_unique(size); ret = ::strftime(recv.get(), size, fmt_str.c_str(), &suctm); } return std::string(recv.get()); } } bool DateTime::IsAM() { return (sep_time.hour < 12); } // 修正逻辑:通常12点后为PM bool DateTime::IsPM() { return (sep_time.hour >= 12); } bool DateTime::TimePassed() { return (storage < ::time(nullptr)); } // 修正逻辑:过去的时间应该小于现在 DateTime::operator tm() { std::tm stm {}; stm.tm_year = sep_time.year - 1900; stm.tm_mon = sep_time.month - 1; stm.tm_mday = sep_time.day; stm.tm_hour = sep_time.hour; stm.tm_min = sep_time.minute; stm.tm_sec = sep_time.second; stm.tm_isdst = -1; return stm; } DateTime::operator Full() { return sep_time; } DateTime::operator time_t() { return storage; } DateTime::operator std::string() { return Format("%Y-%m-%dT%H:%M:%S+08:00"); } // ================== 运算符重载实现 ================== DateTime::Span DateTime::operator-(const tm& stm) { return ToSpan(storage - ::mktime(const_cast(&stm))); } DateTime::Span DateTime::operator-(const Span& ts) { return ToSpan(storage - SpanedSeconds(ts)); } DateTime::Span DateTime::operator-(const Full& sdt) { return ToSpan(storage - FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second)); } DateTime::Span DateTime::operator-(const time_t& t) { return ToSpan(storage - t); } DateTime::Span DateTime::operator-(const DateTime& dt) { return ToSpan(storage - dt.storage); } DateTime::Span DateTime::operator+(const tm& stm) { return ToSpan(storage + ::mktime(const_cast(&stm))); } DateTime::Span DateTime::operator+(const Span& ts) { return ToSpan(storage + SpanedSeconds(ts)); } DateTime::Span DateTime::operator+(const Full& sdt) { return ToSpan(storage + FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second)); } DateTime::Span DateTime::operator+(const time_t& t) { return ToSpan(storage + t); } DateTime::Span DateTime::operator+(const DateTime& dt) { return ToSpan(storage + dt.storage); } DateTime DateTime::operator=(const tm& stm) { storage = ::mktime(const_cast(&stm)); UpdateDT(); return *this; } DateTime DateTime::operator=(const Full& sdt) { storage = FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); UpdateDT(); return *this; } DateTime DateTime::operator=(const time_t& t) { storage = t; UpdateDT(); return *this; } DateTime DateTime::operator=(const DateTime& dt) { storage = dt.storage; UpdateDT(); return *this; } DateTime DateTime::operator+=(const tm& stm) { storage += ::mktime(const_cast(&stm)); UpdateDT(); return *this; } DateTime DateTime::operator+=(const Span& ts) { storage += SpanedSeconds(ts); UpdateDT(); return *this; } DateTime DateTime::operator+=(const Full& sdt) { storage += FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); UpdateDT(); return *this; } DateTime DateTime::operator+=(const time_t& t) { storage += t; UpdateDT(); return *this; } DateTime DateTime::operator+=(const DateTime& dt) { storage += dt.storage; UpdateDT(); return *this; } DateTime DateTime::operator-=(const tm& stm) { storage -= ::mktime(const_cast(&stm)); UpdateDT(); return *this; } DateTime DateTime::operator-=(const Span& ts) { storage -= SpanedSeconds(ts); UpdateDT(); return *this; } DateTime DateTime::operator-=(const Full& sdt) { storage -= FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); UpdateDT(); return *this; } DateTime DateTime::operator-=(const time_t& t) { storage -= t; UpdateDT(); return *this; } DateTime DateTime::operator-=(const DateTime& dt) { storage -= dt.storage; UpdateDT(); return *this; } bool DateTime::operator==(const tm& stm) { return storage == ::mktime(const_cast(&stm)); } bool DateTime::operator==(const Full& sdt) { return storage == FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); } bool DateTime::operator==(const time_t& t) { return storage == t; } bool DateTime::operator==(const DateTime& dt) { return storage == dt.storage; } bool DateTime::operator!=(const tm& stm) { return !(*this == stm); } bool DateTime::operator!=(const Full& sdt) { return !(*this == sdt); } bool DateTime::operator!=(const time_t& t) { return storage != t; } bool DateTime::operator!=(const DateTime& dt) { return storage != dt.storage; } bool DateTime::operator>(const tm& stm) { return storage > ::mktime(const_cast(&stm)); } bool DateTime::operator>(const Full& sdt) { return storage > FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); } bool DateTime::operator>(const time_t& t) { return storage > t; } bool DateTime::operator>(const DateTime& dt) { return storage > dt.storage; } bool DateTime::operator>=(const tm& stm) { return storage >= ::mktime(const_cast(&stm)); } bool DateTime::operator>=(const Full& sdt) { return storage >= FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); } bool DateTime::operator>=(const time_t& t) { return storage >= t; } bool DateTime::operator>=(const DateTime& dt) { return storage >= dt.storage; } bool DateTime::operator<(const tm& stm) { return storage < ::mktime(const_cast(&stm)); } bool DateTime::operator<(const Full& sdt) { return storage < FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); } bool DateTime::operator<(const time_t& t) { return storage < t; } bool DateTime::operator<(const DateTime& dt) { return storage < dt.storage; } bool DateTime::operator<(const DateTime& dt) const { return storage < dt.storage; } bool DateTime::operator<=(const tm& stm) { return storage <= ::mktime(const_cast(&stm)); } bool DateTime::operator<=(const Full& sdt) { return storage <= FormatConvert(sdt.year, sdt.month, sdt.day, sdt.hour, sdt.minute, sdt.second); } bool DateTime::operator<=(const time_t& t) { return storage <= t; } bool DateTime::operator<=(const DateTime& dt) { return storage <= dt.storage; }