467 lines
12 KiB
C++
467 lines
12 KiB
C++
#ifndef A283B06E_3ED5_4D78_A2B5_4B87495A80A6
|
|
#define A283B06E_3ED5_4D78_A2B5_4B87495A80A6
|
|
#include <chrono>
|
|
#include <cmath>
|
|
#include <ctime>
|
|
#include <string>
|
|
#include "Poco/DateTime.h"
|
|
#include "Poco/DateTimeFormat.h"
|
|
#include "Poco/DateTimeFormatter.h"
|
|
#include "Poco/DateTimeParser.h"
|
|
#include "Poco/Exception.h"
|
|
#include "Poco/LocalDateTime.h"
|
|
#include "Poco/Timespan.h"
|
|
#include "Poco/Timestamp.h"
|
|
namespace Util
|
|
{
|
|
class DateTimeUtils
|
|
{
|
|
public:
|
|
static Poco::DateTime now()
|
|
{
|
|
return Poco::DateTime();
|
|
}
|
|
|
|
static Poco::LocalDateTime localNow()
|
|
{
|
|
return Poco::LocalDateTime();
|
|
}
|
|
|
|
static std::string nowStr(const std::string& formatStr = "%Y-%m-%d %H:%M:%S")
|
|
{
|
|
return format(Poco::DateTime(), formatStr);
|
|
}
|
|
|
|
static std::string localNowStr(const std::string& formatStr = "%Y-%m-%d %H:%M:%S")
|
|
{
|
|
return Poco::DateTimeFormatter::format(Poco::LocalDateTime(), formatStr);
|
|
}
|
|
|
|
static Poco::DateTime parse(const std::string& str, const std::string& formatStr = "")
|
|
{
|
|
auto dt = Poco::DateTime(1970, 1, 1);
|
|
if (str.empty())
|
|
{
|
|
return dt;
|
|
}
|
|
int timeZoneDifferential = 0;
|
|
if (!formatStr.empty())
|
|
{
|
|
if (Poco::DateTimeParser::tryParse(formatStr, str, dt, timeZoneDifferential))
|
|
{
|
|
return dt;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Poco::DateTimeParser::tryParse(Poco::DateTimeFormat::ISO8601_FORMAT, str, dt, timeZoneDifferential) ||
|
|
Poco::DateTimeParser::tryParse("%Y-%m-%d %H:%M:%S", str, dt, timeZoneDifferential) ||
|
|
Poco::DateTimeParser::tryParse("%Y/%m/%d %H:%M:%S", str, dt, timeZoneDifferential) ||
|
|
Poco::DateTimeParser::tryParse("%Y%m%d%H%M%S", str, dt, timeZoneDifferential))
|
|
{
|
|
return dt;
|
|
}
|
|
}
|
|
return dt;
|
|
}
|
|
|
|
static std::string format(const Poco::DateTime& dt, const std::string& formatStr = "%Y-%m-%d %H:%M:%S")
|
|
{
|
|
return Poco::DateTimeFormatter::format(dt, formatStr);
|
|
}
|
|
|
|
static std::string toISO8601(const Poco::DateTime& dt)
|
|
{
|
|
return Poco::DateTimeFormatter::format(dt, Poco::DateTimeFormat::ISO8601_FORMAT);
|
|
}
|
|
|
|
static std::string toRFC1123(const Poco::DateTime& dt)
|
|
{
|
|
return Poco::DateTimeFormatter::format(dt, Poco::DateTimeFormat::RFC1123_FORMAT);
|
|
}
|
|
|
|
static Poco::DateTime addDays(const Poco::DateTime& dt, int days)
|
|
{
|
|
return dt + Poco::Timespan(days, 0, 0, 0, 0);
|
|
}
|
|
|
|
static Poco::DateTime addHours(const Poco::DateTime& dt, int hours)
|
|
{
|
|
return dt + Poco::Timespan(0, hours, 0, 0, 0);
|
|
}
|
|
|
|
static Poco::DateTime addMinutes(const Poco::DateTime& dt, int minutes)
|
|
{
|
|
return dt + Poco::Timespan(0, 0, minutes, 0, 0);
|
|
}
|
|
|
|
static Poco::DateTime addSeconds(const Poco::DateTime& dt, int seconds)
|
|
{
|
|
return dt + Poco::Timespan(0, 0, 0, seconds, 0);
|
|
}
|
|
|
|
static Poco::Timespan diff(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp ts1 = dt1.timestamp();
|
|
Poco::Timestamp ts2 = dt2.timestamp();
|
|
|
|
Poco::Timestamp::TimeDiff diffMicroseconds = 0;
|
|
|
|
if (ts1 > ts2)
|
|
{
|
|
diffMicroseconds = ts1 - ts2;
|
|
}
|
|
else
|
|
{
|
|
diffMicroseconds = ts2 - ts1;
|
|
}
|
|
|
|
return Poco::Timespan(diffMicroseconds);
|
|
}
|
|
|
|
static long diffSeconds(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp ts1 = dt1.timestamp();
|
|
Poco::Timestamp ts2 = dt2.timestamp();
|
|
|
|
Poco::Timestamp::TimeDiff diffMicroseconds = 0;
|
|
|
|
if (ts1 > ts2)
|
|
{
|
|
diffMicroseconds = ts1 - ts2;
|
|
}
|
|
else
|
|
{
|
|
diffMicroseconds = ts2 - ts1;
|
|
}
|
|
|
|
Poco::Timespan ts(diffMicroseconds);
|
|
return ts.totalSeconds();
|
|
}
|
|
|
|
static long long diffMilliseconds(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp ts1 = dt1.timestamp();
|
|
Poco::Timestamp ts2 = dt2.timestamp();
|
|
|
|
Poco::Timestamp::TimeDiff diffMicroseconds = 0;
|
|
|
|
if (ts1 > ts2)
|
|
{
|
|
diffMicroseconds = ts1 - ts2;
|
|
}
|
|
else
|
|
{
|
|
diffMicroseconds = ts2 - ts1;
|
|
}
|
|
|
|
return diffMicroseconds / 1000;
|
|
}
|
|
|
|
static long long diffMicroseconds(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp ts1 = dt1.timestamp();
|
|
Poco::Timestamp ts2 = dt2.timestamp();
|
|
|
|
Poco::Timestamp::TimeDiff diffMicroseconds = 0;
|
|
|
|
if (ts1 > ts2)
|
|
{
|
|
diffMicroseconds = ts1 - ts2;
|
|
}
|
|
else
|
|
{
|
|
diffMicroseconds = ts2 - ts1;
|
|
}
|
|
|
|
return diffMicroseconds;
|
|
}
|
|
|
|
static void diffComponents(const Poco::DateTime& dt1, const Poco::DateTime& dt2, int& days, int& hours,
|
|
int& minutes, int& seconds)
|
|
{
|
|
Poco::Timespan ts = diff(dt1, dt2);
|
|
days = ts.days();
|
|
hours = ts.hours();
|
|
minutes = ts.minutes();
|
|
seconds = ts.seconds();
|
|
}
|
|
|
|
static Poco::Timespan calculateDifference(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp::TimeVal us1 = dt1.timestamp().epochMicroseconds();
|
|
Poco::Timestamp::TimeVal us2 = dt2.timestamp().epochMicroseconds();
|
|
|
|
Poco::Timestamp::TimeVal diff = 0;
|
|
if (us1 > us2)
|
|
{
|
|
diff = us1 - us2;
|
|
}
|
|
else
|
|
{
|
|
diff = us2 - us1;
|
|
}
|
|
|
|
return Poco::Timespan(diff);
|
|
}
|
|
|
|
static bool isBefore(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp ts1 = dt1.timestamp();
|
|
Poco::Timestamp ts2 = dt2.timestamp();
|
|
return ts1 < ts2;
|
|
}
|
|
|
|
static bool isAfter(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp ts1 = dt1.timestamp();
|
|
Poco::Timestamp ts2 = dt2.timestamp();
|
|
return ts1 > ts2;
|
|
}
|
|
|
|
static bool isEqual(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timestamp ts1 = dt1.timestamp();
|
|
Poco::Timestamp ts2 = dt2.timestamp();
|
|
return ts1 == ts2;
|
|
}
|
|
|
|
static bool isLeapYear(int year)
|
|
{
|
|
return Poco::DateTime::isLeapYear(year);
|
|
}
|
|
|
|
static int daysInMonth(int year, int month)
|
|
{
|
|
if (month < 1 || month > 12)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Poco::DateTime nextMonth;
|
|
if (month == 12)
|
|
{
|
|
nextMonth = Poco::DateTime(year + 1, 1, 1);
|
|
}
|
|
else
|
|
{
|
|
nextMonth = Poco::DateTime(year, month + 1, 1);
|
|
}
|
|
|
|
Poco::DateTime lastDay = nextMonth - Poco::Timespan(1, 0, 0, 0, 0);
|
|
return lastDay.day();
|
|
}
|
|
|
|
static std::string getWeekdayName(int dayOfWeek)
|
|
{
|
|
static const std::string weekdays[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
|
|
|
|
if (dayOfWeek >= 0 && dayOfWeek <= 6)
|
|
{
|
|
return weekdays[dayOfWeek];
|
|
}
|
|
return "未知";
|
|
}
|
|
|
|
static time_t getTimestamp()
|
|
{
|
|
Poco::Timestamp ts;
|
|
return ts.epochTime();
|
|
}
|
|
|
|
static long long getTimestampMs()
|
|
{
|
|
Poco::Timestamp ts;
|
|
return ts.epochMicroseconds() / 1000;
|
|
}
|
|
|
|
static long long getTimestampUs()
|
|
{
|
|
Poco::Timestamp ts;
|
|
return ts.epochMicroseconds();
|
|
}
|
|
|
|
static Poco::DateTime fromTimestamp(time_t timestamp)
|
|
{
|
|
Poco::Timestamp ts(static_cast<Poco::Timestamp::TimeVal>(timestamp) * 1000000);
|
|
return Poco::DateTime(ts);
|
|
}
|
|
|
|
static Poco::DateTime fromTimestampMs(long long timestampMs)
|
|
{
|
|
Poco::Timestamp ts(static_cast<Poco::Timestamp::TimeVal>(timestampMs) * 1000);
|
|
return Poco::DateTime(ts);
|
|
}
|
|
|
|
static Poco::DateTime fromTimestampUs(long long timestampUs)
|
|
{
|
|
Poco::Timestamp ts(static_cast<Poco::Timestamp::TimeVal>(timestampUs));
|
|
return Poco::DateTime(ts);
|
|
}
|
|
|
|
static Poco::Timestamp toTimestamp(const Poco::DateTime& dt)
|
|
{
|
|
return dt.timestamp();
|
|
}
|
|
|
|
static Poco::DateTime toDateTime(const Poco::Timestamp& ts)
|
|
{
|
|
return Poco::DateTime(ts);
|
|
}
|
|
|
|
static Poco::DateTime getStartOfDay(const Poco::DateTime& dt)
|
|
{
|
|
return Poco::DateTime(dt.year(), dt.month(), dt.day());
|
|
}
|
|
|
|
static Poco::DateTime getEndOfDay(const Poco::DateTime& dt)
|
|
{
|
|
return Poco::DateTime(dt.year(), dt.month(), dt.day(), 23, 59, 59, 999999);
|
|
}
|
|
|
|
static int getAge(const Poco::DateTime& birthDate)
|
|
{
|
|
Poco::DateTime now = DateTimeUtils::now();
|
|
|
|
int age = now.year() - birthDate.year();
|
|
|
|
if (now.month() < birthDate.month() || (now.month() == birthDate.month() && now.day() < birthDate.day()))
|
|
{
|
|
age--;
|
|
}
|
|
|
|
return age;
|
|
}
|
|
|
|
static bool isSameDay(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
return dt1.year() == dt2.year() && dt1.month() == dt2.month() && dt1.day() == dt2.day();
|
|
}
|
|
|
|
static std::string formatTimespan(const Poco::Timespan& ts)
|
|
{
|
|
std::string result;
|
|
|
|
if (ts.days() > 0)
|
|
{
|
|
result += std::to_string(ts.days()) + "天";
|
|
}
|
|
|
|
if (ts.hours() > 0)
|
|
{
|
|
result += std::to_string(ts.hours()) + "小时";
|
|
}
|
|
|
|
if (ts.minutes() > 0)
|
|
{
|
|
result += std::to_string(ts.minutes()) + "分";
|
|
}
|
|
|
|
if (ts.seconds() > 0)
|
|
{
|
|
result += std::to_string(ts.seconds()) + "秒";
|
|
}
|
|
|
|
if (result.empty())
|
|
{
|
|
result = "0秒";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static std::string formatTimeDifference(const Poco::DateTime& dt1, const Poco::DateTime& dt2)
|
|
{
|
|
Poco::Timespan diff = calculateDifference(dt1, dt2);
|
|
return formatTimespan(diff);
|
|
}
|
|
|
|
static std::string formatTimespanWithMs(const Poco::Timespan& ts)
|
|
{
|
|
std::string result = formatTimespan(ts);
|
|
|
|
int milliseconds = ts.milliseconds();
|
|
if (milliseconds > 0)
|
|
{
|
|
result += std::to_string(milliseconds) + "毫秒";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static int getWeekOfYear(const Poco::DateTime& dt)
|
|
{
|
|
Poco::DateTime firstDay(dt.year(), 1, 1);
|
|
|
|
Poco::Timespan diff = dt - firstDay;
|
|
int dayOfYear = diff.days() + 1;
|
|
|
|
int firstDayWeek = firstDay.dayOfWeek();
|
|
int week = (dayOfYear + firstDayWeek - 1) / 7 + 1;
|
|
|
|
return week;
|
|
}
|
|
|
|
static Poco::DateTime getFirstDayOfMonth(const Poco::DateTime& dt)
|
|
{
|
|
return Poco::DateTime(dt.year(), dt.month(), 1);
|
|
}
|
|
|
|
static Poco::DateTime getLastDayOfMonth(const Poco::DateTime& dt)
|
|
{
|
|
int lastDay = daysInMonth(dt.year(), dt.month());
|
|
return Poco::DateTime(dt.year(), dt.month(), lastDay);
|
|
}
|
|
|
|
static Poco::DateTime getFirstDayOfWeek(const Poco::DateTime& dt)
|
|
{
|
|
int dayOfWeek = dt.dayOfWeek();
|
|
int daysToMonday = (dayOfWeek == 0) ? 6 : (dayOfWeek - 1);
|
|
return addDays(dt, -daysToMonday);
|
|
}
|
|
|
|
static Poco::DateTime getLastDayOfWeek(const Poco::DateTime& dt)
|
|
{
|
|
int dayOfWeek = dt.dayOfWeek();
|
|
int daysToSunday = (dayOfWeek == 0) ? 0 : (7 - dayOfWeek);
|
|
return addDays(dt, daysToSunday);
|
|
}
|
|
|
|
static long long getTime(const Poco::DateTime& dt)
|
|
{
|
|
Poco::Timestamp ts = dt.timestamp();
|
|
return ts.epochMicroseconds() / 1000;
|
|
}
|
|
|
|
static time_t getTimeSeconds(const Poco::DateTime& dt)
|
|
{
|
|
Poco::Timestamp ts = dt.timestamp();
|
|
return ts.epochTime();
|
|
}
|
|
|
|
static Poco::DateTime fromTime(long long milliseconds)
|
|
{
|
|
Poco::Timestamp ts(static_cast<Poco::Timestamp::TimeVal>(milliseconds) * 1000);
|
|
return Poco::DateTime(ts);
|
|
}
|
|
|
|
static Poco::DateTime fromTimeSeconds(time_t seconds)
|
|
{
|
|
Poco::Timestamp ts(static_cast<Poco::Timestamp::TimeVal>(seconds) * 1000000);
|
|
return Poco::DateTime(ts);
|
|
}
|
|
|
|
static long long currentTimeMillis()
|
|
{
|
|
Poco::Timestamp ts;
|
|
return ts.epochMicroseconds() / 1000;
|
|
}
|
|
|
|
static time_t currentTimeSeconds()
|
|
{
|
|
Poco::Timestamp ts;
|
|
return ts.epochTime();
|
|
}
|
|
};
|
|
}
|
|
#endif
|