datehelper.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 369 行

CPP
369
字号
// DateHelper.cpp: implementation of the CDateHelper class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DateHelper.h"

#include <math.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

int CDateHelper::CalcDaysFromTo(const COleDateTime& dateFrom, const COleDateTime& dateTo, BOOL bInclusive)
{
	int nDiff = (int)(floor(dateTo) - floor(dateFrom));

	return nDiff + (bInclusive ? 1 : 0);
}

int CDateHelper::CalcDaysFromTo(const COleDateTime& dateFrom, DH_DATE nTo, BOOL bInclusive)
{
	return CalcDaysFromTo(dateFrom, GetDate(nTo), bInclusive);
}

int CDateHelper::CalcDaysFromTo(DH_DATE nFrom, DH_DATE nTo, BOOL bInclusive)
{
	ASSERT (nFrom <= nTo);

	if (nFrom > nTo)
		return 0;
	
	else if (nFrom == nTo)
		return bInclusive ? 1 : 0;

	// else
	return CalcDaysFromTo(GetDate(nFrom), GetDate(nTo), bInclusive);
}

double CDateHelper::GetDate(DH_DATE nDate)
{
	COleDateTime date;

	switch (nDate)
	{
	case DHD_TODAY:
		date = COleDateTime::GetCurrentTime();
		break;

	case DHD_TOMORROW:
		date = GetDate(DHD_TODAY) + 1;
		break;

	case DHD_ENDTHISWEEK:
		{
			// we must get the locale info to find out when this 
			// user's week starts
			date = COleDateTime::GetCurrentTime();
			
			// increment the date until we hit the last day of the week
			// note: we could have kept checking date.GetDayOfWeek but
			// it's a lot of calculation that's just not necessary
			int nLastDOW = LastDayOfWeek();
			int nDOW = date.GetDayOfWeek();
			
			while (nDOW != nLastDOW) 
			{
				date += 1;
				nDOW = NextDayOfWeek(nDOW);
			}
		}
		break;

	case DHD_ENDNEXTWEEK:
		return GetDate(DHD_ENDTHISWEEK) + 7;

	case DHD_ENDTHISMONTH:
		{
			date = COleDateTime::GetCurrentTime();
			int nThisMonth = date.GetMonth();

			while (date.GetMonth() == nThisMonth)
				date += 20; // much quicker than doing it one day at a time

			date -= date.GetDay(); // because we went into next month
		}
		break;

	case DHD_ENDNEXTMONTH:
		{
			date = GetDate(DHD_ENDTHISMONTH) + 1; // first day of next month
			int nNextMonth = date.GetMonth();

			while (date.GetMonth() == nNextMonth)
				date += 20; // much quicker than doing it one day at a time

			date -= date.GetDay(); // because we went into next month + 1
		}
		break;

	case DHD_ENDTHISYEAR:
		date = COleDateTime::GetCurrentTime(); // for current year
		date = COleDateTime(date.GetYear(), 12, 31, 0, 0, 0);
		break;

	case DHD_ENDNEXTYEAR:
		date = COleDateTime::GetCurrentTime(); // for current year
		date = COleDateTime(date.GetYear() + 1, 12, 31, 0, 0, 0);
		break;

	default:
		ASSERT (0);
		date.m_dt = 0;
		break;
	}

	return floor(date);
}

int CDateHelper::CalcWeekdaysFromTo(const COleDateTime& dateFrom, const COleDateTime& dateTo, BOOL bInclusive)
{
	int nWeekdays = 0;
	
	COleDateTime dFrom(floor(dateFrom.m_dt));
	COleDateTime dTo(floor(dateTo.m_dt));

	if (bInclusive)
		dTo += 1;

	int nDiff = (int)(double)(dTo - dFrom);

	if (nDiff > 0)
	{
		while (dFrom < dTo)
		{
			int nDOW = dFrom.GetDayOfWeek();

			if (nDOW != 1 && nDOW != 7)
				nWeekdays++;

			dFrom += 1;
		}
	}

	return nWeekdays;
}

int CDateHelper::FirstDayOfWeek()
{
	char szFDW[3]; // 2 + NULL

	::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, szFDW, 2);

	int nFirstDOW = atoi(szFDW);

	// we need days to have same order as COleDateTime::GetDayOfWeek()
	// which is 1 (sun) - 7 (sat)
	switch (nFirstDOW)
	{
	case 0: /* mon */ return 2;
	case 1: /* tue */ return 3;
	case 2: /* wed */ return 4;
	case 3: /* thu */ return 5;
	case 4: /* fri */ return 6;
	case 5: /* sat */ return 7;
	case 6: /* sun */ return 1;
	}

	ASSERT (0);
	return 1;
}

int CDateHelper::LastDayOfWeek()
{
	switch (FirstDayOfWeek())
	{
	case 2: /* mon */ return 1; // sun
	case 3: /* tue */ return 2; // mon
	case 4: /* wed */ return 3; // tue
	case 5: /* thu */ return 4; // wed
	case 6: /* fri */ return 5; // thu
	case 7: /* sat */ return 6; // fri
	case 1: /* sun */ return 7; // sat
	}

	ASSERT (0);
	return 1;
}

int CDateHelper::NextDayOfWeek(int nDOW)
{
	switch (nDOW)
	{
	case 2: /* mon */ return 3; // tue
	case 3: /* tue */ return 4; // wed
	case 4: /* wed */ return 5; // thu
	case 5: /* thu */ return 6; // fri
	case 6: /* fri */ return 7; // sat
	case 7: /* sat */ return 1; // sun
	case 1: /* sun */ return 2; // mon
	}

	ASSERT (0);
	return 1;
}

CString CDateHelper::FormatDate(const COleDateTime& date, BOOL bISOFormat, BOOL bWantDOW)
{
	CString sDate;

	if (bISOFormat)
	{
		if (bWantDOW)
			sDate.Format("%s %s", GetWeekday(date.GetDayOfWeek(), TRUE), date.Format("%Y-%m-%d"));
		else
			sDate = date.Format("%Y-%m-%d");
	}
	else
	{
		if (bWantDOW)
			sDate.Format("%s %s", GetWeekday(date.GetDayOfWeek(), TRUE), date.Format(VAR_DATEVALUEONLY));
		else
			sDate = date.Format(VAR_DATEVALUEONLY);
	}

	return sDate;
}

CString CDateHelper::FormatCurrentDate(BOOL bISOFormat, BOOL bWantDOW)
{
	return FormatDate(COleDateTime::GetCurrentTime(), bISOFormat, bWantDOW);
}

CString CDateHelper::GetWeekday(int nWeekday, BOOL bShort)
{
	LCTYPE lct = bShort ? LOCALE_SABBREVDAYNAME1 : LOCALE_SDAYNAME1;
	CString sWeekday;

	// data check
	if (nWeekday < 1 || nWeekday> 7)
		return "";

	switch (nWeekday)
	{
	case 1: lct = bShort ? LOCALE_SABBREVDAYNAME7 : LOCALE_SDAYNAME7; break; // sun
	case 2:	lct = bShort ? LOCALE_SABBREVDAYNAME1 : LOCALE_SDAYNAME1; break; // mon
	case 3:	lct = bShort ? LOCALE_SABBREVDAYNAME2 : LOCALE_SDAYNAME2; break; // tue
	case 4:	lct = bShort ? LOCALE_SABBREVDAYNAME3 : LOCALE_SDAYNAME3; break; // wed
	case 5:	lct = bShort ? LOCALE_SABBREVDAYNAME4 : LOCALE_SDAYNAME4; break; // thu
	case 6:	lct = bShort ? LOCALE_SABBREVDAYNAME5 : LOCALE_SDAYNAME5; break; // fri
	case 7:	lct = bShort ? LOCALE_SABBREVDAYNAME6 : LOCALE_SDAYNAME6; break; // sat
	}
	
	GetLocaleInfo(LOCALE_USER_DEFAULT, lct, sWeekday.GetBuffer(30),	29);
	sWeekday.ReleaseBuffer();

	return sWeekday;
}

