windows-nt/Source/XPSP1/NT/net/mmc/common/intltime.cpp

1044 lines
28 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1995 - 1999 **/
/**********************************************************************/
/*
FILE HISTORY:
*/
#define OEMRESOURCE
#include "stdafx.h"
#include <stdlib.h>
#include <memory.h>
#include <ctype.h>
#include <string.h>
#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