⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 date.cpp

📁 API经典入门
💻 CPP
字号:
#include "stdafx.h"
#include "Date.h"

IMPLEMENT_SERIAL(CDate, CObject, 0)

/////////////////////////////////////////////////
// Constructors

CDate::CDate()
{
	m_nYear = 0;
	m_nMonth = 0;
	m_nDay = 0;
	// null date -- not valid as a date, but handy
}            

CDate::CDate(CDate& Date)
{
	m_nYear = Date.m_nYear;
	m_nMonth = Date.m_nMonth;
	m_nDay = Date.m_nDay;
}

CDate::CDate(CTime& Time)
{
	m_nYear = Time.GetYear();
	m_nMonth = Time.GetMonth();
	m_nDay = Time.GetDay();
}

CDate::CDate(SWORD y, UWORD m, UWORD d):
	m_nYear(y),
	m_nMonth(m),
	m_nDay(d)
{}

/////////////////////////////////////////////////
// Assignment operator

CDate& CDate::operator=(CDate& Date)
{
	m_nYear = Date.m_nYear;
	m_nMonth = Date.m_nMonth;
	m_nDay = Date.m_nDay;
	
	return *this;
}

/////////////////////////////////////////////////
// Increment & Decrement functions

void CDate::AddMonth()
{
	if (m_nMonth > 11)
	{
		m_nMonth = 1;
		m_nYear++;
	}
	else
		m_nMonth++;
}

void CDate::SubtractMonth()
{
	if (m_nMonth < 2)
	{
		m_nMonth = 12;
		m_nYear--;
	}
	else
		m_nMonth--;
}
 
void CDate::AddDay()
{
	if (m_nDay < DaysInMonth())
		m_nDay ++;
	else
	{
		m_nDay = 1;
		AddMonth();
	}
}

void CDate::SubtractDay()
{
	if (m_nDay > 1)
		m_nDay--;
	else
	{
		SubtractMonth();
		m_nDay = DaysInMonth();
	}
}

// prefix notation
CDate& CDate::operator++()
{
	AddDay();
	return *this;
}

// postfix notation
CDate& CDate::operator++(int)
{
	CDate Old = *this;
	AddDay();
	return Old;
}

// prefix notation
CDate& CDate::operator--()
{
	SubtractDay();
	return *this;
}

// postfix notation
CDate& CDate::operator--(int)
{
	CDate Old = *this;
	SubtractDay();
	return *this;
}

/////////////////////////////////////////////////
// Sum & Difference functions

CDate& CDate::operator+ (unsigned int Days)
{
	UWORD DaysLeft = Days;
	UWORD Days2First;
    
    ASSERT (Days >= 0);
    
    // If possible, bring the date to the next
    // first of the month.
    Days2First = DaysInMonth() - m_nDay + 1;
    if ( DaysLeft > Days2First )
    {
    	DaysLeft -= Days2First;
    	m_nDay = 1;
		AddMonth();
    }
    
    // Remove the days a month at a time, if
    // possible.
	while ( DaysInMonth() <= DaysLeft )
	{
		DaysLeft -= DaysInMonth();
		AddMonth();
	}
	
	
	m_nDay += DaysLeft;
	
	return *this;
}

CDate& CDate::operator- (unsigned int Days)
{
	UWORD DaysLeft = Days;

	ASSERT (Days >= 0);
    
    // If possible, bring the date to the 
    // last day of the previous month.
    if ( DaysLeft >= m_nDay )
    {
    	DaysLeft = DaysLeft - m_nDay;
    	m_nDay = 1;
    	SubtractDay();
    }
    
    // Remove the days a month at a time, if
    // possible.
	while ( DaysInMonth() <= DaysLeft )
	{
		DaysLeft -= DaysInMonth();
		m_nDay = 1;
		SubtractMonth();
	}
	
	
	m_nDay -= DaysLeft;
	
	return *this;
}

