Click here to Skip to main content
Click here to Skip to main content

A Simple Class To Handle Dates

By , 12 Dec 1999
 
  • Download demo project - 33 Kb
  • Download source files - 9 Kb
  • 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 above class
    3. Parseit.cpp: Helper class that parses date strings
    4. Parseit.h: Header for 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 todays 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 equivilent
    	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


    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 todays 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 maintaied 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 todays date. Todays 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 todays 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 conatins 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 comparision 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");<br>
    CString s=(LPCSTR)Date;<br>
    CSimpleDate S2(Date); // no such constructor but will work because it converts the Date to a LPCSTR <br>
    VERIFY(s=="12/09/1946");<br><br>
    

    operator long();
    returns a long representing the Julian Date number for this CSimpleDate object

    CSimpleDate Date("12/09/1946");<br>
    long s=(long)Date;<br>
    VERIFY(s==Date.GetJulianDate());<br><br>
    

    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 a unformatted string. An unformatted string is one that contains no date seperators such as "121290" or "12121997". If succesful 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 comparisions 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

    About the Author

    Richard Stringer
    Web Developer
    United States United States
    Member
    No Biography provided

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    GeneralMy vote of 5memberIdeapolis16 May '13 - 3:32 
    easy to use, excellent!
    QuestionA patch for VS2010 compilationmemberxyloweb25 Nov '11 - 8:56 
    Hi,
     
    I propose a patch for the class CSimpleDate
    CSimpleDate.patch
    Jean-Michel MARINO
    JMM Code Park

    Generallist of errorsmemberMember 204626731 May '09 - 21:14 
    Hi,
     
    I have included Parseit.h, SimpleDate.h and parseit.cpp, SimpleDate.cpp in a console VC++ project. But I am betting 300 errors after building the solution and all the errors lies in those file.
    Should i change some properties for the project.
    Please let me know why all these errors are coming
     
    Sharmila
     
    sharmila

    Generala bit more complex than should be - but usefulmembernpetrov19 Jul '06 - 1:08 
    A bit overly complex especially on the operators,
    but overall quite useful for the general date addition
    substraction/verification code.
     
    NOTE: It seems from the code that none of the operators
    check for time - just for dates.
     

    Questiona BUG in Demo with VS.net 2005???memberGhostEx25 Feb '06 - 12:56 
    After I compiled and executed the Demo with VS.net 2005, a message "Run-Time Check Failure #2 - Stack around the variable 'time_val' was corrupted." jumped out. And the Demo stoped at SimpleDate.cpp Line 740 .
     
    Is this is a bug?
    AnswerRe: a BUG in Demo with VS.net 2005???membermsatur93 Apr '06 - 22:22 
    This code certainly won't compile under any UniCode implementations, not to mention the extraneous use of deprecated functions such as strcmp and strcpy which will more than likely fail the compile. I considered doing a rewrite of the entire code to be VS2k5 compliant, but as I only needed one or two functions from the lot I simply stole that code and modified it.
    GeneralRe: a BUG in Demo with VS.net 2005???membermattfaramir332 Jan '09 - 12:51 
    This is fixed by adding the following line to your stdafx.h file
     
    #define _USE_32BIT_TIME_T
     
    The reason for the stack error is that VS 2005 uses the 64 bit time_t declaration instead of the 32 bit
    which goes on to cause the stack corruption.
     
    Hope this helps.
     
    Matt
    GeneralCan't compile the simplest implementationsussJennifer James13 Jul '05 - 10:55 
    I created in VS 2003.NET a new Windows Application (and a Windows Console) project. I created a main.cpp with:
    int main()
    {
    return 0;
    }
     
    I also commented out the entire parseit.cpp except for:
    CParseIt::CParseIt(BOOL Strip)
    {
    strcpy(Seperator,",");
    StripQuotes=Strip;
    NumFields=0;
    TheData=NULL;
    }
     

    But, when I compile, I get 87 errors!:
     
    parseit.h: error C2833: 'operator LPCSTR' is not a recognized operator or type
    parseit.h: error C2059: syntax error : 'newline'
    parseit.h: error C2061: syntax error : identifier 'LPCSTR'
    And on and on...
     
    The demo class compiles fine without any problem.
     

    what the heck am I doing wrong here? Project settings wrong? Wrong *something*?

    GeneralRe: Can't compile the simplest implementationmemberNicholas Wourms22 Jul '05 - 11:43 
    This error implies that parseit.h is being included before windefs.h. First, make sure that stdafx.h includes windows.h. Then, check your cpp files to make sure that stdafx.h is included before parseit.h.
    GeneralSpelling Error - SeperatormemberKellyCoinGuy5 Apr '05 - 7:26 
    Just thought you would be interested that Seperator should be spelled Separator...
     
    -Kelly
    GeneralError in parseit.hmemberErnesto Perales Soto24 Oct '04 - 3:27 
    When the header file "simpledate.h" is included before another header file that declares a std::map, the compilation of the map fails with a

    syntax error : identifier '_Wherenode'

    I traced this back to ParseIt.h, and the following definition :

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif

     
    when this definition is removed, it compiles fine again.
     
    Adiós!
     

     
    eperales
    Generalhelp on using this class...memberbbwlam16 Aug '04 - 14:28 
    Smile | :) Smile | :) I tried to integrate your class into my code but it would complain when I try to compile it. Are there any special settings/libraries I need to add/define?
     
    Parseit.h(91) : error C2146: syntax error : missing ';' before identifier 'TheFields'
    Parseit.h(91) : error C2501: 'CPtrArray' : missing storage-class or type specifiers
    Parseit.h(91) : error C2501: 'TheFields' : missing storage-class or type specifiers
    SimpleDate.h(132) : error C2065: 'CDataExchange' : undeclared identifier
    SimpleDate.h(132) : error C2065: 'pDX' : undeclared identifier
    SimpleDate.h(132) : error C2062: type 'int' unexpected
    SimpleDate.h(133) : error C2062: type 'int' unexpected
    SimpleDate.h(134) : error C2062: type 'int' unexpected
     

    Commenting out
    void DDX_SimpleDate(CDataExchange *pDX,int nID,LPSTR str,int nLen);
    and the like would get rid of the errors from SimpleDate.. I guess it is okay to comment them out? but I just can't get ride of the Parseit.h errors. I can't recongise CPtrArray....
     
    Btw, I can compile and run the sample app.
     
    Thanks,
    Bernard Confused | :confused:
    GeneralThank you very muchmemberFranklin577521 Nov '03 - 1:10 
    I was looking for this code for a long time, The feature that is really useful is the Addition and Subtration of Days.
    QuestionSource Code License?memberjcsston30 Jul '03 - 11:04 
    What source code license is this code under?
    I'm changing the class to work with stl::vector and my own cross-platform Smile | :) string class. The license I am using in my code in the GNU GPL.
    AnswerRe: Source Code License?memberRichard Stringer30 Jul '03 - 11:36 
    This souce code is under "License to steal" Smile | :) By that I mean that you can do what you wnat to with it - give me credit or not - just have fun. The only thing I would ask is that if any bugs are found to report them so we can get it fixed.
     
    Richard Stringer
    ISS Software
    Dallas Texas

     
    In Italy for thirty years under the Borgias
    they had warfare, terror, murder and bloodshed
    but they produced Michelangelo, Leonardo
    da Vinci and the Renaissance. In Switzerland,
    they had brotherly love; they had five
    hundred years of democracy and peace
    and what did that produce?
    The cuckoo clock.
    Orson Welles

     

    GeneralRe: Source Code License?memberjcsston30 Jul '03 - 18:42 
    Smile | :) Once I have made sure it works correctly I will post a link to the modifed 'MFC-free' sources.
     
    I have a question, how can I get the Epoch date?
     
    Thanks for the great code Smile | :)
    GeneralRe: Source Code License?memberpwyzorski1 Apr '04 - 15:28 
    I'm really curious if this port to a MFC-free implementation ever got done. I could really use about now.
     
    regards,
    ~P
    GeneralRe: Source Code License?memberjcsston1 Apr '04 - 18:53 
    I found out I didn't need to use it after all. I had to deal with times more than dates.
     
    But here is a MFC-free version. It depends on my own string class, JString because std::string doesn't have any formating functions.
     
    You can get it here
    http://webjory.tripod.com/c/DateClass-2003-07-31-JString.zip
    You'll need to visit http://webjory.tripod.com/ or something similar first so the right referrer is sent (Tripod doesn't like direct links).

    QuestionRedundant call??memberkc5zrs21 Apr '03 - 4:50 
    In the following code snippet,
    BOOL CSimpleDate::ParseDateString(LPCSTR date,int& m,int& d,int& y)
    {
    CParseIt ParseIt(date,"/.-");
    ParseIt.Parse();
    int one,two,three;
    .
    .
    .
    }

    the second line's call to the ParseIt.Parse() function looks redundant to me, since the Parse() function is called by the CParseIt object's constructor in the first line.
     
    Is there something I'm missing? Just checking to see if I understand the code correctly...
     
    Thanks!
    rds
     

     


    GeneralY2K bugsmemberskyfree10 Mar '03 - 9:04 
    The current implementation does not handle dates after Y2K using formats with only 2 year digits ("YY"). I made the following corrections that will cause any year <= 50 to be assumed to be in the current century, and any > 50 to be in the last century. For example, "09/03/51" will be interpreted as "09/03/1951" and "09/03/50" will be "09/03/2050".
     
    BOOL CSimpleDate::ParseDateString(LPCSTR date,int& m,int& d,int& y)
    {
    CParseIt ParseIt(date,"/.-");
    ParseIt.Parse();
    int one,two,three;
    one=two=three=0;
    int N=ParseIt.GetNumFields();
    one=(int)ParseIt.GetField(1);
    if(N > 1)
    two=(int)ParseIt.GetField(2);
    if(N > 2)
    three=(int)ParseIt.GetField(3);
    switch(m_Format)
    {
    case MMDDYY:
    m=one;d=two;y=three;
    if(y < 100 && y > 50)
    y+=1900;
    if(y <= 50)
    y+=2000;
    break;
    case DDMMYY:
    d=one;m=two;y=three;
    if(y < 100 && y > 50)
    y+=1900;
    if(y <= 50)
    y+=2000;
    break;
    case YYMMDD:
    y=one;m=two;d=three;
    if(y < 100 && y > 50)
    y+=1900;
    if(y <= 50)
    y+=2000;
    break;
    case MMDDYYYY:
    m=one;d=two;y=three;
    if(y < 100 && y > 50)
    y+=1900;
    if(y <= 50)
    y+=2000;
    break;
    case DDMMYYYY:
    d=one;m=two;y=three;
    if(y < 100 && y > 50)
    y+=1900;
    if(y <= 50)
    y+=2000;
    break;
    case YYYYMMDD:
    y=one;m=two;d=three;
    if(y < 100 && y > 50)
    y+=1900;
    if(y <= 50)
    y+=2000;
    break;
    default:
    m=y=d=0;
    }
     
    return TRUE;
     
    }
     
    CSimpleDate::operator LPCSTR()
    {
    if(!IsValid())
    return (LPCSTR)0;
    int y = 0;
     
    switch(m_Format)
    {
    case MMDDYY:
    m_DateString.Format("%02d/%02d/%02d",m_Month,m_Day,m_Year > 99 ? (m_Year < 2000 ? m_Year-1900 : m_Year-2000) :m_Year);
    return (LPCSTR)m_DateString;
    case DDMMYY:
    m_DateString.Format("%02d/%02d/%02d",m_Day,m_Month,m_Month,m_Day,m_Year > 99 ? (m_Year < 2000 ? m_Year-1900 : m_Year-2000) :m_Year);
    return (LPCSTR)m_DateString;
    case YYMMDD:
    m_DateString.Format("%02d/%02d/%02d",m_Month,m_Day,m_Year > 99 ? (m_Year < 2000 ? m_Year-1900 : m_Year-2000) :m_Year,m_Month,m_Day);
    return (LPCSTR)m_DateString;
    case MMDDYYYY:
    m_DateString.Format("%02d/%02d/%04d",m_Month,m_Day,m_Year );
    return (LPCSTR)m_DateString;
    case DDMMYYYY:
    m_DateString.Format("%02d/%02d/%04d",m_Day,m_Month,m_Year);
    return (LPCSTR)m_DateString;
    case YYYYMMDD:
    m_DateString.Format("%04d/%02d/%02d",m_Year ,m_Month,m_Day);
    return (LPCSTR)m_DateString;
    default:
    return (LPCSTR)NULL;
    }
    }
     
    Note that I did limited testing to cover my own needs, so take it for what it's worth!
     
    R Thompson
    GeneralRe: Y2K bugsmemberRichard Stringer10 Mar '03 - 9:29 
    Y2K specs REQUIRES a 4 digit year. In your version above someone with a birthday for example of 121246 in an existing database would suddenly now have a birthday of 12122046. One should "assume" ( how I hate that word ) that any date having 2 digits for the year is in the range of 1900 -1999 and also "assume" that dates not in that range are 4 digit fields.
     
    Richard Stringer
     
    I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones.
    Albert Einstein

     

    GeneralRe: Y2K bugsmemberskyfree12 Mar '03 - 6:40 
    OK, Y2K is a poor choice of term. The issue is that if today I initialize CSimpleDate with the string "3/12/03" it assumes I mean "3/12/1903". That is not the behavior I expected, so for my purposes I had to change it. I don't deal with birthdays or dates older than 1950. Commercial software products like PowerBuilder do it this way, and it seems to be the most accepted practice in the marketplace. For a perfect example, please notice the "Date" field at the top of this message.
     
    I don't mean to be critical -- this is a great service to the programming community and saved me lots of time. Thanks -
     
    Ron Thompson
    GeneralRe: Y2K bugsmemberRichard Stringer12 Mar '03 - 8:33 
    Critical I like. Smile | :) I was just justifing my reasons for not implementing that kind of date behavior - it does induce a known failure mode and was not Y2K compliant. We often use a version that behaves much as yours does in applications where we know that the date range is limited to a given range although most of our business handles birth and death dates and dates that can span 3 centuries ( 18 -19 -20 ) .
     
    Richard

     
    In Italy for thirty years under the Borgias
    they had warfare, terror, murder and bloodshed
    but they produced Michelangelo, Leonardo
    da Vinci and the Renaissance. In Switzerland,
    they had brotherly love; they had five
    hundred years of democracy and peace
    and what did that produce?
    The cuckoo clock.
    Orson Welles

     

    GeneralBugssussAnonymous24 Oct '02 - 0:57 
    1. The comparison functions do not take time into account.
     
    I created a function to calculate a calendar value, which is used in all comparisons.
     
    time_t CSimpleDate::ConvertToTimeValue()
    {
    struct tm tmThis = { m_Second, m_Min, m_Hour, m_Day, m_Month - 1, m_Year - 1900};
    return mktime(&tmThis);
    }
     
    2. The AM/PM adjustment is not correct. It's not handling times between 12:00 PM and 1:00 PM correctly.
     
    if (m_Hour > 12)
    {
    m_bPM = TRUE;
    m_Hour -= 12;
    }
    else if (m_Hour == 12)
    {
    m_bPM = TRUE;
    }
    else
    {
    m_bPM = FALSE;
    }
     
    3. GetTimeString() and GetTimeStringShort() when called with the AmPm parameter set to FALSE do not correctly format PM times. Here is a fix:
     
    int Hour = m_Hour;
    if (AmPm == TRUE)
    {
    if (m_bPM)
    Flag = 1;
    else
    Flag = 2;
    }
    else
    {
    if (m_bPM && Hour != 12)
    Hour += 12;
    }
     
    Then format using Hour instead of m_Hour.
    GeneralRe: BugsmemberRichard Stringer24 Oct '02 - 5:45 
    I found that bug a long time ago and sent a corrected version to be posted but I guess it never did make it. The correction is a little bit easier than the above solution. The comparision of if (m_Hour > 12)should be if (m_Hour >= 12)
     
    See below. This fix worked for us.
     

    void CSimpleDate::SetTime()
    {
    long time_val ;
    struct tm *tm_ptr ;
     
    time( (time_t *)&time_val) ;
    tm_ptr = localtime( (time_t *)&time_val) ;
     
    m_Hour=tm_ptr->tm_hour;
    m_Min=tm_ptr->tm_min;
    m_Second=tm_ptr->tm_sec;
    if(m_Hour >= 12)
    {
    m_bPM=TRUE;
    m_Hour-=12;
    }
    else
    m_bPM=FALSE;
     
    }
     

     
    Richard Stringer
     
    When I reflect upon the number of disagreeable people who I know have gone to better world, I am moved to lead a different
    life.
    Mark Twain- Pudd'nhead Wilson's Calendar

     

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Permalink | Advertise | Privacy | Mobile
    Web01 | 2.6.130523.1 | Last Updated 13 Dec 1999
    Article Copyright 1999 by Richard Stringer
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid