软件架构设计之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);
	}
}


你可能感兴趣的:(C++,架构,设计,日期,泛型编程)