FIX: COleDateTimeSpan Returns Incorrect Value (148751)
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), when used with:
- Microsoft Visual C++, 32-bit Editions 4.0
- Microsoft Visual C++, 32-bit Editions 4.1
This article was previously published under Q148751 SYMPTOMS
COleDateTimeSpan returns an incorrect number of days when using dates
earlier than midnight December 30, 1899. Also, adding or subtracting
COleDateTimeSpan objects from COleDateTime objects will produce incorrect
results if the resulting date is before midnight December 30, 1899.
CAUSE
COleDateTime stores a double that represents the number of days relative to
midnight December 30, 1899 (the base date). A date prior to the base date
is represented by a negative number. A date that falls after the base date
is represented by a positive double value. For example, if the date is
December 29, 1899 at midnight, the value of COleDateTime is -1.0.
To calculate the actual number of days between a date prior to the base
date and the base date, add the fractional part of the COleDateTime's
double variable instead of subtracting it. For example, December 29, 1899
at 6:00 a.m. is represented as -1.25. Note, it is .75 days from the base
date of midnight December 30, 1899.
The DoubleFromDate() and DateFromDouble() in OLEVAR.CPP located in the
\Msdev\Mfc\Src directory attempt to correct for the difference with
negative numbers as mentioned above. These functions incorrectly handle
this.
Sample Code
double DoubleFromDate(DATE dt)
{
// No problem if it's positive.
if(dt >= 0)
return dt;
// If it's negative, must convert because negative dates not
// continuous (for example, -1.25 to -.75, -1.50 to -.50,
// -1.75 to -.25).
double dblWhole = modf(dt, &dt); // dt is now a fractional part.
return dblWhole - dt;
}
DATE DateFromDouble(double dbl)
{
// No problem if it's positive.
if(dbl >= 0)
return dbl;
// If it's negative, must convert because negative dates not
// continuous (for example, -.75 to -1.25, -.50 to -1.50,
// -.25 to -1.75).
DATE dtWhole = modf(dbl, &dbl); // dbl is now a fractional part.
return dtWhole - dbl;
}
Notice that the modf() function is called incorrectly. The whole number and
the fractional portion are reversed.
RESOLUTION
You can use one of the following ways to work around these bugs:
- Create your own COleDateTimeSpan object to handle this correctly. Use
the COleDateTimeSpan code in Olevar.cpp as a guide. Then you can cut
and paste. Unfortunately, no virtual functions exist for
COleDateTimeSpan that will allow you to easily correct the bug.
- Write functions that will produce the same results as COleTimeSpan.
See the sample code in this article for a function that will
calculate the number of days between two given dates. The function
always returns a positive number of days to avoid any confusion about
what negative and positive time spans mean. There is also a function
that allows you to add a number of days to an existing COleDateTime
object.
STATUSThis bug was corrected in Visual C++,32-bit Edition, version 4.2.
Modification Type: | Major | Last Reviewed: | 10/24/2003 |
---|
Keywords: | kbBug kbfix kbNoUpdate kbVC420fix KB148751 |
---|
|