int CDate::operator- (CDate& Date)
{
	int Result = 0;
	BOOL NegativeResult = TRUE;
	CDate smallDate;
	UWORD nTargetDay, nTargetMonth;
	SWORD nTargetYear;
	int LeapYearOffset;

	// if the dates are in the same month/year
	// the result is simply the difference between
	// the m_nDay members
	if ( (m_nYear == Date.m_nYear) &&
	     (m_nMonth == Date.m_nMonth) )
	{
		return m_nDay - Date.m_nDay;
	}
	
	// if, on the other hand, the dates are further
	// apart we have to do some work ...
	
	if (*this > Date)
	{
		smallDate = Date;
		nTargetDay = m_nDay;
		nTargetMonth = m_nMonth;
		nTargetYear = m_nYear;
		NegativeResult = FALSE;
	}
	else
	{
		smallDate = *this;
		nTargetDay = Date.m_nDay;
		nTargetMonth = Date.m_nMonth;
		nTargetYear = Date.m_nYear;
	}
	
	// Move to the first of the next month so as
	// to avoid any month length fluxuations
	while ( smallDate.m_nDay != 1 )
	{
		smallDate.AddDay();
		Result++;
	}
	
	// Add up the days a month at a time until
	// we reach the target month.
	while ( smallDate.m_nMonth != nTargetMonth )
	{
		Result += smallDate.DaysInMonth();
		smallDate.AddMonth();
	}

	// Keep track of the leap year calculations
	if (nTargetMonth < 3)
		LeapYearOffset = 0;
	else
		LeapYearOffset = 1;
	
	// Add up the days a year at a time until
	// we reach the target year.
	while ( smallDate.m_nYear != nTargetYear )
	{
		// if leap year affects calculation add 366 days
		if (CDate::IsLeapYear(smallDate.m_nYear + LeapYearOffset) )
		{
			Result += 366;
		}
		// otherwise add 365
		else
		{
			Result += 365;
		}
		smallDate.m_nYear++;
	}

	// At this point we are at the first of the target
	// month and year -- so we may simply add the target
	// day minus one.
	Result += nTargetDay - 1;
	
	// Result is computed absolutely but must be
	// returned with a sign!
	if (NegativeResult)
		return -Result;
	else
		return Result;
		
}

void CDate::Subtract (CDate& Date, UWORD& Years, UWORD& Months, UWORD& Days)
{
	UWORD nDayTarget;
	CDate largeDate;
	int nMonthCount = 0, nYearCount = 0, nDayCount = 0;
	
	// if the dates are equal, zero the differences
	if (*this == Date)
	{
		Years = 0;
		Months = 0;
		Days = 0;
		return;
	}

	// order the two dates
    if (*this > Date)
    {
    	largeDate = *this;
		nDayTarget = Date.m_nDay;
		nYearCount = m_nYear - Date.m_nYear;
		nMonthCount = m_nMonth - Date.m_nMonth;
	}
	else
    {
		largeDate = Date;
		nDayTarget = m_nDay;
		nYearCount = Date.m_nYear - m_nYear;
		nMonthCount = Date.m_nMonth - m_nMonth;
	}
	
	// change largeDate's Day to the target day, 
	// keeping track of the counts.
	if (largeDate.m_nDay >= nDayTarget)
	{
		while ( largeDate.m_nDay > nDayTarget )
		{
			largeDate.SubtractDay();
			nDayCount++;
		}
	}
	else
	{
		while ( largeDate.m_nDay < nDayTarget )
		{
			largeDate.AddDay();
			nDayCount--;
		}

		largeDate.m_nMonth--;
		nDayCount += largeDate.DaysInMonth();
		nMonthCount--;
	}
	

	// adjust the counts to be in proper form
	if ( nMonthCount < 0 )
	{
		nMonthCount += 12;
		nYearCount--;
	}

	Days = nDayCount;	
	Years = nYearCount;
	Months = nMonthCount;
	
}

void CDate::Add (SWORD Years, SWORD Months, SWORD Days)
{
	// first add the years -- no problems here
	m_nYear += Years;

	if (Months < 0)
	{
		// if Months is negative perform subtraction
		// decrementing the year as necessary
		Months = abs(Months);
		while (m_nMonth <= (UWORD)Months)
		{
			Months -= 12;
			m_nYear--;
		}
		m_nMonth -= Months;
	}
	else if (Months > 0)
	{
		// if Months is positive perform addition
		// incrementing the year as necessary
		m_nMonth += Months;
		while (m_nMonth > 12)
		{
			m_nMonth -= 12;
			m_nYear++;
		}
	}

	// make sure the day is valid
	if (m_nDay > DaysInMonth())
		m_nDay = DaysInMonth();
	
	if (Days == 0)
		return;
		
	if (Days < 0)
		for (int i = 1; i <= abs(Days); i++)
			SubtractDay();
	else
		for (int i = 1; i <= Days; i++)
			AddDay();
}

/////////////////////////////////////////////////
// Comparison operators
	
BOOL CDate::operator== (CDate& Date)
{
	return (m_nYear == Date.m_nYear) && 
			(m_nMonth == Date.m_nMonth) &&
			(m_nDay == Date.m_nDay);
}

BOOL CDate::operator!= (CDate& Date)
{
	return ( !(operator==(Date)) );
}

BOOL CDate::operator> (CDate& Date)
{
	if (m_nYear == Date.m_nYear)
		if (m_nMonth == Date.m_nMonth)
			return m_nDay > Date.m_nDay;
		else
			return m_nMonth > Date.m_nMonth;
	else
		return m_nYear > Date.m_nYear;
}

BOOL CDate::operator>= (CDate& Date)
{
	return ( !(operator<(Date)) );
}

BOOL CDate::operator< (CDate& Date)
{
	if (m_nYear == Date.m_nYear)
		if (m_nMonth == Date.m_nMonth)
			return m_nDay < Date.m_nDay;
		else
			return m_nMonth < Date.m_nMonth;
	else
		return m_nYear < Date.m_nYear;
}

