// This file is originally from Trantor - Date.cc // Copyright (c) 2016-2021, Tao An. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of Tao An nor the names of other contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "date.h" #include "core/utilities.h" #ifndef _WIN32 #include #endif #include #include #include #ifdef _WIN32 #include #include #endif #ifdef _WIN32 int gettimeofday(timeval *tp, void *tzp) { time_t clock; struct tm tm; SYSTEMTIME wtm; GetLocalTime(&wtm); tm.tm_year = wtm.wYear - 1900; tm.tm_mon = wtm.wMonth - 1; tm.tm_mday = wtm.wDay; tm.tm_hour = wtm.wHour; tm.tm_min = wtm.wMinute; tm.tm_sec = wtm.wSecond; tm.tm_isdst = -1; clock = mktime(&tm); tp->tv_sec = static_cast(clock); tp->tv_usec = wtm.wMilliseconds * 1000; return (0); } #endif const Date Date::date() { #ifndef _WIN32 struct timeval tv; gettimeofday(&tv, NULL); int64_t seconds = tv.tv_sec; return Date(seconds * MICRO_SECONDS_PRE_SEC + tv.tv_usec); #else timeval tv; gettimeofday(&tv, NULL); int64_t seconds = tv.tv_sec; return Date(seconds * MICRO_SECONDS_PRE_SEC + tv.tv_usec); #endif } const Date Date::after(double second) const { return Date(static_cast(microSecondsSinceEpoch_ + second * MICRO_SECONDS_PRE_SEC)); } const Date Date::roundSecond() const { return Date(microSecondsSinceEpoch_ - (microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC)); } const Date Date::roundDay() const { struct tm t; time_t seconds = static_cast(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); #ifndef _WIN32 localtime_r(&seconds, &t); #else localtime_s(&t, &seconds); #endif t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0; return Date(mktime(&t) * MICRO_SECONDS_PRE_SEC); } struct tm Date::tmStruct() const { time_t seconds = static_cast(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); struct tm tm_time; #ifndef _WIN32 gmtime_r(&seconds, &tm_time); #else gmtime_s(&tm_time, &seconds); #endif return tm_time; } std::string Date::toFormattedString(bool showMicroseconds) const { // std::cout<<"toFormattedString"<(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); struct tm tm_time; #ifndef _WIN32 gmtime_r(&seconds, &tm_time); #else gmtime_s(&tm_time, &seconds); #endif if (showMicroseconds) { int microseconds = static_cast(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC); snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, microseconds); } else { snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); } return buf; } std::string Date::toCustomedFormattedString(const std::string &fmtStr, bool showMicroseconds) const { char buf[256] = { 0 }; time_t seconds = static_cast(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); struct tm tm_time; #ifndef _WIN32 gmtime_r(&seconds, &tm_time); #else gmtime_s(&tm_time, &seconds); #endif strftime(buf, sizeof(buf), fmtStr.c_str(), &tm_time); if (!showMicroseconds) return std::string(buf); char decimals[12] = { 0 }; int microseconds = static_cast(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC); snprintf(decimals, sizeof(decimals), ".%06d", microseconds); return std::string(buf) + decimals; } void Date::toCustomedFormattedString(const std::string &fmtStr, char *str, size_t len) const { // not safe time_t seconds = static_cast(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); struct tm tm_time; #ifndef _WIN32 gmtime_r(&seconds, &tm_time); #else gmtime_s(&tm_time, &seconds); #endif strftime(str, len, fmtStr.c_str(), &tm_time); } std::string Date::toFormattedStringLocal(bool showMicroseconds) const { // std::cout<<"toFormattedString"<(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); struct tm tm_time; #ifndef _WIN32 localtime_r(&seconds, &tm_time); #else localtime_s(&tm_time, &seconds); #endif if (showMicroseconds) { int microseconds = static_cast(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC); snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, microseconds); } else { snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); } return buf; } std::string Date::toDbStringLocal() const { char buf[128] = { 0 }; time_t seconds = static_cast(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); struct tm tm_time; #ifndef _WIN32 localtime_r(&seconds, &tm_time); #else localtime_s(&tm_time, &seconds); #endif bool showMicroseconds = (microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC != 0); if (showMicroseconds) { int microseconds = static_cast(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC); snprintf(buf, sizeof(buf), "%4d-%02d-%02d %02d:%02d:%02d.%06d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, microseconds); } else { if (*this == roundDay()) { snprintf(buf, sizeof(buf), "%4d-%02d-%02d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday); } else { snprintf(buf, sizeof(buf), "%4d-%02d-%02d %02d:%02d:%02d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec); } } return buf; } Date Date::fromDbStringLocal(const std::string &datetime) { unsigned int year = { 0 }, month = { 0 }, day = { 0 }, hour = { 0 }, minute = { 0 }, second = { 0 }, microSecond = { 0 }; std::vector &&v = Utilities::splitString(datetime, " "); if (2 == v.size()) { // date std::vector date = Utilities::splitString(v[0], "-"); if (3 == date.size()) { year = std::stol(date[0]); month = std::stol(date[1]); day = std::stol(date[2]); std::vector time = Utilities::splitString(v[1], ":"); if (2 < time.size()) { hour = std::stol(time[0]); minute = std::stol(time[1]); auto seconds = Utilities::splitString(time[2], "."); second = std::stol(seconds[0]); if (1 < seconds.size()) { if (seconds[1].length() > 6) { seconds[1].resize(6); } else if (seconds[1].length() < 6) { seconds[1].append(6 - seconds[1].length(), '0'); } microSecond = std::stol(seconds[1]); } } } } return std::move( Date(year, month, day, hour, minute, second, microSecond)); } std::string Date::toCustomedFormattedStringLocal(const std::string &fmtStr, bool showMicroseconds) const { char buf[256] = { 0 }; time_t seconds = static_cast(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC); struct tm tm_time; #ifndef _WIN32 localtime_r(&seconds, &tm_time); #else localtime_s(&tm_time, &seconds); #endif strftime(buf, sizeof(buf), fmtStr.c_str(), &tm_time); if (!showMicroseconds) return std::string(buf); char decimals[12] = { 0 }; int microseconds = static_cast(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC); snprintf(decimals, sizeof(decimals), ".%06d", microseconds); return std::string(buf) + decimals; } Date::Date(unsigned int year, unsigned int month, unsigned int day, unsigned int hour, unsigned int minute, unsigned int second, unsigned int microSecond) { struct tm tm; memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; time_t epoch; tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = minute; tm.tm_sec = second; epoch = mktime(&tm); microSecondsSinceEpoch_ = epoch * MICRO_SECONDS_PRE_SEC + microSecond; }