Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A Simple Class To Handle Dates

0.00/5 (No votes)
12 Dec 1999 1  
A class that simplifies common date handling tasks

Introduction

All algorithms used to develop this class may be found here, and the class is here.

To use the class in your project, you will need the following files:

  1. SimpleDate.cpp: contains the date class functions
  2. SimpleDate.h: Header for the above class
  3. Parseit.cpp: Helper class that parses date strings
  4. Parseit.h: Header for the above class

In writing business applications, one is forced to deal with dates in many forms. A simple lightweight class to manipulate dates is not part of MFC or the WIN API. There are classes available to do this but at a level of cost and complexity that is really not needed in most cases. My general needs were:

  1. Ease of use
  2. Ability to easily store dates in structures, databases, flat files, etc.
  3. Ability to do simple math using dates such as adding or subtracting an arbitrary number of months,days, years to a given date
  4. Ability to handle 2 and 4 digit years (within reason)
  5. Handle different date formats
  6. Ability to perform logical comparisons on dates without much trouble
  7. Ability to handle user input and apply formatting and validity checks using the standard MFC architecture
  8. Did I mention Ease of use?

What I finally developed is a class I call CSimpleDate. I think that it meets or exceeds all the above. All of the math functions return a self-reference so that they may be used as rvalues in assignments. Internally, the dates are stored as Julian Dates. There is an operator long that will return this value allowing the CSimpleDate to be a rvalue in comparisons or assignments also. Dates can be stored in files, databases, or structs as either a text string (human readable) or as a long. Dates stored as a long are very easy to use as indexes or to make rapid date comparisons on but are not readable by the average human. Take your pick.

As I am using integer math for calculations, I think the accuracy may be a little off when projecting dates far in the past or future. I will leave this to the algorithm buffs out there to determine.

Example of Usage

void CYourClass::Something()
{
	CSimpleDate Date1;  // will have today's date in it default constructor
	CSimpleDate Date2("12/07/1941"); //Set to that date 
	CString s=(LPCSTR)Date2;// s will be "12/07/1941"

	s = Date2.GetFullDateString();// s= "Sun Dec 07 1941" 
 	s = Date2.GetFullDateStringLong();// s=  "Sunday December 071941" 
 	if(Date2 != "12/09/1940") 
	  DoThis()
	else
	  DoThat();
	if(Date2 < Date1)
		s="It Better be";
	else
		s="We Got Troubles";

	Date2="02/29/2000";//copy type 1
	Date2.AddYear(1)//Date2 now equals "02/28/2001"
	Date2=Date;//copy type 2
	Date=Date2.AddDays(1234) // Date and Date2 are both equal now see source code

	long D1=(long)Date;// these functions are equivalent
	long D2=Date2.GeyJulianDate();
}

There are also DDX functions available that understand the class. They perform formatting as well as date verification.

void CMainView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMainView)
	DDX_SimpleDate(pDX, IDC_THEDATE, m_TheDateString);	// string or cstring
	DDX_SimpleDate(pDX, IDC_THEDATE2, m_TheDataLong);	// long
	DDX_Text(pDX, IDC_RESULTS, m_R1);
	//}}AFX_DATA_MAP
}

There is the basis for time functions built into the class. I have implemented only very basic time functionality as I have very little need for it. See the source code for details.

There is a small demo program showing how the class is used and also a file containing the class and the reference text only.


Documentation for CSimpleDate C++ Class

Table of Contents


Constructors and Destructors

  • CSimpleDate(int FormatType=MMDDYYYY);
  • CSimpleDate(LPCSTR DateString,int FormatType=MMDDYYYY);
  • CSimpleDate(long JD,int FormatType=MMDDYYYY);
  • virtual ~CSimpleDate();

Date Math Routines

  • const CSimpleDate& AddDays(int Days);
  • const CSimpleDate& AddYears(int Yrs);
  • const CSimpleDate& AddMonths(int Mon);
  • const CSimpleDate& SubtractYears(int Yrs);
  • const CSimpleDate& SubtractDays(int Days);
  • const CSimpleDate& SubtractMonths(int Mon);
  • virtual int YearsOld();

Data Access Routines

  • LPCSTR GetFullDateString();
  • LPCSTR GetFullDateStringLong();
  • virtual int GetDayOfWeek();
  • virtual BOOL IsValid();
  • long GetJulianDate();
  • virtual int GetDay()
  • virtual int GetMonth()
  • virtual int GetYear()
  • virtual void GetIntegerDate(int& m, int& d,int& y)
  • virtual int GetHour()
  • virtual int GetMin()
  • virtual int GetSeconds()
  • virtual void GetTimeString(CString& s,BOOL AmPm=TRUE);
  • virtual void GetTimeString(LPSTR s,int nLen,BOOL AmPm=TRUE);
  • virtual void GetTimeStringShort(CString& s,BOOL AmPm=TRUE);
  • virtual void GetTimeStringShort(LPSTR s,int nLen,BOOL AmPm=TRUE);

