FIX: COleDateTimeSpan Returns Incorrect ValueLast reviewed: March 20, 1998Article ID: Q148751 |
4.00 4.10
WINDOWS NT
kbprg kbbuglist kbfixlist
The information in this article applies to:
SYMPTOMSCOleDateTimeSpan 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.
CAUSECOleDateTime 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. Here is the code: double DoubleFromDate(DATE dt) { // No problem if positive if(dt >= 0) return dt; // If negative, must convert because negative dates not continuous // (examples: -1.25 to -.75, -1.50 to -.50, -1.75 to -.25) double dblWhole = modf(dt, &dt); // dt is now fractional part return dblWhole - dt;} DATE DateFromDouble(double dbl) { // No problem if positive if(dbl >= 0) return dbl; // If negative, must convert because negative dates not continuous // (examples: -.75 to -1.25, -.50 to -1.50, -.25 to -1.75) DATE dtWhole = modf(dbl, &dbl); // dbl is now fractional part return dtWhole - dbl;} Notice that the modf() function is called incorrectly. The whole number and the fractional portion are reversed.
RESOLUTIONThere are two primary ways to work around these bugs:
STATUSMicrosoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This problem was corrected in Visual C++, 32-bit Edition, version 4.2.
MORE INFORMATION
Sample Code
#include <afxole.h> #include <math.h>double GetDaySpan(COleDateTime dt1, COleDateTime dt2) { // No problem if positive if(dt1>=0 && dt2 >= 0) return fabs(dt1-dt2); // Days from midnight December 30, 1899 double Dt1SpanFromZero, Dt2SpanFromZero; if (dt1<0) { double dblDt1Whole, dblDt1Fraction; dblDt1Fraction=modf(dt1,&dblDt1Whole); Dt1SpanFromZero=dblDt1Whole-dblDt1Fraction; } else { Dt1SpanFromZero=dt1; } if (dt2<0) { double dblDt2Whole,dblDt2Fraction; dblDt2Fraction = modf(dt2, &dblDt2Whole); Dt2SpanFromZero=dblDt2Whole-dblDt2Fraction; } else { Dt2SpanFromZero=dt2; } // return positive # of days return fabs(Dt1SpanFromZero-Dt2SpanFromZero);}
void AddDays(COleDateTime &date, double dblDays){ // First, normalize negative date // Days from midnight December 30, 1899 double Dt1SpanFromZero; if (date.m_dt<0) { double dblDt1Whole, dblDt1Fraction; dblDt1Fraction=modf(date.m_dt,&dblDt1Whole); Dt1SpanFromZero=dblDt1Whole-dblDt1Fraction; } else { Dt1SpanFromZero = date.m_dt; } date.m_dt = Dt1SpanFromZero + dblDays; if (date.m_dt>=0) return; // Date before midnight December 30, 1899 // need to correct date by changing the fractional portion double dblWhole, dblFraction; dblFraction=modf(date,&dblWhole); date.m_dt=dblWhole - ( 2 + dblFraction); // Add 1 to make the fraction positive // Add 1 more to increase the whole part by one // e.g., converts a span of -1.75 ( which is -1 - .75 ) // to -2.25 ( which is -2 + .25 )}
|
Additional reference words: 4.00 4.10 vcbuglist400 vcfixlist420
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |