软件架构设计之Utility模块——DateTime
这里的日期实现比较简单:采用的是UTC日期(现在还不涉及到其他日期格式的转换如Gregorian日历),且以星期一作为每周的第一天。剩下的就看代码吧:
头文件:
class UTIL_API YKDateTime { public: enum DT_FORM { DTF_YMDHMS1, //%Y-%m-%d %H:%M:%S,中文格式选此 DTF_YMDHMS2, //%m/%d/%Y %H:%M:%S DTF_YMDHM1, //%Y-%m-%d %H:%M,中文格式选此 DTF_YMDHM2, //%Y/%m/%d %H:%M DTF_YMD1, //%Y-%m-%d,中文格式选此 DTF_YMD2, //%Y/%m/%d DTF_HMS1, //%H:%M:%S,中文格式选此 DTF_HM1, //%H:%M,中文格式选此 DTF_MDYHMS1, //%m-%d-%Y %H:%M:%S DTF_MDYHMS2, //%m/%d/%Y %H:%M:%S DTF_MDYHM1, //%m-%d-%Y %H:%M DTF_MDYHM2, //%m/%d/%Y %H:%M DTF_MDY1, //%m-%d-%Y DTF_MDY2, //%m/%d/%Y }; static YK_UINT PER_SECOND; static YK_UINT PER_MINUTE; static YK_UINT PER_HOUR; static YK_UINT PER_DAY; //static YK_UINT PER_MONTH; 每个月的天数并不相同,因此不定义 static YK_UINT PER_YEAR; public: YKDateTime(YK_TM tm = 0); YKDateTime(YK_INT nYear, YK_INT nMonth, YK_INT nDay, YK_INT nHour = 0, YK_INT nMinute = 0, YK_INT nSecond = 0); ~YKDateTime(void); static YKDateTime GetLocalTime(); YKDateTime& operator=(YK_TM tm) { m_time = tm; return *this; } // 是否是有效日期 YK_BOOL ValidDateTime(); YK_TM GetDateTime() const { return m_time; } YKDateTime GetDate(); // 获取年月日 YK_INT GetYear() const; // 获取年 YK_INT GetMonth() const; // 获取月 YK_INT GetDay() const; // 获取天 YK_INT GetHour() const; // 获取小时 YK_INT GetMinute() const; // 获取分钟 YK_INT GetSecond() const; // 获取秒 YK_INT GetDayOfYear() const; // 获取时间所在年的第几天 YK_INT GetDayOfMonth() const; // 获取时间所在月的第几天 YK_INT GetDayOfWeek() const; // 获取时间所在周的第几天,星期一作为第一天,(1~7) YK_INT GetWeekOfYear() const; // 获取时间所在年的第几周,星期一作为第一天,(1~54) YK_INT GetWeekOfMonth() const; // 获取时间所在月的第几周 YK_INT GetFirstDayOfWeek() const; // 获取时间所在周的第一天 YKString Format(DT_FORM dtf = DTF_YMDHMS1); // 日期或时间中文格式化 XXXX年XX月XX日 XX时XX分XX秒 YKString FormatChs(DT_FORM dtf = DTF_YMDHMS1); YKString FormatPostfix(YK_WCHAR postfix); // 从字符串中提取日期时间 static YKDateTime ParseDateTime(const YKString& str, DT_FORM tf = DTF_YMDHMS1); static YKDateTime ParseDateTimeChs(const YKString& str, DT_FORM tf = DTF_YMDHMS1); // 与当前时间相比,是否流逝了val秒 YK_BOOL IsElapsed(YK_TM val) const; void AddSecond(YK_INT second) { *this += (second); } void AddMinute(YK_INT minute) { AddSecond(minute*PER_MINUTE); } void AddHour(YK_INT hour) { AddMinute(hour*PER_HOUR); } void AddDay(YK_INT day) { AddHour(day*PER_DAY); } void AddMonth(YK_INT month); void AddYear(YK_INT year) { AddMonth(year*PER_YEAR); } YKDateTime& operator+=(const YKDateTime& tm) { this->m_time += tm.m_time; return *this; } YKDateTime& operator-=(const YKDateTime& tm) { this->m_time -= tm.m_time; return *this; } YK_BOOL operator==(const YKDateTime& tm) const { return this->m_time == tm.m_time; } YK_BOOL operator!=(const YKDateTime& tm ) const { return !(*this == tm); } YK_BOOL operator>(const YKDateTime& tm ) const { return this->m_time > tm.m_time; } YK_BOOL operator>=(const YKDateTime& tm ) const { return !(*this < tm); } YK_BOOL operator<(const YKDateTime& tm ) const { return tm > *this ; } YK_BOOL operator<=(const YKDateTime& tm ) const { return !(*this > tm); } protected: YKString GetDTFormValue(DT_FORM dtf); private: YK_TM m_time; };
实现部分:
YK_UINT YKDateTime::PER_SECOND = 1000; YK_UINT YKDateTime::PER_MINUTE = 60; YK_UINT YKDateTime::PER_HOUR = 60; YK_UINT YKDateTime::PER_DAY = 24; YK_UINT YKDateTime::PER_YEAR = 12; YKDateTime::YKDateTime( YK_TM tm /* = 0 */ ) : m_time(tm) { } YKDateTime::YKDateTime( YK_INT nYear, YK_INT nMonth, YK_INT nDay, YK_INT nHour /*= 0*/, YK_INT nMinute /*= 0*/, YK_INT nSecond /*= 0*/ ) { tm t1; t1.tm_year = nYear-1900; t1.tm_mon = nMonth-1; t1.tm_mday = nDay; t1.tm_hour = nHour; t1.tm_min = nMinute; t1.tm_sec = nSecond; m_time = _mktime64(&t1); } YKDateTime::~YKDateTime(void) { } YKDateTime YKDateTime::GetLocalTime() { return YKDateTime(time(NULL)); } YK_BOOL YKDateTime::ValidDateTime() { YKDateTime dtTemp(1900, 1, 1); return m_time >= dtTemp.m_time; } YKDateTime YKDateTime::GetDate() { return YKDateTime(GetYear(), GetMonth(), GetDay()); } YK_INT YKDateTime::GetYear() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_year + 1900; } YK_INT YKDateTime::GetMonth() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_mon + 1; } YK_INT YKDateTime::GetDay() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_mday; } YK_INT YKDateTime::GetHour() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_hour; } YK_INT YKDateTime::GetMinute() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_min; } YK_INT YKDateTime::GetSecond() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_sec; } YK_INT YKDateTime::GetDayOfYear() const { tm t1; localtime_s(&t1, &m_time); char temp[128]; strftime(temp, 128, "%j", &t1); return atoi(temp); } YK_INT YKDateTime::GetDayOfMonth() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_mday; } YK_INT YKDateTime::GetDayOfWeek() const { tm t1; localtime_s(&t1, &m_time); return t1.tm_wday == 0 ? 7 : t1.tm_wday; } YK_INT YKDateTime::GetWeekOfYear() const { tm t1; localtime_s(&t1, &m_time); char temp[128]; strftime(temp, 128, "%W", &t1); return atoi(temp)+1; } YK_INT YKDateTime::GetWeekOfMonth() const { tm t1; localtime_s(&t1, &m_time); char temp[128]; strftime(temp, 128, "%w", &t1); return atoi(temp); } YK_INT YKDateTime::GetFirstDayOfWeek() const { YKDateTime dt(m_time); YK_INT dayDiff = GetDayOfWeek()-1; assert(dayDiff > 0); dt.AddDay(-dayDiff); return dt.GetDay(); } YKString YKDateTime::Format( DT_FORM dtf /* = TF_YMDHMS1 */ ) { tm t1; localtime_s(&t1, &m_time); YK_WCHAR temp[128]; wcsftime(temp, 128, GetDTFormValue(dtf).c_str(), &t1); return temp; } YKString YKDateTime::FormatChs( DT_FORM dtf /* = DTF_YMDHMS1 */ ) { tm t1; localtime_s(&t1, &m_time); YKString str; YK_BOOL bDate = false; switch (dtf) { case DTF_YMDHMS1: case DTF_YMDHM1: case DTF_YMD1: { str += YKString::Format(t1.tm_year+1900) + L"年"; str += YKString::FormatDigit(t1.tm_mon+1, 2) + L"月"; str += YKString::FormatDigit(t1.tm_mday, 2) + L"日"; bDate = true; } break; } switch (dtf) { case DTF_YMDHMS1: case DTF_YMDHM1: case DTF_HMS1: case DTF_HM1: { if (bDate) str += L" "; str += YKString::FormatDigit(t1.tm_hour, 2) + L"时"; str += YKString::FormatDigit(t1.tm_min, 2) + L"分"; } break; } switch (dtf) { case DTF_YMDHMS1: case DTF_HMS1: { str += YKString::FormatDigit(t1.tm_sec, 2) + L"秒"; } break; } return str; } YKString YKDateTime::FormatPostfix(YK_WCHAR postfix) { YKString str; switch (postfix) { case L'S': str = YKString::Format(m_time); break; case L'M': str = YKString::Format(((YK_DOUBLE)m_time)/PER_MINUTE); break; case L'H': str = YKString::Format(((YK_DOUBLE)m_time)/(PER_HOUR*PER_MINUTE)); break; case L'D': str = YKString::Format(((YK_DOUBLE)m_time)/(PER_DAY*PER_HOUR*PER_MINUTE)); break; default: return str; } str += postfix; return str; } YKDateTime YKDateTime::ParseDateTime(const YKString& str, DT_FORM tf /* = TF_YMDHMS1 */) { switch (tf) { case DTF_YMDHMS1: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"-"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 3) { return YKDateTime(vecDate[0], vecDate[1], vecDate[2], vecTime[0], vecTime[1], vecTime[2]); } } } break; case DTF_YMDHMS2: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"/"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 3) { return YKDateTime(vecDate[0], vecDate[1], vecDate[2], vecTime[0], vecTime[1], vecTime[2]); } } } break; case DTF_YMDHM1: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"-"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 2) { return YKDateTime(vecDate[0], vecDate[1], vecDate[2], vecTime[0], vecTime[1]); } } } break; case DTF_YMDHM2: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"/"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 2) { return YKDateTime(vecDate[0], vecDate[1], vecDate[2], vecTime[0], vecTime[1]); } } } break; case DTF_YMD1: { std::vector<YK_ULONG> vecDate = str.Parse<YK_ULONG>(L"-"); if (vecDate.size() == 3) { return YKDateTime(vecDate[0], vecDate[1], vecDate[2]); } } break; case DTF_YMD2: { std::vector<YK_ULONG> vecDate = str.Parse<YK_ULONG>(L"/"); if (vecDate.size() == 3) { return YKDateTime(vecDate[0], vecDate[1], vecDate[2]); } } break; case DTF_HMS1: { std::vector<YK_ULONG> vecTime = str.Parse<YK_ULONG>(L":"); if (vecTime.size() == 3) { return YKDateTime(1970, 1, 1, vecTime[0], vecTime[1], vecTime[2]); } } break; case DTF_HM1: { std::vector<YK_ULONG> vecTime = str.Parse<YK_ULONG>(L":"); if (vecTime.size() == 2) { return YKDateTime(1970, 1, 1, vecTime[0], vecTime[1]); } } break; case DTF_MDYHMS1: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"-"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 3) { return YKDateTime(vecDate[2], vecDate[0], vecDate[1], vecTime[0], vecTime[1], vecTime[2]); } } } break; case DTF_MDYHMS2: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"/"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 3) { return YKDateTime(vecDate[2], vecDate[0], vecDate[1], vecTime[0], vecTime[1], vecTime[2]); } } } break; case DTF_MDYHM1: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"-"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 2) { return YKDateTime(vecDate[2], vecDate[0], vecDate[1], vecTime[0], vecTime[1]); } } } break; case DTF_MDYHM2: { std::vector<YKString> vecDT = str.Parse<YKString>(L" "); if (vecDT.size() == 2) { std::vector<YK_ULONG> vecDate = vecDT[0].Parse<YK_ULONG>(L"/"); std::vector<YK_ULONG> vecTime = vecDT[1].Parse<YK_ULONG>(L":"); if (vecDate.size() == 3 && vecTime.size() == 2) { return YKDateTime(vecDate[2], vecDate[0], vecDate[1], vecTime[0], vecTime[1]); } } } break; case DTF_MDY1: { std::vector<YK_ULONG> vecDate = str.Parse<YK_ULONG>(L"-"); if (vecDate.size() == 3) { return YKDateTime(vecDate[2], vecDate[0], vecDate[1]); } } break; case DTF_MDY2: { std::vector<YK_ULONG> vecDate = str.Parse<YK_ULONG>(L"/"); if (vecDate.size() == 3) { return YKDateTime(vecDate[2], vecDate[0], vecDate[1]); } } break; } return 0; } YKString YKDateTime::GetDTFormValue( DT_FORM dtf ) { YKString str; switch (dtf) { case DTF_YMDHMS1: str = L"%Y-%m-%d %H:%M:%S"; break; case DTF_YMDHMS2: str = L"%Y/%m/%d %H:%M:%S"; break; case DTF_YMDHM1: str = L"%Y-%m-%d %H:%M"; break; case DTF_YMDHM2: str = L"%Y/%m/%d %H:%M"; break; case DTF_YMD1: str = L"%Y-%m-%d"; break; case DTF_YMD2: str = L"%Y/%m/%d"; break; case DTF_HMS1: str = L"%H:%M:%S"; break; case DTF_HM1: str = L"%H:%M"; break; case DTF_MDYHMS1: str = L"%m-%d-%Y %H:%M:%S"; break; case DTF_MDYHMS2: str = L"%m/%d/%Y %H:%M:%S"; break; case DTF_MDYHM1: str = L"%m-%d-%Y %H:%M"; break; case DTF_MDYHM2: str = L"%m/%d/%Y %H:%M"; break; case DTF_MDY1: str = L"%m-%d-%Y"; break; case DTF_MDY2: str = L"%m/%d/%Y"; break; } return str; } YKDateTime YKDateTime::ParseDateTimeChs( const YKString& str, DT_FORM tf /*= DTF_YMDHMS1*/ ) { YKString::size_type fPos = 0, lPos = 0; std::vector<YK_UINT> vecVal; for (; lPos < str.size(); ++lPos) { if (str.IsAlpha(lPos)) { YKString strTemp = str.substr(fPos, lPos-fPos); strTemp.TrimLeft(); vecVal.push_back(strTemp.Convert<YK_UINT>()); fPos = lPos+1; } } switch (tf) { case DTF_YMDHMS1: return YKDateTime(vecVal[0], vecVal[1], vecVal[2], vecVal[3], vecVal[4], vecVal[5]); break; case DTF_YMDHM1: return YKDateTime(vecVal[0], vecVal[1], vecVal[2], vecVal[3], vecVal[4]); break; case DTF_YMD1: return YKDateTime(vecVal[0], vecVal[1], vecVal[2]); break; case DTF_HMS1: return YKDateTime(1970, 1, 1, vecVal[0], vecVal[1], vecVal[2]); break; case DTF_HM1: return YKDateTime(1970, 1, 1, vecVal[0], vecVal[1]); break; default: break; } return 0; } YK_BOOL YKDateTime::IsElapsed( YK_TM val ) const { YKDateTime dtNow = YKDateTime::GetLocalTime(); return (dtNow.m_time-m_time) >= val; } void YKDateTime::AddMonth( YK_INT month ) { tm t1; localtime_s(&t1, &m_time); YK_INT absMonth = month; if (month < 0) absMonth = abs(month); YK_INT year = absMonth / PER_YEAR; YK_INT mon = absMonth % PER_YEAR; if (month > 0) { *this = YKDateTime(t1.tm_year+1900+year, t1.tm_mon+mon, t1.tm_mday, t1.tm_hour, t1.tm_min, t1.tm_sec); } else { *this = YKDateTime(t1.tm_year+1900-year, t1.tm_mon-mon, t1.tm_mday, t1.tm_hour, t1.tm_min, t1.tm_sec); } }