Operator Assignments Conversions Equality, etc.

  • operator LPCSTR();
  • operator long();
  • const CSimpleDate& operator = (const CSimpleDate& Date);
  • const CSimpleDate& operator = (LPCSTR Date);
  • BOOL operator > (const CSimpleDate& Date);
  • BOOL operator < (const CSimpleDate& Date);
  • BOOL operator >= (const CSimpleDate& Date);
  • BOOL operator <= (const CSimpleDate& Date);
  • BOOL operator == (const CSimpleDate& Date);
  • BOOL operator != (const CSimpleDate& Date);
  • BOOL operator > (LPCSTR Date);
  • BOOL operator < (LPCSTR Date);
  • BOOL operator >= (LPCSTR Date);
  • BOOL operator <= (LPCSTR Date);
  • BOOL operator == (LPCSTR Date);
  • BOOL operator != (LPCSTR Date);

Protected Internal Class Members

  • virtual BOOL SetToday();
  • virtual BOOL CSimpleDate::ParseDateString(LPCSTR,int& m,int& d,int& y);
  • virtual BOOL ParseDateString(LPCSTR);
  • virtual long ConvertToJulian( int month,int day,int year);
  • virtual long ConvertToJulian();
  • virtual void ConvertFromJulian(int& Month,int& Day,int& Year);
  • virtual void ConvertFromJulian();
  • virtual void AdjustDays();
  • virtual void SetTime();

Static Member Functions

  • static BOOL VerifyDateFormat(LPCSTR date);
  • static BOOL FixDateFormat(CString & date);
  • static BOOL FixDateFormat(LPSTR date);

NON Member Data Exchange Functions

  • void DDX_SimpleDate(CDataExchange *pDX,int nID,LPSTR str,int nLen);
  • void DDX_SimpleDate(CDataExchange *pDX,int nID,CString& str);
  • void DDX_SimpleDate(CDataExchange *pDX,int nID,long& jdate);

Constructors

There are three constructors available. The first one:

CSimpleDate(int FormatType=MMDDYYYY);

will initilize the object to today's date. This is the default constructor.

Example of use: CSimpleDate D; or CSimpleDate D(MMDDYY);

The second one:

CSimpleDate(LPCSTR DateString,int FormatType=MMDDYYYY);

takes a character string or a CString containing a date properly formatted as the first parameter. The optional format type is the second parameter.

Example of use: CSimpleDate("12/07/1999"); or CSimpleDate("12/07/99",MMDDYY);

One caveat; The internal representation of the dates are maintained as a 4 digit year, no matter what format is in effect. The format only affects output.

The third one:

CSimpleDate(long JD,int FormatType=MMDDYYYY);

takes a long integer representing a Julian Date Number as a parameter and the optional format type.


Date Math

const	CSimpleDate& AddDays(int Days);
const	CSimpleDate& AddYears(int Yrs);
const	CSimpleDate& AddMonths(int Mon);
const	CSimpleDate& SubtractYears(int Yrs);
const	CSimpleDate& SubtractDays(int Days);
const	CSimpleDate& SubtractMonths(int Mon);
virtual int YearsOld();

These routines are self explanatory. They will take a existing CSimpleDate object and perform the requested operation on it. With the exception of YearsOld(), they all return a reference to self allowing them to be used on the right side of a expression. For example, look at the following few lines of code.

CSimpleDate Date("12/12/1990"); // Date=dec 12 1990
CSimpeDate  Date2;              // Date2 = todays date
Date2 = Date.AddMonths(1);      // date2 now equals Jan 12 1991 and so does Date1.

The copy constructor is invoked and assignment can be made in this manner.

The YearsOld() returns the number of whole years between a CSimpleDate value and today's date. Today's date is the current system date. There is no negative return 0 will be returned as the smallest value. If the CSimpleDate object is Invalid or if it contains a date greater than today's date, 0 will be returned.


Class Access Functions

LPCSTR GetFullDateString();

returns a string containing the date in the format of "Sun Dec 7 1941"

LPCSTR GetFullDateStringLong();

returns a string containing the date in the format of "Sunday December 7 1941"

int GetDayOfWeek();

returns integer representing the day of the week where Sunday=1 Moday=2, etc.

BOOL IsValid();

returns TRUE if the CSimpleDate object contains a vaild date else FALSE;

long GetJulianDate(); 

returns a long int representing the Julian date number for this CSimpeDate objects Gregorian date

int GetDay()
int GetMonth()
int GetYear()
void GetIntegerDate(int& m, int& d,int& y)

These all return integers representing the internal values held for the requested objects

int GetHour()
int GetMin()
int GetSeconds()

