/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1995 - 1999 **/ /**********************************************************************/ /* FILE HISTORY: */ #define OEMRESOURCE #include "stdafx.h" #include #include #include #include #include "dbgutil.h" #include "objplus.h" #include "intltime.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW ///////////////////////////////////////////////////////////////////////////// // FormatDateTime // // Generates a current local date/time string // // ///////////////////////////////////////////////////////////////////////////// void InternalFormatDateTime(CString & strOutput, SYSTEMTIME * psystemtime, BOOL fLongDate) { int nLen; CString strDate, strTime; DWORD dwFlags = 0; dwFlags = fLongDate ? DATE_LONGDATE : DATE_SHORTDATE; // call once to get the length, and again to format the string nLen = GetDateFormat(GetThreadLocale(), dwFlags, psystemtime, NULL, NULL, 0); nLen = GetDateFormat(GetThreadLocale(), dwFlags, psystemtime, NULL, strDate.GetBuffer(nLen + 1), nLen + 1); strDate.ReleaseBuffer(); // now the time nLen = GetTimeFormat(GetThreadLocale(), 0, psystemtime, NULL, NULL, 0); nLen = GetTimeFormat(GetThreadLocale(), 0, psystemtime, NULL, strTime.GetBuffer(nLen + 1), nLen + 1); strTime.ReleaseBuffer(); strOutput = strDate + _T(" ") + strTime; } void FormatDateTime(CString & strOutput, SYSTEMTIME * psystemtime, BOOL fLongDate) { InternalFormatDateTime(strOutput, psystemtime, fLongDate); } void FormatDateTime(CString & strOutput, FILETIME * pfiletime, BOOL fLongDate) { FILETIME localTime; SYSTEMTIME systemtime; if (!FileTimeToLocalFileTime(pfiletime, &localTime)) { return; } if (!FileTimeToSystemTime(&localTime, &systemtime)) { return; } InternalFormatDateTime(strOutput, &systemtime, fLongDate); } void FormatDateTime(CString & strOutput, CTime & time, BOOL fLongDate) { SYSTEMTIME systemtime; struct tm * ptm = time.GetLocalTm(NULL); if (ptm != NULL) { systemtime.wYear = (WORD) (1900 + ptm->tm_year); systemtime.wMonth = (WORD) (1 + ptm->tm_mon); systemtime.wDayOfWeek = (WORD) ptm->tm_wday; systemtime.wDay = (WORD) ptm->tm_mday; systemtime.wHour = (WORD) ptm->tm_hour; systemtime.wMinute = (WORD) ptm->tm_min; systemtime.wSecond = (WORD) ptm->tm_sec; systemtime.wMilliseconds = 0; InternalFormatDateTime(strOutput, &systemtime, fLongDate); } else { strOutput.Empty(); } } ///////////////////////////////////////////////////////////////////////////// // CIntlTime // // These allocations cause a phoney "memory leak" error, since // they're not freed until after the audit-check. Anyway // around this? // ///////////////////////////////////////////////////////////////////////////// // Initialise static members CIntlTime::INTL_TIME_SETTINGS CIntlTime::m_itsInternationalSettings; BOOL CIntlTime::m_fIntlOk = CIntlTime::SetIntlTimeSettings(); CString CIntlTime::m_strBadDate("--"); CString CIntlTime::m_strBadTime("--"); /*** * * CIntlTime::SetIntlTimeSettings * * Purpose: * * This is a static function which initialises the international * settings (date seperator, etc) of the CIntlTime class. * * Returns: * * TRUE if the international settings are properly initialised, * or FALSE if they are not. * */ BOOL CIntlTime::SetIntlTimeSettings () { #ifdef _WIN32 #define MAXSTR 128 BOOL fOk; TCHAR str[MAXSTR]; #define GETCSTRINGFIELD(field,cstring)\ ::GetLocaleInfo(GetUserDefaultLCID(), field, cstring.GetBuffer(MAXSTR), MAXSTR);\ cstring.ReleaseBuffer() #define GETINTFIELD(field, integer)\ ::GetLocaleInfo(GetUserDefaultLCID(), field, str, MAXSTR);\ integer = _ttol(str) #define GETBOOLFIELD(field, boolean)\ ::GetLocaleInfo(GetUserDefaultLCID(), field, str, MAXSTR);\ boolean=*str == '1' fOk = GETCSTRINGFIELD(LOCALE_SDATE, CIntlTime::m_itsInternationalSettings.strDateSeperator); fOk &= GETCSTRINGFIELD(LOCALE_STIME, CIntlTime::m_itsInternationalSettings.strTimeSeperator); fOk &= GETINTFIELD(LOCALE_IDATE, CIntlTime::m_itsInternationalSettings.nDateFormat); ASSERT((CIntlTime::m_itsInternationalSettings.nDateFormat >= 0) && (CIntlTime::m_itsInternationalSettings.nDateFormat <= 2)); fOk &= GETBOOLFIELD(LOCALE_ITIME, CIntlTime::m_itsInternationalSettings.f24HourClock); fOk &= GETBOOLFIELD(LOCALE_ICENTURY, CIntlTime::m_itsInternationalSettings.fCentury); fOk &= GETBOOLFIELD(LOCALE_ITLZERO, CIntlTime::m_itsInternationalSettings.fLeadingTimeZero); fOk &= GETBOOLFIELD(LOCALE_IDAYLZERO, CIntlTime::m_itsInternationalSettings.fLeadingDayZero); fOk &= GETBOOLFIELD(LOCALE_IMONLZERO, CIntlTime::m_itsInternationalSettings.fLeadingMonthZero); if (CIntlTime::m_itsInternationalSettings.f24HourClock) { CIntlTime::m_itsInternationalSettings.strAM = ""; CIntlTime::m_itsInternationalSettings.strPM = ""; } else { fOk &= GETCSTRINGFIELD(LOCALE_S1159, CIntlTime::m_itsInternationalSettings.strAM); fOk &= GETCSTRINGFIELD(LOCALE_S2359, CIntlTime::m_itsInternationalSettings.strPM); } #ifdef _DEBUG if (!fOk) { Trace0("There was a problem with some of the intl time settings\n"); } #endif // _DEBUG return(fOk); #endif // _WIN32 #ifdef _WIN16 #define MAXSTR 128 CString strMisc; #define GETCSTRINGFIELD(field,cstring,defstring)\ ::GetProfileString("Intl", field, defstring, cstring.GetBuffer(MAXSTR), MAXSTR);\ cstring.ReleaseBuffer() #define GETINTFIELD(field, integer, defint)\ integer = ::GetProfileInt("Intl", field, defint) #define GETBOOLFIELD(field, boolean, defint)\ boolean = ::GetProfileInt("Intl", field, defint)==1 // Get the values. Assume American defaults in case of failure. GETCSTRINGFIELD("sDate", CIntlTime::m_itsInternationalSettings.strDateSeperator, "/"); GETCSTRINGFIELD("sTime", CIntlTime::m_itsInternationalSettings.strTimeSeperator, ":"); GETINTFIELD("iDate", CIntlTime::m_itsInternationalSettings.nDateFormat, 0); ASSERT((CIntlTime::m_itsInternationalSettings.nDateFormat >= 0) && (CIntlTime::m_itsInternationalSettings.nDateFormat <= 2)); GETBOOLFIELD("iTime", CIntlTime::m_itsInternationalSettings.f24HourClock, FALSE); GETBOOLFIELD("iTLZero", CIntlTime::m_itsInternationalSettings.fLeadingTimeZero, FALSE); if (CIntlTime::m_itsInternationalSettings.f24HourClock) { CIntlTime::m_itsInternationalSettings.strAM = ""; CIntlTime::m_itsInternationalSettings.strPM = ""; } else { GETCSTRINGFIELD("s1159", CIntlTime::m_itsInternationalSettings.strAM, "AM"); GETCSTRINGFIELD("s2359", CIntlTime::m_itsInternationalSettings.strPM, "PM"); } GETCSTRINGFIELD("sShortDate", strMisc, "M/d/yy"); // These settings are determined from the short date sample, as // there is no direct equivalent in the win.ini CIntlTime::m_itsInternationalSettings.fCentury = strMisc.Find("yyyy") != -1; CIntlTime::m_itsInternationalSettings.fLeadingDayZero = strMisc.Find("dd") != -1; CIntlTime::m_itsInternationalSettings.fLeadingMonthZero = strMisc.Find("MM") != -1; return(TRUE); #endif // _WIN16 } /*** * * CIntlTime::Reset() * * Purpose: * * Reset the international settings. Usually in response to * a change in those international settings by the user. * * Notes: * * This is a publically available static function. * */ void CIntlTime::Reset() { CIntlTime::m_fIntlOk = CIntlTime::SetIntlTimeSettings(); } /*** * * CIntlTime::IsLeapYear * * Purpose: * * Determine if the given year is/was a leap year * * Arguments: * * int nYear The year in question. * * Returns: * * TRUE if the year is/was a leap year, or FALSE otherwise. * * Comments: * * A year is a leap year, if is divisible by 4, but not by a 100, unless * it is divisible by 400. e.g. 1900 was not a leap year, but 2000 will * be. * */ BOOL CIntlTime::IsLeapYear(UINT nYear) { return(!(nYear % 4) && ( (nYear % 100) || !(nYear % 400) )); } /*** * * CIntlTime::IsValidDate * * Purpose: * * Determine if the given month, day year values are * valid. * * Arguments: * * int nMonth Month * int nDay Day * int nYear Year * * Returns: * * TRUE for a valid date, FALSE otherwise. * */ BOOL CIntlTime::IsValidDate(UINT nMonth, UINT nDay, UINT nYear) { // Sanity Check: BOOL fOk = ((nYear <100) || (nYear >= 1970)) && (nYear <= 2037) && ((nMonth >= 1) && (nMonth <= 12)) && ((nDay >= 1) && (nDay <= 31)); // Detailed check of days per month if (fOk) { switch(nMonth) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: break; case 4: case 6: case 9: case 11: fOk = (nDay <= 30); break; case 2: fOk = (nDay <= (UINT)(IsLeapYear(nYear) ? 29 : 28)); break; } } return(fOk); } /*** * * CIntlTime::IsValidTime * * Purpose: * * Determine if the given hour, minute, second values * valid. * * Arguments: * * int nHour Hour * int nMinute Minute * int nSecond Second * * Returns: * * TRUE for a valid time, FALSE otherwise. * */ BOOL CIntlTime::IsValidTime(UINT nHour, UINT nMinute, UINT nSecond) { return ((nHour < 24) && (nMinute < 60) && (nSecond < 60)); } // Constructors. m_fInitOk will indicate whether or not the object // was succesfully constructed. This can be checked at runtime by // the IsValid() member function CIntlTime::CIntlTime() :CTime() { // Time set to 0, always bad. m_fInitOk = FALSE; } CIntlTime::CIntlTime(const CTime &timeSrc) :CTime(timeSrc) { m_fInitOk = GetTime() > 0L; } CIntlTime::CIntlTime(time_t time) :CTime(time) { m_fInitOk = (time > 0); } CIntlTime::CIntlTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec) :CTime(nYear, nMonth, nDay, nHour, nMin, nSec) { m_fInitOk = IsValidDate(nMonth, nDay, nYear) && IsValidTime(nHour, nMin, nSec); } CIntlTime::CIntlTime(WORD wDosDate, WORD wDosTime) :CTime(wDosDate, wDosTime) { m_fInitOk = GetTime() != 0L; } // Constructor taking a string as an argument. The string can contain // either a time, a date or both. If the string is missing the date, // the current date will be filled in. If the string is missing the time, // the current time will be filled in. As with all constructors, be // sure the call IsValid() to determine proper contruction. CIntlTime::CIntlTime(const CString & strTime, int nFormat, time_t * ptmOldValue) :CTime(ConvertFromString(strTime, nFormat, ptmOldValue, &m_fInitOk)) { } CIntlTime::CIntlTime(const CIntlTime &timeSrc) { CTime::operator=(timeSrc.GetTime()); m_fInitOk = timeSrc.IsValid(); } #ifdef _WIN32 CIntlTime::CIntlTime(const SYSTEMTIME& sysTime) : CTime(sysTime) { m_fInitOk = IsValidDate((UINT)sysTime.wMonth, (UINT)sysTime.wDay, (UINT)sysTime.wYear) && IsValidTime((UINT)sysTime.wHour, (UINT)sysTime.wMinute, (UINT)sysTime.wSecond); } CIntlTime::CIntlTime(const FILETIME& fileTime) : CTime(fileTime) { m_fInitOk = GetTime() != 0L; } #endif // _WIN32 // Desctructor CIntlTime::~CIntlTime() { } // Assignment operators. As with constructors, be sure to check the // IsValid() member function to determine succesfull assignment, as // assignment operators do set the m_fInitOk member variable. const CIntlTime& CIntlTime::operator =(const CString & strValue) { time_t tmValue = ConvertFromString (strValue, CIntlTime::TFRQ_TIME_OR_DATE, NULL, &m_fInitOk); if (m_fInitOk) { CTime::operator=(tmValue); } return(*this); } // Assignment operator taking a time_t argument const CIntlTime& CIntlTime::operator =(time_t tmValue) { CTime::operator=(tmValue); m_fInitOk = (tmValue > 0); return(*this); } const CIntlTime& CIntlTime::operator =(const CTime & time) { CTime::operator=(time.GetTime()); m_fInitOk = (GetTime() > 0); return(*this); } const CIntlTime& CIntlTime::operator =(const CIntlTime & time) { CTime::operator=(time.GetTime()); m_fInitOk = (GetTime() > 0); return(*this); } // Conversion operators CIntlTime::operator const time_t() const { return(GetTime()); } // Conversion operator that returns the date followed by the time // in international format as a CString. CIntlTime::operator const CString() const { return(ConvertToString(TFRQ_TIME_AND_DATE)); } CIntlTime::operator CString() const { return(ConvertToString(TFRQ_TIME_AND_DATE)); } /*** * * CIntlTime::GetDateString() * * Purpose: * * Represent the current date in a format consistent with the current * international settings in a CString. * * Returns: * * A CString containing the date in string format, or "--" if * the date is invalid. * */ const CString CIntlTime::GetDateString() const { CString strIntl; if (!IsValid()) { return(CIntlTime::m_strBadDate); } TCHAR szPct02D[] = _T("%02d"); TCHAR szPctD[] = _T("%d"); TCHAR szDay[3], szMonth[16], szYear[8]; TCHAR *first, *second, *third; int i; i = GetYear(); if(!CIntlTime::m_itsInternationalSettings.fCentury) { i %= 100; } // fix year 2000 problem -- ericdav //::_itot(i, szYear, 10); ::wsprintf (szYear, szPct02D, i); ::wsprintf (szMonth, CIntlTime::m_itsInternationalSettings.fLeadingMonthZero ? szPct02D : szPctD, GetMonth()); ::wsprintf (szDay, CIntlTime::m_itsInternationalSettings.fLeadingDayZero ? szPct02D : szPctD, GetDay()); if (CIntlTime::m_itsInternationalSettings.nDateFormat == _DFMT_YMD) { first = szYear; second = szMonth; third = szDay; } else { third = szYear; if (CIntlTime::m_itsInternationalSettings.nDateFormat == _DFMT_DMY) { first = szDay; second = szMonth; } else { first = szMonth; second = szDay; } } ::wsprintf (strIntl.GetBuffer(80), _T("%s%s%s%s%s"), first, (LPCTSTR)CIntlTime::m_itsInternationalSettings.strDateSeperator, second, (LPCTSTR)CIntlTime::m_itsInternationalSettings.strDateSeperator, third); strIntl.ReleaseBuffer(); return(strIntl); } /*** * * CIntlTime::GetTimeString() * * Purpose: * * Represent the current time in a format consistent with the current * international settings in a CString. * * Returns: * * A CString containing the time in string format, or "--" if * the time is invalid. * */ const CString CIntlTime::GetTimeString() const { CString strIntl; if (!IsValid()) { return(CIntlTime::m_strBadTime); } int hour = GetHour(); int minute = GetMinute(); int second = GetSecond(); // Set AM/PM depending on non-24 hour clock, and the time // of day. Note: a space is prepended for readability. CString strAMPM(CIntlTime::m_itsInternationalSettings.f24HourClock ? "" : " " + ((hour < 12) ? CIntlTime::m_itsInternationalSettings.strAM : CIntlTime::m_itsInternationalSettings.strPM) ); if ((!CIntlTime::m_itsInternationalSettings.f24HourClock) && (!(hour %= 12))) { hour = 12; } ::wsprintf (strIntl.GetBuffer(30), CIntlTime::m_itsInternationalSettings.fLeadingTimeZero ? _T("%02d%s%02d%s%02d%s") : _T("%d%s%02d%s%02d%s"), hour, (LPCTSTR)CIntlTime::m_itsInternationalSettings.strTimeSeperator, minute, (LPCTSTR)CIntlTime::m_itsInternationalSettings.strTimeSeperator, second, (LPCTSTR)strAMPM); strIntl.ReleaseBuffer(); return(strIntl); } const CString CIntlTime::GetMilitaryTime() const { CString strIntl; if (!IsValid()) { return(CIntlTime::m_strBadTime); } int hour = GetHour(); int minute = GetMinute(); int second = GetSecond(); ::wsprintf (strIntl.GetBuffer(30), _T("%02d:%02d:%02d"), hour, minute, second); strIntl.ReleaseBuffer(); return(strIntl); } /*** * * CIntlTime::ConvertToString(int nFormat) * * Purpose: * * Convert the curent time/date to a string * * Arguments: * * int nFormat Format request ID, can be one of the following * values (enumerated in CIntlTime): * * TFRQ_TIME_ONLY Only give me the time. * TFRQ_DATE_ONLY Only give me the date. * TFRQ_TIME_AND_DATE Give me the time and the date. * * Returns: * * A CString containing the time and/or date in international format. * */ const CString CIntlTime::ConvertToString(int nFormat) const { switch(nFormat) { case TFRQ_TIME_ONLY: return(GetTimeString()); case TFRQ_DATE_ONLY: return(GetDateString()); case TFRQ_TIME_AND_DATE: return(GetDateString() + CString(" ") + GetTimeString()); case TFRQ_MILITARY_TIME: return(GetMilitaryTime()); case TFRQ_TIME_OR_DATE: default: Trace1("Invalid time/date format code %d requested.\n", nFormat); return(CIntlTime::m_strBadDate); } } /*** * * CIntlTime::ConvertFromString * * Purpose: * * Convert a given CString into a time_t * * Arguments: * * const CString & str The string to convert * int nFormat Format request ID, can be one of the following * values (enumerated in CIntlTime): * * TFRQ_TIME_ONLY Only give me the time. * TFRQ_DATE_ONLY Only give me the date. * TFRQ_TIME_AND_DATE Give me the time and the date. * TFRQ_TIME_OR_DATE Give me time or date (or both). * * time_t * ptmOldValue This time_t will be used to fill in the fields * not given in the string. If it is NULL, the current * time or date will be used. * BOOL * pfOk Returns TRUE for succesfull conversion, FALSE * otherwise. * * Returns: * * A time_t representing the time/date string, or 0 in case of error. * * Notes: * * Full validation of all paremeters will be done, e.g. No Feb 29 in * a non-leap year will be accepted. * * [CAVEAT] Time, date seperators longer than one character will not * work. * */ time_t CIntlTime::ConvertFromString ( const CString & str, int nFormat, time_t * ptmOldValue, // If only getting time or date, count on remaining // fields to be provided here (optionally); BOOL * pfOk) { #define MAXSTRLEN 40 TCHAR dtseps[10] ; // Date/Time separators passed to _tcstok TCHAR *pchToken; TCHAR szDateString[MAXSTRLEN+1]; BOOL fGotDate = FALSE; BOOL fGotTime = FALSE; BOOL fPM = FALSE; BOOL fAM = FALSE; int i; UINT anValues[6] = { 0, 0, 0, 0, 0, 0 }; CTime tmTmp; *pfOk = FALSE; // Assume failure. if (ptmOldValue != NULL) { tmTmp = *ptmOldValue; } else { tmTmp = CTime::GetCurrentTime(); } if (str.GetLength() > MAXSTRLEN) { // Too long to be a proper time/date string return(0); } ::lstrcpy(szDateString, (LPCTSTR)str); int nIndex = 0; // If we're looking for something specific, only // accept specific seperators (time, date, both, either) if ((nFormat == TFRQ_DATE_ONLY) || (nFormat == TFRQ_TIME_AND_DATE) || (nFormat == TFRQ_TIME_OR_DATE)) { dtseps[nIndex++] = '/'; dtseps[nIndex++] = '-'; dtseps[nIndex++] = ','; dtseps[nIndex++] = CIntlTime::m_itsInternationalSettings.strDateSeperator[0]; } if ((nFormat == TFRQ_TIME_ONLY) || (nFormat == TFRQ_TIME_AND_DATE) || (nFormat == TFRQ_TIME_OR_DATE)) { dtseps[nIndex++] = ':'; dtseps[nIndex++] = '.'; dtseps[nIndex++] = ' '; dtseps[nIndex++] = CIntlTime::m_itsInternationalSettings.strTimeSeperator[0]; } ASSERT(nIndex != 0); // Make sure we asked for something. if (nIndex == 0) { // Request type is illegal return(0); } dtseps[nIndex++] = '\0'; Trace3("CIntlTime::ConvertFromString. String: %s Format = %d Seps: %s\n", str, nFormat, dtseps); i = 0; pchToken = ::_tcstok(szDateString, dtseps); while (pchToken != NULL) { if (i > 6) // 7 fields max (date, time + AM/PM maximum) { // Too many values, reject the string. return(0); } // Determine if its a number (can't _ttoi, since it will // merely return 0 for inappropriate values) BOOL fProperNumber = TRUE; int l = ::lstrlen(pchToken); if ( (l == 0) || (l == 3) || (l > 4) ) { fProperNumber = FALSE; } else { int j; for (j=0; j < l; ++j) { if (!isdigit(*(pchToken+j))) { fProperNumber = FALSE; break; } } } if (!fProperNumber) { // Ok, this is not a proper numeric field. Only // if it's AM or PM at the end of the string can this // string be saved. fGotTime = TRUE; if ((CIntlTime::m_itsInternationalSettings.f24HourClock) || (::_tcstok(NULL, dtseps) != NULL)) { return(0); } if (!CIntlTime::m_itsInternationalSettings.strAM.CompareNoCase(pchToken)) { fAM = TRUE; } else if (!CIntlTime::m_itsInternationalSettings.strPM.CompareNoCase(pchToken)) { fPM = TRUE; } else { // Neither AM nor PM return(0); } break; } else { // Value is acceptable anValues[i++] = (UINT)::_ttoi(pchToken); } pchToken = ::_tcstok(NULL, dtseps); } // Now what did we get, exactly? ASSERT(!fAM || !fPM); // Make sure we didn't set both somehow. if (i == 0) { // String without values return(0); } switch(i) { case 1: // Hour case 2: // Hour, minutes Trace0("We got time\n"); fGotTime = TRUE; break; case 3: // This one might be ambiguous, try to intelligently decide what // we have. First check if only time or date only was requested, // then check for out of bounds time values, and lastly check for // the presence of a time seperator. if (!fGotTime) // If we didn't already have AM/PM { Trace0("Picking between time and date by seperator\n"); if (nFormat == TFRQ_DATE_ONLY) { fGotDate = TRUE; } else if (nFormat == TFRQ_TIME_ONLY) { fGotTime = TRUE; } else if ((anValues[0] > 23) || (anValues[1] > 59) || (anValues[2] > 59)) { fGotDate = TRUE; } else if (str.Find(CIntlTime::m_itsInternationalSettings.strTimeSeperator) != -1) { fGotTime = TRUE; } else { fGotDate = TRUE; } Trace1("Decided on %s", (fGotDate ? "date\n" : "time\n")); } break; case 4: // Date, hour case 5: // Date, hours, minutes case 6: // Date, hours, minutes, seconds Trace0("We got date and time\n"); fGotDate = TRUE; fGotTime = TRUE; break; default: ASSERT(0 && "Incorrect number of values!"); return(0); } // Was that what we're looking for? if ( ((nFormat == TFRQ_DATE_ONLY) && fGotTime) || ((nFormat == TFRQ_TIME_ONLY) && fGotDate) || ((nFormat == TFRQ_TIME_AND_DATE) && (!fGotTime || !fGotDate)) ) { Trace0("Entry didn't match expectations\n"); return(0); } i = 0; int h, m, s, D, M, Y; // Array indices; // Now determine where to find what. if (fGotDate) // Date always goes first { switch(CIntlTime::m_itsInternationalSettings.nDateFormat) { case _DFMT_MDY: M = i++; D = i++; Y = i++; break; case _DFMT_DMY: D = i++; M = i++; Y = i++; break; case _DFMT_YMD: Y = i++; M = i++; D = i++; break; } // If only 2 digits are given, determine if we're talking about // the 21st or 20th century if (anValues[Y] < 100) { anValues[Y] += (anValues[Y] > 37) ? 1900 : 2000; } Trace3("Month = %d Day = %d Year = %d\n", anValues[M], anValues[D], anValues[Y]); // Validation. if (!IsValidDate(anValues[M], anValues[D], anValues[Y])) { return(0); } } if (fGotTime) { h = i++; m = i++; s = i++; Trace3("Hours = %d Minutes = %d Seconds = %d\n", anValues[h], anValues[m], anValues[s]); // Shouldn't specify AM or PM with 24 hour clock value. if ((anValues[h] > 12) && (fAM || fPM)) { return(0); } // Adjust for AM/PM modifiers if (fPM) { if (anValues[h] != 12) { anValues[h] += 12; } } else if (fAM) { if ( anValues[h] == 12) { anValues[h] -= 12; } } // Sanity Check: if (!IsValidTime(anValues[h], anValues[m], anValues[s])) { return(0); } } // Fill in the missing fields CIntlTime tm( fGotDate ? anValues[Y] : tmTmp.GetYear(), fGotDate ? anValues[M] : tmTmp.GetMonth(), fGotDate ? anValues[D] : tmTmp.GetDay(), fGotTime ? anValues[h] : tmTmp.GetHour(), fGotTime ? anValues[m] : tmTmp.GetMinute(), fGotTime ? anValues[s] : tmTmp.GetSecond() ); *pfOk = (tm.GetTime() > (time_t)0); return(tm); } #ifdef _DEBUG // Dump to debug device CDumpContext& AFXAPI operator<<(CDumpContext& dc, const CIntlTime& tim) { dc << _T("\nDate Seperator: ") << tim.m_itsInternationalSettings.strDateSeperator; dc << _T("\nTime Seperator: ") << tim.m_itsInternationalSettings.strTimeSeperator; dc << _T("\nAM String: ") << tim.m_itsInternationalSettings.strAM; dc << _T("\nPM String: ") << tim.m_itsInternationalSettings.strPM; dc << _T("\nDate Format: ") << tim.m_itsInternationalSettings.nDateFormat; dc << _T("\n24 Hour Clock: ") << (tim.m_itsInternationalSettings.f24HourClock ? "TRUE" : "FALSE"); dc << _T("\n4 Digit Century: ") << (tim.m_itsInternationalSettings.fCentury ? "TRUE" : "FALSE"); dc << _T("\nTime Leading Zero: ") << (tim.m_itsInternationalSettings.fLeadingTimeZero ? "TRUE" : "FALSE"); dc << _T("\nDay Leading Zero ") << (tim.m_itsInternationalSettings.fLeadingDayZero ? "TRUE" : "FALSE"); dc << _T("\nMonth Leading Zero: ") << (tim.m_itsInternationalSettings.fLeadingMonthZero ? "TRUE" : "FALSE"); dc << _T("\n\ntime_t: ") << tim.GetTime(); return(dc); } #endif // _DEBUG