Introduction
Most of our apps use Oracle databases, and over the last 5 years, we've come to rely heavily on our COleDateTime
objects' ability to deal with a m_dt
value of 0.0 (12/30/1899). Long before I joined the team, I also relied on this. The COleDateTme
considered a value of 0.0 to be "valid", and it would happily format the date as expected. Until February of 2006, we used VC6, but then our team began using VS2005.
It seems that Microsoft changed the COleDateTime
class so that a m_dt
value of 0.0 was still considered "valid", but the class ASSERT
s if you attempt to format any date that falls on the back-side of 01/01/1900. This new behaviour instantly broke millions of lines of code for us (and that's no exaggeration).
How We Fixed It
As usual, we were under a time crunch to get our code converted, so we had to come up with something quick and dirty. We simply wrote a static function in one of our utility classes, and here it is. I made liberal use of the CString::Replace()
method. One thing (that strikes me as a bit weird) about this is that I had to use the CString
constructor to pass literal strings into the various CString
functions. I might have been missing a compiler definition in my test app or something that our converted projects had, but in any case, this should work with or without that weirdness. Without further delay, here's the code:
CString FormatOleDateTime(COleDateTime odt, LPCTSTR strFormatString)
{
CString strDateTime("");
CString sFormatString(strFormatString);
if (odt.m_dt == 0.0)
{
sFormatString.Replace(CString("%#d"), CString("%d"));
sFormatString.Replace(CString("%#H"), CString("%H"));
sFormatString.Replace(CString("%#I"), CString("%I"));
sFormatString.Replace(CString("%#j"), CString("%j"));
sFormatString.Replace(CString("%#m"), CString("%m"));
sFormatString.Replace(CString("%#M"), CString("%M"));
sFormatString.Replace(CString("%#S"), CString("%S"));
sFormatString.Replace(CString("%#U"), CString("%U"));
sFormatString.Replace(CString("%#w"), CString("%w"));
sFormatString.Replace(CString("%#W"), CString("%W"));
sFormatString.Replace(CString("%#y"), CString("%y"));
sFormatString.Replace(CString("%#Y"), CString("%Y"));
sFormatString.Replace(CString("%j"), CString(""));
sFormatString.Replace(CString("%w"), CString(""));
sFormatString.Replace(CString("%a"), CString("Sat"));
sFormatString.Replace(CString("%A"), CString("Saturday"));
sFormatString.Replace(CString("%p"), CString("PM"));
odt.SetDateTime(1900, 12, 29, 23, 59, 59);
strDateTime = odt.Format(sFormatString);
if (sFormatString.Find(CString("%Y")) >= 0 &&
strDateTime.Find(CString("1900")) >= 0)
{
strDateTime.Replace(CString("1900"), CString("1899"));
}
if (sFormatString.Find(CString("%y")) >= 0)
{
strDateTime.Replace(CString("-00"), CString("-99"));
strDateTime.Replace(CString("/00"), CString("/99"));
strDateTime.Replace(CString(",00"), CString(",99"));
strDateTime.Replace(CString(".00"), CString(".99"));
strDateTime.Replace(CString("00"), CString("99"));
}
strDateTime.Replace(CString("23"), CString("00"));
strDateTime.Replace(CString("59"), CString("00"));
strDateTime.Replace(CString("29"), CString("30"));
}
else
{
strDateTime = odt.Format(strFormatString);
}
return strDateTime;
}
Upcoming VS2005 Service Pack
Microsoft claims there's a service pack on the way, and that they have done something to the COleDateTime
class as a direct result of complaints they've been receiving, but I haven't seen anywhere where they mentioned what they did. I guess we're going to have to wait and see, but until we get more info (and/or the service pack), this is a passable workaround.