void CDateHelper::OffsetDate(COleDateTime& date, int nAmount, DH_UNITS nUnits)
{
	if (date.m_dt > 0)
	{
		switch (nUnits)
		{
		case DHU_DAYS:
			date += (double)nAmount;
			break;

		case DHU_WEEKS:
			date += nAmount * 7.0;
			break;

		case DHU_MONTHS:
			{
				SYSTEMTIME st;
				date.GetAsSystemTime(st);

				// convert amount to years and months
				st.wYear = (WORD)((int)st.wYear + (nAmount / 12));
				st.wMonth = (WORD)((int)st.wMonth + (nAmount % 12));

				// handle overflow
				if (st.wMonth > 12)
				{
					st.wYear++;
					st.wMonth -= 12;
				}
				else if (st.wMonth < 1)
				{
					st.wYear--;
					st.wMonth += 12;
				}

				// update time
				date = COleDateTime(st);
			}
			break;

		case DHU_YEARS:
			{
				SYSTEMTIME st;
				date.GetAsSystemTime(st);

				// update year
				st.wYear = (WORD)((int)st.wYear + nAmount);

				// update time
				date = COleDateTime(st);
			}
			break;
		}
	}
}

void CDateHelper::GetWeekdays(BOOL bShort, CStringArray& aWeekDays)
{
	aWeekDays.RemoveAll();

	for (int nDay = 1; nDay <= 7; nDay++)
		aWeekDays.Add(GetWeekday(nDay, bShort));
}

CString CDateHelper::GetMonth(int nMonth, BOOL bShort)
{
	LCTYPE lct = LOCALE_SABBREVMONTHNAME1;
	CString sMonth;

	// data check
	if (nMonth < 1 || nMonth> 12)
		return "";

	switch (nMonth)
	{
	case 1:  lct = bShort ? LOCALE_SABBREVMONTHNAME1  : LOCALE_SMONTHNAME1;  break; // jan
	case 2:  lct = bShort ? LOCALE_SABBREVMONTHNAME2  : LOCALE_SMONTHNAME2;  break; // feb
	case 3:  lct = bShort ? LOCALE_SABBREVMONTHNAME3  : LOCALE_SMONTHNAME3;  break; // mar
	case 4:  lct = bShort ? LOCALE_SABBREVMONTHNAME4  : LOCALE_SMONTHNAME4;  break; // apr
	case 5:  lct = bShort ? LOCALE_SABBREVMONTHNAME5  : LOCALE_SMONTHNAME5;  break; // may
	case 6:  lct = bShort ? LOCALE_SABBREVMONTHNAME6  : LOCALE_SMONTHNAME6;  break; // jun
	case 7:  lct = bShort ? LOCALE_SABBREVMONTHNAME7  : LOCALE_SMONTHNAME7;  break; // jul
	case 8:  lct = bShort ? LOCALE_SABBREVMONTHNAME8  : LOCALE_SMONTHNAME8;  break; // aug
	case 9:  lct = bShort ? LOCALE_SABBREVMONTHNAME9  : LOCALE_SMONTHNAME9;  break; // sep
	case 10: lct = bShort ? LOCALE_SABBREVMONTHNAME10 : LOCALE_SMONTHNAME10; break; // oct
	case 11: lct = bShort ? LOCALE_SABBREVMONTHNAME11 : LOCALE_SMONTHNAME11; break; // nov
	case 12: lct = bShort ? LOCALE_SABBREVMONTHNAME12 : LOCALE_SMONTHNAME12; break; // dec
	}

	GetLocaleInfo(LOCALE_USER_DEFAULT, lct, sMonth.GetBuffer(30),	29);
	sMonth.ReleaseBuffer();

	return sMonth;
}

void CDateHelper::GetMonths(BOOL bShort, CStringArray& aMonths)
{
	aMonths.RemoveAll();

	for (int nMonth = 1; nMonth <= 12; nMonth++)
		aMonths.Add(GetMonth(nMonth, bShort));
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?