BOOL CDate::operator<= (CDate& Date)
{
	return ( !(operator>(Date)) );
}

/////////////////////////////////////////////////
// Miscelaneous support functions

BOOL CDate::IsValid()
{
	// IsValid is aka Vali_Date
	if (m_nMonth < 1 || m_nMonth > 12)
		return FALSE;
	if (m_nDay > 0 && m_nDay <= DaysInMonth())
		return TRUE;
	else
		return FALSE;
		
	// note that a null date is not valid
}

void CDate::MakeValid()
{
	if (m_nMonth < 1)
		m_nMonth = 1;
	// Note that m_nMonth can't be less than 0
	// since UWORD is unsigned
		
	// cycle any excess months into years
	while (m_nMonth > 12)
	{
		m_nMonth -= 12;
		m_nYear++;
	}

	// clip the days to fit in the month
	if (m_nDay < 1)
		m_nDay = 1;
	else if (m_nDay > DaysInMonth())
		m_nDay = DaysInMonth();
}

int CDate::IsLeapYear(SWORD y)
{
	// Perform standard leap year calculations
	// leap years occur on years divisible by 4 ...
	if (y % 4 != 0)
		return FALSE;
	else
	{
		// ... unless it抯 a century year ...
		if (y % 100 != 0)
			return TRUE;
		// ... where it must be divisible by 400
		else if (y % 400 != 0)
			return FALSE;
		else
			return TRUE;
	}
}
	
UWORD CDate::DaysInMonth()
{
	switch (m_nMonth)
	{
		case 2:
		if (IsLeapYear(m_nYear))
			return 29;
		else
			return 28;
			
		case 4:
		case 6:
		case 9:
		case 11:
		return 30;
	
		default:
		return 31;
	}
}

/////////////////////////////////////////////////
// Format functions

CString CDate::DateString (const char* Format)
{
	const BuffLen = 128;
	CString S = "NULL DATE";
	
	if (*this == CDate())
		return S;
	
	char* pszS = S.GetBuffer(BuffLen);
	
	struct tm Date = {0,0,0,m_nDay,m_nMonth-1,m_nYear-1900,0,0,0};

	strftime(pszS, BuffLen-1, Format, &Date);
	
	S.ReleaseBuffer();

	return S;
}

BOOL CDate::StringToDate (const char* strDate)
{
	CString S = strDate, tempS;
	const char* Months[] = 
		{"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
		 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
	
	int Numbers[3];
	const char* NumSet = "0123456789";
	
	int Pos;
	int Month = 0;
	
	S.MakeUpper();
	
	for (int i = 0; i < 12; i++)
	{
		Pos = S.Find(Months[i]);
		if (Pos > 0)
			Month = i+1;
	}
	
	// Parse strDate looking for numbers that may
	// coorespond to date values.
	i = 0;
	while (!S.IsEmpty())
	{
		tempS = S.SpanIncluding(NumSet);
		if (tempS.IsEmpty())
		{
			S = S.Right(S.GetLength()-1);
		}
		else
		{
			Numbers[i] = atoi(tempS);
			i++;
			if (i>2)
				break;
			S = S.Right(S.GetLength()-tempS.GetLength());
		}
	}
    
    CDate testDate;
	if (Month)
		testDate = CDate(Numbers[1], Month, Numbers[0]);
	else
		testDate = CDate(Numbers[2], Numbers[0], Numbers[1]);

	// two-digit dates are automatically converted to
	// twentieth century dates.
	if (testDate.m_nYear < 100)
		testDate.m_nYear += 1900;

	if (testDate.IsValid())
	{
		*this = testDate;
		return TRUE;
	}
	else
		return FALSE;
}


/////////////////////////////////////////////////
// Debug function overrides

#ifdef _DEBUG

void CDate::Dump(CDumpContext& dc) const
{
	// first call the ancestor's Dump()
	CObject::Dump(dc);
	
	dc << "Year: " << m_nYear << " Month: " << m_nMonth
	   << " Day: " << m_nDay << "\n";
}

void CDate::AssertValid() const
{
	CDate* pD = (CDate*)this;
	
	// first call the ancestor's AssertValid()
	CObject::AssertValid();
	
	// if date is null, don't halt the program
	// a null date is valid in this sense
	if ( pD->operator==(CDate()) )
		return;
		
	ASSERT(pD->IsValid());
}

#endif

void CDate::Serialize( CArchive& ar)
{
	// serialize the base class first
	CObject::Serialize( ar );
	
	// convert m_nYear to a CArchive-friendly type
	long y = (long)m_nYear;
	
	if ( ar.IsStoring() )
		ar << y << m_nMonth << m_nDay;
	else
	{
		ar >> y >> m_nMonth >> m_nDay;
		m_nYear = (int)y;
	}
		
}

⌨️ 快捷键说明

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