These all return integers representing the internal values held for the requested objects. The GetHour function returns are based on a 24 hour clock and are not adjusted for AM PM.

void GetTimeString(CString& s,BOOL AmPm=TRUE);
void GetTimeString(LPSTR s,int nLen,BOOL AmPm=TRUE);

returns a string representing the current system time. The hour portion is adjusted for a 12 hour clock. If AmPm is true ( default value), AM or PM will be appended to the string. The returned string will be in the format of "9:45:55 PM".

void GetTimeStringShort(CString& s,BOOL AmPm=TRUE);
void GetTimeStringShort(LPSTR s,int nLen,BOOL AmPm=TRUE);

returns a string representing the current system time. The hour portion is adjusted for a 12 hour clock. If AmPm is true (default value) AM or PM will be appended to the string. The returned string will be in the format of "9:45 PM".


Operators and Comparison Functions

operator LPCSTR();

returns a string representation of the CSimpledate object. This also allows for a CSimpleDate to be constructed with a CSimpleDate as a parameter.

CSimpleDate Date("12/09/1946");
CString s=(LPCSTR)Date;
CSimpleDate S2(Date); // no such constructor but will work because it converts the Date to a LPCSTR 
VERIFY(s=="12/09/1946");
operator long();

returns a long representing the Julian Date number for this CSimpleDate object:

CSimpleDate Date("12/09/1946");

long s=(long)Date;

VERIFY(s==Date.GetJulianDate());
const CSimpleDate& operator = (const CSimpleDate& Date);
const CSimpleDate& operator = (LPCSTR Date);

Copy constructors basic stuff nothing fancy:

BOOL operator >  (const CSimpleDate& Date);
BOOL operator <  (const CSimpleDate& Date);
BOOL operator > = (const CSimpleDate& Date);
BOOL operator < = (const CSimpleDate& Date);
BOOL operator == (const CSimpleDate& Date);
BOOL operator != (const CSimpleDate& Date);
BOOL operator >  (LPCSTR Date);
BOOL operator <  (LPCSTR Date);
BOOL operator > = (LPCSTR Date);
BOOL operator < = (LPCSTR Date);
BOOL operator == (LPCSTR Date);
BOOL operator != (LPCSTR Date);

These are all overloaded equality operators and are used in the normal manner. They can be applied between CSimpleDate objects and/or string representations of dates (rvalues only). For example:

CSimpleDate Date("12/09/1998");
CSimpeDate Date2;
if ( Date2 >  Date1) 
{
   DoThis();
}
else if(Date <  "12/12/1998")
   DoThis();
else
   ForGetIt();

Internal Protected Functions

BOOL SetToday();
BOOL CSimpleDate::ParseDateString(LPCSTR,int& m,int& d,int& y);
BOOL ParseDateString(LPCSTR);
long ConvertToJulian( int month,int day,int year);
long ConvertToJulian();
void ConvertFromJulian(int& Month,int& Day,int& Year);
void ConvertFromJulian();
void AdjustDays();
void SetTime();

These are all used in setting and maintaining the class data. All functions are virtual so they can be overridden in inherited classes. The names are pretty explanatory. Please examine the source code as to the functionality for each member.


Static Functions

BOOL VerifyDateFormat(LPCSTR date);

Passed a string representation of a date I.E "12/01/90" or "12-08-1998" will determine if the date is correct and formatted in a manner that the Class can recognize. Invalid dates I.E "02/30/1998" will also be caught. Returns true if OK, else false.

BOOL FixDateFormat(CString & date);
BOOL FixDateFormat(LPSTR date);

This pair of functions will attempt to format an unformatted string. An unformatted string is one that contains no date separators such as "121290" or "12121997". If successful, the string will be formatted and checked for validity. The LPSTR version ASSUMES that the string is long enough to hold the formatted date.


Non Member Functions

DDX_SimpleDate(CDataExchange *pDX,int nID,LPSTR str,int nLen);
DDX_SimpleDate(CDataExchange *pDX,int nID,CString& str);
DDX_SimpleDate(CDataExchange *pDX,int nID,long& jdate);

These are data exchange functions that can be used to input and display CSimpleDate type dates. The only data that needs to be saved to and from a database or datafile is either a string representation of the date or the Julian Date number. By saving a Julian Date number, simple comparisons can be rapidly made between date fields, I.E. greater than less than equal to. These functions also provide error checking to assure that a valid date is entered. They are used exactly like the DDX_xxx functions provided by MFC. For example:

void CMainView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMainView)
	DDX_SimpleDate(pDX, IDC_THEDATE, m_TheDate);	// string or cstring 
	DDX_SimpleDate(pDX, IDC_THEDATE2, m_Date2);	// long 
	DDX_Text(pDX, IDC_RESULTS, m_R1);
	//}}AFX_DATA_MAP
}

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here