Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3055 lines
85 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. DATETIMEPARSER.CPP
  5. Abstract:
  6. Parses a date/time string and converts it into it's component values.
  7. History:
  8. raymcc 25-Jul-99 Updated to bypass strict checks on DMTF
  9. formats due to backward compatibility issues
  10. and breaks reported by other teams. See
  11. NOT_USED_IN_WIN2000 #idndef bracketed code.
  12. --*/
  13. //=============================================================================
  14. //
  15. // CDateTimeParser
  16. //
  17. // Parses a date/time string and converts it into it's component values.
  18. //
  19. // Supported DMTF date/time formats:
  20. // 1: yyyymmddhhmmss.uuuuuu+UTC
  21. // 2: yyyymmddhhmmss.uuuuuu-UTC
  22. //
  23. // Supported date formats:
  24. // 1: Mon[th] dd[,] [yy]yy
  25. // 2: Mon[th][,] yyyy
  26. // 3: Mon[th] [yy]yy dd
  27. // 4: dd Mon[th][,][ ][yy]yy
  28. // 5: dd [yy]yy Mon[th]
  29. // 6: [yy]yy Mon[th] dd
  30. // 7: yyyy Mon[th]
  31. // 8: yyyy dd Mon[th]
  32. // 9: [M]M{/-.}dd{/-,}[yy]yy ->Has to be same separator!
  33. // 10: dd{/-.}[M]M{/-.}[yy]yy ->Has to be same separator!
  34. // 11: [M]M{/-.}[yy]yy{/-.}dd ->Has to be same separator!
  35. // 12: dd{/-.}[yy]yy{/-.}[M]M ->Has to be same separator!
  36. // 13: [yy]yy{/-.}dd{/-.}[M]M ->Has to be same separator!
  37. // 14: [yy]yy{/-.}[M]M{/-.}dd ->Has to be same separator!
  38. // 15: [yy]yyMMdd and yyyy[MM[dd]]
  39. //
  40. // Supported Time formats:
  41. // 1: hh[ ]{AP}M
  42. // 2: hh:mm
  43. // 3: hh:mm[ ]{AP}M
  44. // 4: hh:mm:ss
  45. // 5: hh:mm:ss[ ]{AP}M
  46. // 6: hh:mm:ss:uuu
  47. // 7: hh:mm:ss.[[u]u]u
  48. // 8: hh:mm:ss:uuu[ ]{AP}M
  49. // 9: hh:mm:ss.[[u]u]u[ ]{AP}M
  50. //=============================================================================
  51. #include "precomp.h"
  52. #include <string.h>
  53. #include <stdio.h>
  54. #include "DateTimeParser.h"
  55. #include <TCHAR.h>
  56. //=============================================================================
  57. // Constructor. This takes a DateTime string and parses it.
  58. //=============================================================================
  59. CDateTimeParser::CDateTimeParser(const TCHAR *pszDateTime)
  60. : m_nDayFormatPreference(mdy)
  61. {
  62. // Get the prefered date format by using NLS locale call
  63. GetPreferedDateFormat();
  64. //Get the localised long month strings
  65. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME1, m_pszFullMonth[0]);
  66. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME2, m_pszFullMonth[1]);
  67. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME3, m_pszFullMonth[2]);
  68. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME4, m_pszFullMonth[3]);
  69. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME5, m_pszFullMonth[4]);
  70. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME6, m_pszFullMonth[5]);
  71. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME7, m_pszFullMonth[6]);
  72. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME8, m_pszFullMonth[7]);
  73. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME9, m_pszFullMonth[8]);
  74. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME10, m_pszFullMonth[9]);
  75. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME11, m_pszFullMonth[10]);
  76. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME12, m_pszFullMonth[11]);
  77. GetLocalInfoAndAlloc(LOCALE_SMONTHNAME13, m_pszFullMonth[12]);
  78. //Get the localised short month strings
  79. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME1, m_pszShortMonth[0]);
  80. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME2, m_pszShortMonth[1]);
  81. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME3, m_pszShortMonth[2]);
  82. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME4, m_pszShortMonth[3]);
  83. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME5, m_pszShortMonth[4]);
  84. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME6, m_pszShortMonth[5]);
  85. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME7, m_pszShortMonth[6]);
  86. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME8, m_pszShortMonth[7]);
  87. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME9, m_pszShortMonth[8]);
  88. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME10, m_pszShortMonth[9]);
  89. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME11, m_pszShortMonth[10]);
  90. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME12, m_pszShortMonth[11]);
  91. GetLocalInfoAndAlloc(LOCALE_SABBREVMONTHNAME13, m_pszShortMonth[12]);
  92. //Get the localised AM/PM strings
  93. GetLocalInfoAndAlloc(LOCALE_S1159, m_pszAmPm[0]);
  94. GetLocalInfoAndAlloc(LOCALE_S2359, m_pszAmPm[1]);
  95. //Decode the date time string.
  96. SetDateTime(pszDateTime);
  97. }
  98. CDateTimeParser::CDateTimeParser( void )
  99. : m_nDayFormatPreference(mdy),
  100. m_bValidDateTime( FALSE ),
  101. m_nDay( 0 ),
  102. m_nMonth( 0 ),
  103. m_nYear( 0 ),
  104. m_nHours( 0 ),
  105. m_nMinutes( 0 ),
  106. m_nSeconds( 0 ),
  107. m_nMicroseconds( 0 ),
  108. m_nUTC( 0 )
  109. {
  110. ZeroMemory( m_pszFullMonth, sizeof(m_pszFullMonth) );
  111. ZeroMemory( m_pszShortMonth, sizeof(m_pszShortMonth) );
  112. ZeroMemory( m_pszAmPm, sizeof(m_pszAmPm) );
  113. }
  114. //=============================================================================
  115. // Destructor. Tidies up after itself.
  116. //=============================================================================
  117. CDateTimeParser::~CDateTimeParser()
  118. {
  119. if ( NULL != m_pszFullMonth[0] ) delete [] m_pszFullMonth[0];
  120. if ( NULL != m_pszFullMonth[1] ) delete [] m_pszFullMonth[1];
  121. if ( NULL != m_pszFullMonth[2] ) delete [] m_pszFullMonth[2];
  122. if ( NULL != m_pszFullMonth[3] ) delete [] m_pszFullMonth[3];
  123. if ( NULL != m_pszFullMonth[4] ) delete [] m_pszFullMonth[4];
  124. if ( NULL != m_pszFullMonth[5] ) delete [] m_pszFullMonth[5];
  125. if ( NULL != m_pszFullMonth[6] ) delete [] m_pszFullMonth[6];
  126. if ( NULL != m_pszFullMonth[7] ) delete [] m_pszFullMonth[7];
  127. if ( NULL != m_pszFullMonth[8] ) delete [] m_pszFullMonth[8];
  128. if ( NULL != m_pszFullMonth[9] ) delete [] m_pszFullMonth[9];
  129. if ( NULL != m_pszFullMonth[10] ) delete [] m_pszFullMonth[10];
  130. if ( NULL != m_pszFullMonth[11] ) delete [] m_pszFullMonth[11];
  131. if ( NULL != m_pszFullMonth[12] ) delete [] m_pszFullMonth[12];
  132. if ( NULL != m_pszShortMonth[0] ) delete [] m_pszShortMonth[0];
  133. if ( NULL != m_pszShortMonth[1] ) delete [] m_pszShortMonth[1];
  134. if ( NULL != m_pszShortMonth[2] ) delete [] m_pszShortMonth[2];
  135. if ( NULL != m_pszShortMonth[3] ) delete [] m_pszShortMonth[3];
  136. if ( NULL != m_pszShortMonth[4] ) delete [] m_pszShortMonth[4];
  137. if ( NULL != m_pszShortMonth[5] ) delete [] m_pszShortMonth[5];
  138. if ( NULL != m_pszShortMonth[6] ) delete [] m_pszShortMonth[6];
  139. if ( NULL != m_pszShortMonth[7] ) delete [] m_pszShortMonth[7];
  140. if ( NULL != m_pszShortMonth[8] ) delete [] m_pszShortMonth[8];
  141. if ( NULL != m_pszShortMonth[9] ) delete [] m_pszShortMonth[9];
  142. if ( NULL != m_pszShortMonth[10] ) delete [] m_pszShortMonth[10];
  143. if ( NULL != m_pszShortMonth[11] ) delete [] m_pszShortMonth[11];
  144. if ( NULL != m_pszShortMonth[12] ) delete [] m_pszShortMonth[12];
  145. if ( NULL != m_pszAmPm[0] ) delete [] m_pszAmPm[0];
  146. if ( NULL != m_pszAmPm[1] ) delete [] m_pszAmPm[1];
  147. }
  148. TCHAR* CDateTimeParser::AllocAmPm()
  149. {
  150. TCHAR* pszAP = new TCHAR[4];
  151. if (pszAP)
  152. {
  153. pszAP[0] = ' ';
  154. pszAP[1] = m_pszAmPm[0][0];
  155. pszAP[2] = m_pszAmPm[1][0];
  156. pszAP[3] = 0;
  157. }
  158. return pszAP;
  159. }
  160. //=============================================================================
  161. // Does a GetLocalInfo and allocates the buffer large enough for the item.
  162. //=============================================================================
  163. void CDateTimeParser::GetLocalInfoAndAlloc(LCTYPE LCType, LPTSTR &lpLCData)
  164. {
  165. int nSize;
  166. nSize = GetLocaleInfo(LOCALE_USER_DEFAULT, LCType, NULL, 0);
  167. lpLCData = new TCHAR[nSize];
  168. if (lpLCData)
  169. GetLocaleInfo(LOCALE_USER_DEFAULT, LCType, lpLCData, nSize);
  170. }
  171. //=============================================================================
  172. // Uses locale call to work out the prefered date format.
  173. //=============================================================================
  174. void CDateTimeParser::GetPreferedDateFormat()
  175. {
  176. int nSize;
  177. if (!(nSize = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, NULL, 0)))
  178. return; // will use default of mdy
  179. TCHAR* lpLCData = new TCHAR[nSize];
  180. if(lpLCData == NULL)
  181. return;
  182. if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, lpLCData, nSize))
  183. {
  184. delete [] lpLCData;
  185. return; // will use default of mdy
  186. }
  187. nSize -= 2; // index of last character
  188. // It is only necessary to check first and last character to determine format
  189. if (lpLCData[0] == 'M')
  190. {
  191. if (lpLCData[nSize] == 'y')
  192. m_nDayFormatPreference = mdy;
  193. else // lpLCData[nSize] == 'd'
  194. m_nDayFormatPreference = myd;
  195. }
  196. else if (lpLCData[0] == 'd')
  197. {
  198. if (lpLCData[nSize] == 'y')
  199. m_nDayFormatPreference = dmy;
  200. else // lpLCData[nSize] == 'M'
  201. m_nDayFormatPreference = dym;
  202. }
  203. else // lpLCPata[0] == 'y'
  204. {
  205. if (lpLCData[nSize] == 'd')
  206. m_nDayFormatPreference = ymd;
  207. else // lpLCData[nSize] == 'M'
  208. m_nDayFormatPreference = ydm;
  209. }
  210. delete [] lpLCData;
  211. }
  212. //=============================================================================
  213. // Tidies up and parses a new date and time.
  214. //=============================================================================
  215. BOOL CDateTimeParser::SetDateTime(const TCHAR *pszDateTime)
  216. {
  217. ResetDateTime(TRUE);
  218. if (CheckDMTFDateTimeFormatInternal(pszDateTime) == TRUE)
  219. return TRUE;
  220. if (CheckDateFormat(pszDateTime, TRUE) == TRUE)
  221. return TRUE;
  222. if (CheckTimeFormat(pszDateTime, TRUE) == TRUE)
  223. return TRUE;
  224. return TRUE;
  225. }
  226. //=============================================================================
  227. // Resets all the date/time values to the default values.
  228. // If bSQL is TRUE it sets to the SQL default. Otherwise
  229. // sets to the DMTF default.
  230. //=============================================================================
  231. void CDateTimeParser::ResetDateTime(BOOL bSQL)
  232. {
  233. ResetDate(bSQL);
  234. ResetTime(bSQL);
  235. }
  236. void CDateTimeParser::ResetDate(BOOL bSQL)
  237. {
  238. m_bValidDateTime = FALSE;
  239. m_nDay = 1;
  240. m_nMonth = 1;
  241. m_nYear = 1990;
  242. }
  243. void CDateTimeParser::ResetTime(BOOL bSQL)
  244. {
  245. m_bValidDateTime = FALSE;
  246. m_nHours = 0;
  247. m_nMinutes = 0;
  248. m_nSeconds = 0;
  249. m_nMicroseconds = 0;
  250. m_nUTC = 0;
  251. }
  252. //=============================================================================
  253. // Checks the date time for a valid DMTF string
  254. // 1: yyyymmddhhmmss.uuuuuu+UTC
  255. // 2: yyyymmddhhmmss.uuuuuu-UTC
  256. // Note, this code is a near duplicate of the checks used to test the interval format.
  257. //=============================================================================
  258. BOOL CDateTimeParser::CheckDMTFDateTimeFormatInternal(const TCHAR *pszDateTime)
  259. {
  260. if (lstrlen(pszDateTime) != 25)
  261. return FALSE;
  262. //Validate digits and puntuation...
  263. for (int i = 0; i < 14; i++)
  264. {
  265. if (!isdigit(pszDateTime[i]))
  266. return FALSE;
  267. }
  268. if (pszDateTime[i] != '.')
  269. return FALSE;
  270. for (i++;i < 21; i++)
  271. {
  272. if (!isdigit(pszDateTime[i]))
  273. return FALSE;
  274. }
  275. if ((pszDateTime[i] != '+') && (pszDateTime[i] != '-'))
  276. return FALSE;
  277. for (i++; i < 25; i++)
  278. {
  279. if (!isdigit(pszDateTime[i]))
  280. return FALSE;
  281. }
  282. m_nYear = ((pszDateTime[0] - '0') * 1000) +
  283. ((pszDateTime[1] - '0') * 100) +
  284. ((pszDateTime[2] - '0') * 10) +
  285. (pszDateTime[3] - '0');
  286. if (m_nYear < 1601)
  287. return FALSE;
  288. m_nMonth = ((pszDateTime[4] - '0') * 10) +
  289. (pszDateTime[5] - '0');
  290. if (m_nMonth < 1 || m_nMonth > 12)
  291. return FALSE;
  292. m_nDay = ((pszDateTime[6] - '0') * 10) +
  293. (pszDateTime[7] - '0');
  294. if (m_nDay < 1 || m_nDay > 31)
  295. return FALSE;
  296. m_nHours = ((pszDateTime[8] - '0') * 10) +
  297. (pszDateTime[9] - '0');
  298. if (m_nHours > 23)
  299. return FALSE;
  300. m_nMinutes = ((pszDateTime[10] - '0') * 10) +
  301. (pszDateTime[11] - '0');
  302. if (m_nMinutes > 59)
  303. return FALSE;
  304. m_nSeconds = ((pszDateTime[12] - '0') * 10) +
  305. (pszDateTime[13] - '0');
  306. if (m_nSeconds > 59)
  307. return FALSE;
  308. //14 is '.'
  309. m_nMicroseconds = ((pszDateTime[15] - '0') * 100000) +
  310. ((pszDateTime[16] - '0') * 10000) +
  311. ((pszDateTime[17] - '0') * 1000) +
  312. ((pszDateTime[18] - '0') * 100) +
  313. ((pszDateTime[19] - '0') * 10) +
  314. (pszDateTime[20] - '0');
  315. //21 is '+' or '-'
  316. m_nUTC = ((pszDateTime[22] - '0') * 100) +
  317. ((pszDateTime[23] - '0') * 10) +
  318. (pszDateTime[24] - '0');
  319. if (pszDateTime[21] == '-')
  320. m_nUTC = 0 - m_nUTC;
  321. m_bValidDateTime = TRUE;
  322. return TRUE;
  323. }
  324. //=============================================================================
  325. // Static helper function so outside code can do quick DMTF format checks.
  326. //=============================================================================
  327. BOOL CDateTimeParser::CheckDMTFDateTimeFormat(
  328. const TCHAR *wszDateTime,
  329. BOOL bFailIfRelative,
  330. BOOL bFailIfUnzoned
  331. )
  332. {
  333. if (wszDateTime == 0)
  334. return FALSE;
  335. int nLen = lstrlen(wszDateTime);
  336. if (nLen != 25)
  337. return FALSE;
  338. // Do two quick checks. Ensure that the . and : are in
  339. // the right places or at least that * chars are there.
  340. wchar_t c1 = wszDateTime[14];
  341. wchar_t c2 = wszDateTime[21];
  342. if (!(c1 == L'.' || c1 == L'*'))
  343. return FALSE;
  344. if (!(c2 == L'+' || c2 == L'*' || c2 == '-'))
  345. return FALSE;
  346. return TRUE;
  347. #ifdef NOT_USED_IN_WIN2000
  348. BOOL bReturn = FALSE;
  349. // Temporary buffer for conversion
  350. char szTemp[64];
  351. int nNumChars = WideCharToMultiByte( CP_ACP, 0L, wszDateTime, -1, NULL, 0, NULL, NULL );
  352. if ( nNumChars < sizeof(szTemp) - 1 )
  353. {
  354. // We know it will fit, so do the conversion and use the date/time parser to
  355. // perform a conversion
  356. WideCharToMultiByte( CP_ACP, 0L, wszDateTime, -1, szTemp, sizeof(szTemp), NULL, NULL );
  357. // Check for use of asterisks for relative date/time
  358. if (!bFailIfRelative)
  359. {
  360. // Check year and if ALL asterisks then replace with a valid number
  361. if (szTemp[0] == '*' && szTemp[1] == '*' && szTemp[2] == '*' && szTemp[3] == '*')
  362. {
  363. szTemp[0] = '1'; szTemp[1] = '9'; szTemp[2] = '9'; szTemp[3] = '0';
  364. }
  365. // Check month and if ALL asterisks then replace with a valid number
  366. if (szTemp[4] == '*' && szTemp[5] == '*')
  367. {
  368. szTemp[4] = '0'; szTemp[5] = '1';
  369. }
  370. // Check day and if ALL asterisks then replace with a valid number
  371. if (szTemp[6] == '*' && szTemp[7] == '*')
  372. {
  373. szTemp[6] = '0'; szTemp[7] = '1';
  374. }
  375. // Check hour and if ALL asterisks then replace with a valid number
  376. if (szTemp[8] == '*' && szTemp[9] == '*')
  377. {
  378. szTemp[8] = '0'; szTemp[9] = '0';
  379. }
  380. // Check minutes and if ALL asterisks then replace with a valid number
  381. if (szTemp[10] == '*' && szTemp[11] == '*')
  382. {
  383. szTemp[10] = '0'; szTemp[11] = '0';
  384. }
  385. // Check seconds and if ALL asterisks then replace with a valid number
  386. if (szTemp[12] == '*' && szTemp[13] == '*')
  387. {
  388. szTemp[12] = '0'; szTemp[13] = '0';
  389. }
  390. // Check microseconds and if ALL asterisks then replace with a valid number
  391. if (szTemp[15] == '*' && szTemp[16] == '*' && szTemp[17] == '*' &&
  392. szTemp[18] == '*' && szTemp[19] == '*' && szTemp[20] == '*')
  393. {
  394. szTemp[15] = '0'; szTemp[16] = '0'; szTemp[17] = '0';
  395. szTemp[18] = '0'; szTemp[19] = '0'; szTemp[20] = '0';
  396. }
  397. }
  398. // Check for use of asterisks for unzoned date/time
  399. if (!bFailIfUnzoned)
  400. {
  401. // Check UTC and if ALL asterisks then replace with a valid number
  402. if (szTemp[22] == '*' && szTemp[23] == '*' && szTemp[24] == '*')
  403. {
  404. szTemp[22] = '0'; szTemp[23] = '0'; szTemp[24] = '0';
  405. }
  406. }
  407. CDateTimeParser dtParse;
  408. bReturn = dtParse.CheckDMTFDateTimeFormatInternal( szTemp );
  409. }
  410. return bReturn;
  411. #endif
  412. }
  413. //=============================================================================
  414. // Static helper function so outside code can do quick DMTF format checks.
  415. // Currently, a time interval can only be validated, it cannot be used
  416. // to initialize a CDateTimeParser instance.
  417. //=============================================================================
  418. BOOL CDateTimeParser::CheckDMTFDateTimeInterval(
  419. LPCTSTR wszInterval
  420. )
  421. {
  422. if (wszInterval == 0)
  423. return FALSE;
  424. int nLen = lstrlen(wszInterval);
  425. if (nLen != 25)
  426. return FALSE;
  427. // Do two quick checks. Ensure that the . and : are in
  428. // the right places or at least that * chars are there.
  429. wchar_t c1 = wszInterval[14];
  430. wchar_t c2 = wszInterval[21];
  431. if (!(c1 == L'.' || c1 == L'*'))
  432. return FALSE;
  433. if (!(c2 == L':' || c2 == L'*'))
  434. return FALSE;
  435. return TRUE;
  436. #ifdef NOT_USED_IN_WIN2000
  437. // Temporary buffer for conversion
  438. char szTemp[64];
  439. int nNumChars = WideCharToMultiByte( CP_ACP, 0L, wszInterval, -1, NULL, 0, NULL, NULL );
  440. if ( nNumChars < sizeof(szTemp) - 1 )
  441. {
  442. // We know it will fit, so do the conversion and use the date/time parser to
  443. // perform a conversion
  444. WideCharToMultiByte( CP_ACP, 0L, wszInterval, -1, szTemp, sizeof(szTemp), NULL, NULL );
  445. // =======================================================================================
  446. // Check the date time for a valid DMTF interval string:
  447. // ddddddddHHMMSS.mmmmmm:000
  448. // Note, this code is a near duplicate of the checks used to test the non-interval format.
  449. // =======================================================================================
  450. if (strlen(szTemp) != 25)
  451. return FALSE;
  452. //Validate digits and puntuation...
  453. for (int i = 0; i < 14; i++)
  454. {
  455. if (!isdigit(szTemp[i]))
  456. return FALSE;
  457. }
  458. if (szTemp[i] != '.')
  459. return FALSE;
  460. for (i++;i < 21; i++)
  461. {
  462. if (!isdigit(szTemp[i]))
  463. return FALSE;
  464. }
  465. if (szTemp[i] != ':')
  466. return FALSE;
  467. for (i++; i < 25; i++)
  468. {
  469. if (szTemp[i] != '0')
  470. return FALSE;
  471. }
  472. int nHours = ((szTemp[8] - '0') * 10) +
  473. (szTemp[9] - '0');
  474. if (nHours > 23)
  475. return FALSE;
  476. int nMinutes = ((szTemp[10] - '0') * 10) +
  477. (szTemp[11] - '0');
  478. if (nMinutes > 59)
  479. return FALSE;
  480. int nSeconds = ((szTemp[12] - '0') * 10) +
  481. (szTemp[13] - '0');
  482. if (nSeconds > 59)
  483. return FALSE;
  484. return TRUE;
  485. }
  486. return FALSE;
  487. #endif
  488. }
  489. //=============================================================================
  490. // Goes through each of the date formats checking to see if any are valid
  491. //=============================================================================
  492. BOOL CDateTimeParser::CheckDateFormat(const TCHAR *pszDate, BOOL bCheckTimeAfter)
  493. {
  494. if (DateFormat1(pszDate, bCheckTimeAfter))
  495. return TRUE;
  496. if (DateFormat2(pszDate, bCheckTimeAfter))
  497. return TRUE;
  498. if (DateFormat3(pszDate, bCheckTimeAfter))
  499. return TRUE;
  500. if (DateFormat4(pszDate, bCheckTimeAfter))
  501. return TRUE;
  502. if (DateFormat5(pszDate, bCheckTimeAfter))
  503. return TRUE;
  504. if (DateFormat6(pszDate, bCheckTimeAfter))
  505. return TRUE;
  506. if (DateFormat7(pszDate, bCheckTimeAfter))
  507. return TRUE;
  508. if (DateFormat8(pszDate, bCheckTimeAfter))
  509. return TRUE;
  510. if (DateFormat15(pszDate, bCheckTimeAfter))
  511. return TRUE;
  512. switch(m_nDayFormatPreference)
  513. {
  514. case dmy:
  515. if (DateFormat10(pszDate, __TEXT("/"), bCheckTimeAfter))
  516. return TRUE;
  517. if (DateFormat10(pszDate, __TEXT("-"), bCheckTimeAfter))
  518. return TRUE;
  519. if (DateFormat10(pszDate, __TEXT("."), bCheckTimeAfter))
  520. return TRUE;
  521. if (DateFormat9(pszDate, __TEXT("/"), bCheckTimeAfter))
  522. return TRUE;
  523. if (DateFormat9(pszDate, __TEXT("-"), bCheckTimeAfter))
  524. return TRUE;
  525. if (DateFormat9(pszDate, __TEXT("."), bCheckTimeAfter))
  526. return TRUE;
  527. if (DateFormat11(pszDate, __TEXT("/"), bCheckTimeAfter))
  528. return TRUE;
  529. if (DateFormat11(pszDate, __TEXT("-"), bCheckTimeAfter))
  530. return TRUE;
  531. if (DateFormat11(pszDate, __TEXT("."), bCheckTimeAfter))
  532. return TRUE;
  533. if (DateFormat12(pszDate, __TEXT("/"), bCheckTimeAfter))
  534. return TRUE;
  535. if (DateFormat12(pszDate, __TEXT("-"), bCheckTimeAfter))
  536. return TRUE;
  537. if (DateFormat12(pszDate, __TEXT("."), bCheckTimeAfter))
  538. return TRUE;
  539. if (DateFormat13(pszDate, __TEXT("/"), bCheckTimeAfter))
  540. return TRUE;
  541. if (DateFormat13(pszDate, __TEXT("-"), bCheckTimeAfter))
  542. return TRUE;
  543. if (DateFormat13(pszDate, __TEXT("."), bCheckTimeAfter))
  544. return TRUE;
  545. if (DateFormat14(pszDate, __TEXT("/"), bCheckTimeAfter))
  546. return TRUE;
  547. if (DateFormat14(pszDate, __TEXT("-"), bCheckTimeAfter))
  548. return TRUE;
  549. if (DateFormat14(pszDate, __TEXT("."), bCheckTimeAfter))
  550. return TRUE;
  551. break;
  552. case dym:
  553. if (DateFormat12(pszDate, __TEXT("/"), bCheckTimeAfter))
  554. return TRUE;
  555. if (DateFormat12(pszDate, __TEXT("-"), bCheckTimeAfter))
  556. return TRUE;
  557. if (DateFormat12(pszDate, __TEXT("."), bCheckTimeAfter))
  558. return TRUE;
  559. if (DateFormat9(pszDate, __TEXT("/"), bCheckTimeAfter))
  560. return TRUE;
  561. if (DateFormat9(pszDate, __TEXT("-"), bCheckTimeAfter))
  562. return TRUE;
  563. if (DateFormat9(pszDate, __TEXT("."), bCheckTimeAfter))
  564. return TRUE;
  565. if (DateFormat10(pszDate, __TEXT("/"), bCheckTimeAfter))
  566. return TRUE;
  567. if (DateFormat10(pszDate, __TEXT("-"), bCheckTimeAfter))
  568. return TRUE;
  569. if (DateFormat10(pszDate, __TEXT("."), bCheckTimeAfter))
  570. return TRUE;
  571. if (DateFormat11(pszDate, __TEXT("/"), bCheckTimeAfter))
  572. return TRUE;
  573. if (DateFormat11(pszDate, __TEXT("-"), bCheckTimeAfter))
  574. return TRUE;
  575. if (DateFormat11(pszDate, __TEXT("."), bCheckTimeAfter))
  576. return TRUE;
  577. if (DateFormat13(pszDate, __TEXT("/"), bCheckTimeAfter))
  578. return TRUE;
  579. if (DateFormat13(pszDate, __TEXT("-"), bCheckTimeAfter))
  580. return TRUE;
  581. if (DateFormat13(pszDate, __TEXT("."), bCheckTimeAfter))
  582. return TRUE;
  583. if (DateFormat14(pszDate, __TEXT("/"), bCheckTimeAfter))
  584. return TRUE;
  585. if (DateFormat14(pszDate, __TEXT("-"), bCheckTimeAfter))
  586. return TRUE;
  587. if (DateFormat14(pszDate, __TEXT("."), bCheckTimeAfter))
  588. return TRUE;
  589. break;
  590. case mdy:
  591. if (DateFormat9(pszDate, __TEXT("/"), bCheckTimeAfter))
  592. return TRUE;
  593. if (DateFormat9(pszDate, __TEXT("-"), bCheckTimeAfter))
  594. return TRUE;
  595. if (DateFormat9(pszDate, __TEXT("."), bCheckTimeAfter))
  596. return TRUE;
  597. if (DateFormat10(pszDate, __TEXT("/"), bCheckTimeAfter))
  598. return TRUE;
  599. if (DateFormat10(pszDate, __TEXT("-"), bCheckTimeAfter))
  600. return TRUE;
  601. if (DateFormat10(pszDate, __TEXT("."), bCheckTimeAfter))
  602. return TRUE;
  603. if (DateFormat11(pszDate, __TEXT("/"), bCheckTimeAfter))
  604. return TRUE;
  605. if (DateFormat11(pszDate, __TEXT("-"), bCheckTimeAfter))
  606. return TRUE;
  607. if (DateFormat11(pszDate, __TEXT("."), bCheckTimeAfter))
  608. return TRUE;
  609. if (DateFormat12(pszDate, __TEXT("/"), bCheckTimeAfter))
  610. return TRUE;
  611. if (DateFormat12(pszDate, __TEXT("-"), bCheckTimeAfter))
  612. return TRUE;
  613. if (DateFormat12(pszDate, __TEXT("."), bCheckTimeAfter))
  614. return TRUE;
  615. if (DateFormat13(pszDate, __TEXT("/"), bCheckTimeAfter))
  616. return TRUE;
  617. if (DateFormat13(pszDate, __TEXT("-"), bCheckTimeAfter))
  618. return TRUE;
  619. if (DateFormat13(pszDate, __TEXT("."), bCheckTimeAfter))
  620. return TRUE;
  621. if (DateFormat14(pszDate, __TEXT("/"), bCheckTimeAfter))
  622. return TRUE;
  623. if (DateFormat14(pszDate, __TEXT("-"), bCheckTimeAfter))
  624. return TRUE;
  625. if (DateFormat14(pszDate, __TEXT("."), bCheckTimeAfter))
  626. return TRUE;
  627. break;
  628. case myd:
  629. if (DateFormat11(pszDate, __TEXT("/"), bCheckTimeAfter))
  630. return TRUE;
  631. if (DateFormat11(pszDate, __TEXT("-"), bCheckTimeAfter))
  632. return TRUE;
  633. if (DateFormat11(pszDate, __TEXT("."), bCheckTimeAfter))
  634. return TRUE;
  635. if (DateFormat9(pszDate, __TEXT("/"), bCheckTimeAfter))
  636. return TRUE;
  637. if (DateFormat9(pszDate, __TEXT("-"), bCheckTimeAfter))
  638. return TRUE;
  639. if (DateFormat9(pszDate, __TEXT("."), bCheckTimeAfter))
  640. return TRUE;
  641. if (DateFormat10(pszDate, __TEXT("/"), bCheckTimeAfter))
  642. return TRUE;
  643. if (DateFormat10(pszDate, __TEXT("-"), bCheckTimeAfter))
  644. return TRUE;
  645. if (DateFormat10(pszDate, __TEXT("."), bCheckTimeAfter))
  646. return TRUE;
  647. if (DateFormat12(pszDate, __TEXT("/"), bCheckTimeAfter))
  648. return TRUE;
  649. if (DateFormat12(pszDate, __TEXT("-"), bCheckTimeAfter))
  650. return TRUE;
  651. if (DateFormat12(pszDate, __TEXT("."), bCheckTimeAfter))
  652. return TRUE;
  653. if (DateFormat13(pszDate, __TEXT("/"), bCheckTimeAfter))
  654. return TRUE;
  655. if (DateFormat13(pszDate, __TEXT("-"), bCheckTimeAfter))
  656. return TRUE;
  657. if (DateFormat13(pszDate, __TEXT("."), bCheckTimeAfter))
  658. return TRUE;
  659. if (DateFormat14(pszDate, __TEXT("/"), bCheckTimeAfter))
  660. return TRUE;
  661. if (DateFormat14(pszDate, __TEXT("-"), bCheckTimeAfter))
  662. return TRUE;
  663. if (DateFormat14(pszDate, __TEXT("."), bCheckTimeAfter))
  664. return TRUE;
  665. break;
  666. case ydm:
  667. if (DateFormat13(pszDate, __TEXT("/"), bCheckTimeAfter))
  668. return TRUE;
  669. if (DateFormat13(pszDate, __TEXT("-"), bCheckTimeAfter))
  670. return TRUE;
  671. if (DateFormat13(pszDate, __TEXT("."), bCheckTimeAfter))
  672. return TRUE;
  673. if (DateFormat9(pszDate, __TEXT("/"), bCheckTimeAfter))
  674. return TRUE;
  675. if (DateFormat9(pszDate, __TEXT("-"), bCheckTimeAfter))
  676. return TRUE;
  677. if (DateFormat9(pszDate, __TEXT("."), bCheckTimeAfter))
  678. return TRUE;
  679. if (DateFormat10(pszDate, __TEXT("/"), bCheckTimeAfter))
  680. return TRUE;
  681. if (DateFormat10(pszDate, __TEXT("-"), bCheckTimeAfter))
  682. return TRUE;
  683. if (DateFormat10(pszDate, __TEXT("."), bCheckTimeAfter))
  684. return TRUE;
  685. if (DateFormat11(pszDate, __TEXT("/"), bCheckTimeAfter))
  686. return TRUE;
  687. if (DateFormat11(pszDate, __TEXT("-"), bCheckTimeAfter))
  688. return TRUE;
  689. if (DateFormat11(pszDate, __TEXT("."), bCheckTimeAfter))
  690. return TRUE;
  691. if (DateFormat12(pszDate, __TEXT("/"), bCheckTimeAfter))
  692. return TRUE;
  693. if (DateFormat12(pszDate, __TEXT("-"), bCheckTimeAfter))
  694. return TRUE;
  695. if (DateFormat12(pszDate, __TEXT("."), bCheckTimeAfter))
  696. return TRUE;
  697. if (DateFormat14(pszDate, __TEXT("/"), bCheckTimeAfter))
  698. return TRUE;
  699. if (DateFormat14(pszDate, __TEXT("-"), bCheckTimeAfter))
  700. return TRUE;
  701. if (DateFormat14(pszDate, __TEXT("."), bCheckTimeAfter))
  702. return TRUE;
  703. break;
  704. case ymd:
  705. if (DateFormat14(pszDate, __TEXT("/"), bCheckTimeAfter))
  706. return TRUE;
  707. if (DateFormat14(pszDate, __TEXT("-"), bCheckTimeAfter))
  708. return TRUE;
  709. if (DateFormat14(pszDate, __TEXT("."), bCheckTimeAfter))
  710. return TRUE;
  711. if (DateFormat9(pszDate, __TEXT("/"), bCheckTimeAfter))
  712. return TRUE;
  713. if (DateFormat9(pszDate, __TEXT("-"), bCheckTimeAfter))
  714. return TRUE;
  715. if (DateFormat9(pszDate, __TEXT("."), bCheckTimeAfter))
  716. return TRUE;
  717. if (DateFormat10(pszDate, __TEXT("/"), bCheckTimeAfter))
  718. return TRUE;
  719. if (DateFormat10(pszDate, __TEXT("-"), bCheckTimeAfter))
  720. return TRUE;
  721. if (DateFormat10(pszDate, __TEXT("."), bCheckTimeAfter))
  722. return TRUE;
  723. if (DateFormat11(pszDate, __TEXT("/"), bCheckTimeAfter))
  724. return TRUE;
  725. if (DateFormat11(pszDate, __TEXT("-"), bCheckTimeAfter))
  726. return TRUE;
  727. if (DateFormat11(pszDate, __TEXT("."), bCheckTimeAfter))
  728. return TRUE;
  729. if (DateFormat12(pszDate, __TEXT("/"), bCheckTimeAfter))
  730. return TRUE;
  731. if (DateFormat12(pszDate, __TEXT("-"), bCheckTimeAfter))
  732. return TRUE;
  733. if (DateFormat12(pszDate, __TEXT("."), bCheckTimeAfter))
  734. return TRUE;
  735. if (DateFormat13(pszDate, __TEXT("/"), bCheckTimeAfter))
  736. return TRUE;
  737. if (DateFormat13(pszDate, __TEXT("-"), bCheckTimeAfter))
  738. return TRUE;
  739. if (DateFormat13(pszDate, __TEXT("."), bCheckTimeAfter))
  740. return TRUE;
  741. break;
  742. default:
  743. return FALSE;
  744. }
  745. return FALSE;
  746. }
  747. //=============================================================================
  748. // Goes through each of the time formats checking to see if any are valid
  749. // Order is important here. Re-arranged to properly recognize AM/PM - mdavis.
  750. //=============================================================================
  751. BOOL CDateTimeParser::CheckTimeFormat(const TCHAR *pszTime, BOOL bCheckDateAfter)
  752. {
  753. if (TimeFormat1(pszTime, bCheckDateAfter))
  754. return TRUE;
  755. if (TimeFormat3(pszTime, bCheckDateAfter))
  756. return TRUE;
  757. if (TimeFormat2(pszTime, bCheckDateAfter))
  758. return TRUE;
  759. if (TimeFormat5(pszTime, bCheckDateAfter))
  760. return TRUE;
  761. if (TimeFormat4(pszTime, bCheckDateAfter))
  762. return TRUE;
  763. if (TimeFormat8(pszTime, bCheckDateAfter))
  764. return TRUE;
  765. if (TimeFormat6(pszTime, bCheckDateAfter))
  766. return TRUE;
  767. if (TimeFormat9(pszTime, bCheckDateAfter))
  768. return TRUE;
  769. if (TimeFormat7(pszTime, bCheckDateAfter))
  770. return TRUE;
  771. return FALSE;
  772. }
  773. //=============================================================================
  774. // Checks for date/time in the following format...
  775. // 'Mon[th] dd[,] [yy]yy'
  776. // passes remaining string on to time parser if bCheckTimeAfter is set
  777. //=============================================================================
  778. BOOL CDateTimeParser::DateFormat1(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  779. {
  780. //Copy of string which we can change...
  781. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  782. if (!pszString)
  783. goto error;
  784. lstrcpy(pszString, pszDateTime);
  785. if (IsValidMonthString(pszString, __TEXT(" "), m_pszFullMonth, m_pszShortMonth) != ok)
  786. goto error;
  787. if (IsValidDayNumber(NULL, __TEXT(" ,")) != ok)
  788. goto error;
  789. if (IsValidYearNumber(NULL, __TEXT(" "), FALSE) != ok)
  790. goto error;
  791. if (bCheckTimeAfter)
  792. {
  793. //Get the remaining string
  794. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  795. if (pszRemainingString)
  796. {
  797. //Skip white space
  798. while (*pszRemainingString == __TEXT(' '))
  799. pszRemainingString++;
  800. //if we are not at the end of the string pass on to the time
  801. //parser
  802. if (*pszRemainingString != __TEXT('\0'))
  803. {
  804. if (!CheckTimeFormat(pszRemainingString, FALSE))
  805. {
  806. goto error;
  807. }
  808. }
  809. }
  810. }
  811. delete [] pszString;
  812. //mark date/time as valid...
  813. m_bValidDateTime = TRUE;
  814. return TRUE;
  815. error:
  816. //mark date/time as invalid...
  817. ResetDate(TRUE);
  818. //Tidy up
  819. if (pszString)
  820. delete [] pszString;
  821. return FALSE;
  822. }
  823. //=============================================================================
  824. // Checks for date/time in the following format...
  825. // 'Mon[th][,] yyyy'
  826. // passes remaining string on to time parser if bCheckTimeAfter is set
  827. //=============================================================================
  828. BOOL CDateTimeParser::DateFormat2(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  829. {
  830. //Copy of string which we can change...
  831. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  832. if (!pszString)
  833. goto error;
  834. lstrcpy(pszString, pszDateTime);
  835. if (IsValidMonthString(pszString, __TEXT(" ,"), m_pszFullMonth, m_pszShortMonth) != ok)
  836. goto error;
  837. if (IsValidYearNumber(NULL, __TEXT(" "), TRUE) != ok)
  838. goto error;
  839. if (bCheckTimeAfter)
  840. {
  841. //Get the remaining string
  842. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  843. if (pszRemainingString)
  844. {
  845. //Skip white space
  846. while (*pszRemainingString == __TEXT(' '))
  847. pszRemainingString++;
  848. //if we are not at the end of the string pass on to the time
  849. //parser
  850. if (*pszRemainingString != __TEXT('\0'))
  851. {
  852. if (!CheckTimeFormat(pszRemainingString, FALSE))
  853. {
  854. goto error;
  855. }
  856. }
  857. }
  858. }
  859. delete [] pszString;
  860. //mark date/time as valid...
  861. m_bValidDateTime = TRUE;
  862. return TRUE;
  863. error:
  864. //mark date/time as invalid...
  865. ResetDate(TRUE);
  866. //Tidy up
  867. if (pszString)
  868. delete [] pszString;
  869. return FALSE;
  870. }
  871. //=============================================================================
  872. // Checks for date/time in the following format...
  873. // 'Mon[th] [yy]yy dd'
  874. // passes remaining string on to time parser if bCheckTimeAfter is set
  875. //=============================================================================
  876. BOOL CDateTimeParser::DateFormat3(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  877. {
  878. //Copy of string which we can change...
  879. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  880. if (!pszString)
  881. goto error;
  882. lstrcpy(pszString, pszDateTime);
  883. if (IsValidMonthString(pszString, __TEXT(" ,"), m_pszFullMonth, m_pszShortMonth) != ok)
  884. goto error;
  885. if (IsValidYearNumber(NULL, __TEXT(" "), FALSE) != ok)
  886. goto error;
  887. if (IsValidDayNumber(NULL, __TEXT(" ")) != ok)
  888. goto error;
  889. if (bCheckTimeAfter)
  890. {
  891. //Get the remaining string
  892. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  893. if (pszRemainingString)
  894. {
  895. //Skip white space
  896. while (*pszRemainingString == __TEXT(' '))
  897. pszRemainingString++;
  898. //if we are not at the end of the string pass on to the time
  899. //parser
  900. if (*pszRemainingString != __TEXT('\0'))
  901. {
  902. if (!CheckTimeFormat(pszRemainingString, FALSE))
  903. {
  904. goto error;
  905. }
  906. }
  907. }
  908. }
  909. delete [] pszString;
  910. //mark date/time as valid...
  911. m_bValidDateTime = TRUE;
  912. return TRUE;
  913. error:
  914. //mark date/time as invalid...
  915. ResetDate(TRUE);
  916. //Tidy up
  917. if (pszString)
  918. delete [] pszString;
  919. return FALSE;
  920. }
  921. //=============================================================================
  922. // Checks for date/time in the following format...
  923. // 'dd Mon[th][,][ ][yy]yy'
  924. // passes remaining string on to time parser if bCheckTimeAfter is set
  925. //=============================================================================
  926. BOOL CDateTimeParser::DateFormat4(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  927. {
  928. //Copy of string which we can change...
  929. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  930. if (!pszString)
  931. goto error;
  932. lstrcpy(pszString, pszDateTime);
  933. if (IsValidDayNumber(pszString, __TEXT(" ")) != ok)
  934. goto error;
  935. if (IsValidMonthString(NULL, __TEXT(" ,"), m_pszFullMonth, m_pszShortMonth) != ok)
  936. goto error;
  937. if (IsValidYearNumber(NULL, __TEXT(" "), FALSE) != ok)
  938. goto error;
  939. if (bCheckTimeAfter)
  940. {
  941. //Get the remaining string
  942. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  943. if (pszRemainingString)
  944. {
  945. //Skip white space
  946. while (*pszRemainingString == __TEXT(' '))
  947. pszRemainingString++;
  948. //if we are not at the end of the string pass on to the time
  949. //parser
  950. if (*pszRemainingString != __TEXT('\0'))
  951. {
  952. if (!CheckTimeFormat(pszRemainingString, FALSE))
  953. {
  954. goto error;
  955. }
  956. }
  957. }
  958. }
  959. delete [] pszString;
  960. //mark date/time as valid...
  961. m_bValidDateTime = TRUE;
  962. return TRUE;
  963. error:
  964. //mark date/time as invalid...
  965. ResetDate(TRUE);
  966. //Tidy up
  967. if (pszString)
  968. delete [] pszString;
  969. return FALSE;
  970. }
  971. //=============================================================================
  972. // Checks for date/time in the following format...
  973. // 'dd [yy]yy Mon[th]'
  974. // passes remaining string on to time parser if bCheckTimeAfter is set
  975. //=============================================================================
  976. BOOL CDateTimeParser::DateFormat5(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  977. {
  978. //Copy of string which we can change...
  979. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  980. if (!pszString)
  981. goto error;
  982. lstrcpy(pszString, pszDateTime);
  983. if (IsValidDayNumber(pszString, __TEXT(" ")) != ok)
  984. goto error;
  985. if (IsValidYearNumber(NULL, __TEXT(" "), FALSE) != ok)
  986. goto error;
  987. if (IsValidMonthString(NULL, __TEXT(" "), m_pszFullMonth, m_pszShortMonth) != ok)
  988. goto error;
  989. if (bCheckTimeAfter)
  990. {
  991. //Get the remaining string
  992. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  993. if (pszRemainingString)
  994. {
  995. //Skip white space
  996. while (*pszRemainingString == __TEXT(' '))
  997. pszRemainingString++;
  998. //if we are not at the end of the string pass on to the time
  999. //parser
  1000. if (*pszRemainingString != __TEXT('\0'))
  1001. {
  1002. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1003. {
  1004. goto error;
  1005. }
  1006. }
  1007. }
  1008. }
  1009. delete [] pszString;
  1010. //mark date/time as valid...
  1011. m_bValidDateTime = TRUE;
  1012. return TRUE;
  1013. error:
  1014. //mark date/time as invalid...
  1015. ResetDate(TRUE);
  1016. //Tidy up
  1017. if (pszString)
  1018. delete [] pszString;
  1019. return FALSE;
  1020. }
  1021. //=============================================================================
  1022. // Checks for date/time in the following format...
  1023. // '[yy]yy Mon[th] dd'
  1024. // passes remaining string on to time parser if bCheckTimeAfter is set
  1025. //=============================================================================
  1026. BOOL CDateTimeParser::DateFormat6(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  1027. {
  1028. //Copy of string which we can change...
  1029. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1030. if (!pszString)
  1031. goto error;
  1032. lstrcpy(pszString, pszDateTime);
  1033. if (IsValidYearNumber(pszString, __TEXT(" "), FALSE) != ok)
  1034. goto error;
  1035. if (IsValidMonthString(NULL, __TEXT(" "), m_pszFullMonth, m_pszShortMonth) != ok)
  1036. goto error;
  1037. if (IsValidDayNumber(NULL, __TEXT(" ")) != ok)
  1038. goto error;
  1039. if (bCheckTimeAfter)
  1040. {
  1041. //Get the remaining string
  1042. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1043. if (pszRemainingString)
  1044. {
  1045. //Skip white space
  1046. while (*pszRemainingString == ' ')
  1047. pszRemainingString++;
  1048. //if we are not at the end of the string pass on to the time
  1049. //parser
  1050. if (*pszRemainingString != '\0')
  1051. {
  1052. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1053. {
  1054. goto error;
  1055. }
  1056. }
  1057. }
  1058. }
  1059. delete [] pszString;
  1060. //mark date/time as valid...
  1061. m_bValidDateTime = TRUE;
  1062. return TRUE;
  1063. error:
  1064. //mark date/time as invalid...
  1065. ResetDate(TRUE);
  1066. //Tidy up
  1067. if (pszString)
  1068. delete [] pszString;
  1069. return FALSE;
  1070. }
  1071. //=============================================================================
  1072. // Checks for date in the following format...
  1073. // yyyy Mon[th]
  1074. // passes remaining string on to time parser if bCheckTimeAfter is set
  1075. //=============================================================================
  1076. BOOL CDateTimeParser::DateFormat7(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  1077. {
  1078. //Copy of string which we can change...
  1079. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1080. if (!pszString)
  1081. goto error;
  1082. lstrcpy(pszString, pszDateTime);
  1083. if (IsValidYearNumber(pszString, __TEXT(" "), TRUE) != ok)
  1084. goto error;
  1085. if (IsValidMonthString(NULL, __TEXT(" "), m_pszFullMonth, m_pszShortMonth) != ok)
  1086. goto error;
  1087. if (bCheckTimeAfter)
  1088. {
  1089. //Get the remaining string
  1090. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1091. if (pszRemainingString)
  1092. {
  1093. //Skip white space
  1094. while (*pszRemainingString == __TEXT(' '))
  1095. pszRemainingString++;
  1096. //if we are not at the end of the string pass on to the time
  1097. //parser
  1098. if (*pszRemainingString != __TEXT('\0'))
  1099. {
  1100. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1101. {
  1102. goto error;
  1103. }
  1104. }
  1105. }
  1106. }
  1107. delete [] pszString;
  1108. //mark date/time as valid...
  1109. m_bValidDateTime = TRUE;
  1110. return TRUE;
  1111. error:
  1112. //mark date/time as invalid...
  1113. ResetDate(TRUE);
  1114. //Tidy up
  1115. if (pszString)
  1116. delete [] pszString;
  1117. return FALSE;
  1118. }
  1119. //=============================================================================
  1120. // Checks for date/time in the following format...
  1121. // yyyy dd Mon[th]
  1122. // passes remaining string on to time parser if bCheckTimeAfter is set
  1123. //=============================================================================
  1124. BOOL CDateTimeParser::DateFormat8(const TCHAR *pszDateTime, BOOL bCheckTimeAfter)
  1125. {
  1126. //Copy of string which we can change...
  1127. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1128. if (!pszString)
  1129. goto error;
  1130. lstrcpy(pszString, pszDateTime);
  1131. if (IsValidYearNumber(pszString, __TEXT(" "), TRUE) != ok)
  1132. goto error;
  1133. if (IsValidDayNumber(NULL, __TEXT(" ")) != ok)
  1134. goto error;
  1135. if (IsValidMonthString(NULL, __TEXT(" "), m_pszFullMonth, m_pszShortMonth) != ok)
  1136. goto error;
  1137. if (bCheckTimeAfter)
  1138. {
  1139. //Get the remaining string
  1140. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1141. if (pszRemainingString)
  1142. {
  1143. //Skip white space
  1144. while (*pszRemainingString == __TEXT(' '))
  1145. pszRemainingString++;
  1146. //if we are not at the end of the string pass on to the time
  1147. //parser
  1148. if (*pszRemainingString != '\0')
  1149. {
  1150. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1151. {
  1152. goto error;
  1153. }
  1154. }
  1155. }
  1156. }
  1157. delete [] pszString;
  1158. //mark date/time as valid...
  1159. m_bValidDateTime = TRUE;
  1160. return TRUE;
  1161. error:
  1162. //mark date/time as invalid...
  1163. ResetDate(TRUE);
  1164. //Tidy up
  1165. if (pszString)
  1166. delete [] pszString;
  1167. return FALSE;
  1168. }
  1169. //=============================================================================
  1170. // Checks for date in the following format...
  1171. // '[M]M{/-.}dd{/-.}[yy]yy -> Separators have to be the same
  1172. // passes remaining string on to time parser if bCheckTimeAfter is set
  1173. //=============================================================================
  1174. BOOL CDateTimeParser::DateFormat9(const TCHAR *pszDateTime,
  1175. const TCHAR *pszDateSeparator,
  1176. BOOL bCheckTimeAfter)
  1177. {
  1178. //Copy of string which we can change...
  1179. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1180. if (!pszString)
  1181. goto error;
  1182. lstrcpy(pszString, pszDateTime);
  1183. if (IsValidMonthNumber(pszString, pszDateSeparator) != ok)
  1184. goto error;
  1185. if (IsValidDayNumber(NULL, pszDateSeparator) != ok)
  1186. goto error;
  1187. if (IsValidYearNumber(NULL, __TEXT(" "), FALSE) != ok)
  1188. goto error;
  1189. if (bCheckTimeAfter)
  1190. {
  1191. //Get the remaining string
  1192. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1193. if (pszRemainingString)
  1194. {
  1195. //Skip white space
  1196. while (*pszRemainingString == __TEXT(' '))
  1197. pszRemainingString++;
  1198. //if we are not at the end of the string pass on to the time
  1199. //parser
  1200. if (*pszRemainingString != __TEXT('\0'))
  1201. {
  1202. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1203. {
  1204. goto error;
  1205. }
  1206. }
  1207. }
  1208. }
  1209. delete [] pszString;
  1210. //mark date/time as valid...
  1211. m_bValidDateTime = TRUE;
  1212. return TRUE;
  1213. error:
  1214. //mark date/time as invalid...
  1215. ResetDate(TRUE);
  1216. //Tidy up
  1217. if (pszString)
  1218. delete [] pszString;
  1219. return FALSE;
  1220. }
  1221. //=============================================================================
  1222. // Checks for date in the following format...
  1223. // dd{/-.}[M]M{/-.}[yy]yy -> Separators have to be the same
  1224. // passes remaining string on to time parser if bCheckTimeAfter is set
  1225. //=============================================================================
  1226. BOOL CDateTimeParser::DateFormat10(const TCHAR *pszDateTime,
  1227. const TCHAR *pszDateSeparator,
  1228. BOOL bCheckTimeAfter)
  1229. {
  1230. //Copy of string which we can change...
  1231. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1232. if (!pszString)
  1233. goto error;
  1234. lstrcpy(pszString, pszDateTime);
  1235. if (IsValidDayNumber(pszString, pszDateSeparator) != ok)
  1236. goto error;
  1237. if (IsValidMonthNumber(NULL, pszDateSeparator) != ok)
  1238. goto error;
  1239. if (IsValidYearNumber(NULL, __TEXT(" "), FALSE) != ok)
  1240. goto error;
  1241. if (bCheckTimeAfter)
  1242. {
  1243. //Get the remaining string
  1244. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1245. if (pszRemainingString)
  1246. {
  1247. //Skip white space
  1248. while (*pszRemainingString == __TEXT(' '))
  1249. pszRemainingString++;
  1250. //if we are not at the end of the string pass on to the time
  1251. //parser
  1252. if (*pszRemainingString != __TEXT('\0'))
  1253. {
  1254. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1255. {
  1256. goto error;
  1257. }
  1258. }
  1259. }
  1260. }
  1261. delete [] pszString;
  1262. //mark date/time as valid...
  1263. m_bValidDateTime = TRUE;
  1264. return TRUE;
  1265. error:
  1266. //mark date/time as invalid...
  1267. ResetDate(TRUE);
  1268. //Tidy up
  1269. if (pszString)
  1270. delete [] pszString;
  1271. return FALSE;
  1272. }
  1273. //=============================================================================
  1274. // Checks for date in the following format...
  1275. // [M]M{/-.}[yy]yy{/-.}dd ->Has to be same separator!
  1276. // passes remaining string on to time parser if bCheckTimeAfter is set
  1277. //=============================================================================
  1278. BOOL CDateTimeParser::DateFormat11(const TCHAR *pszDateTime,
  1279. const TCHAR *pszDateSeparator,
  1280. BOOL bCheckTimeAfter)
  1281. {
  1282. //Copy of string which we can change...
  1283. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1284. if (!pszString)
  1285. goto error;
  1286. lstrcpy(pszString, pszDateTime);
  1287. if (IsValidMonthNumber(pszString, pszDateSeparator) != ok)
  1288. goto error;
  1289. if (IsValidYearNumber(NULL, pszDateSeparator, FALSE) != ok)
  1290. goto error;
  1291. if (IsValidDayNumber(NULL, __TEXT(" ")) != ok)
  1292. goto error;
  1293. if (bCheckTimeAfter)
  1294. {
  1295. //Get the remaining string
  1296. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1297. if (pszRemainingString)
  1298. {
  1299. //Skip white space
  1300. while (*pszRemainingString == __TEXT(' '))
  1301. pszRemainingString++;
  1302. //if we are not at the end of the string pass on to the time
  1303. //parser
  1304. if (*pszRemainingString != __TEXT('\0'))
  1305. {
  1306. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1307. {
  1308. goto error;
  1309. }
  1310. }
  1311. }
  1312. }
  1313. delete [] pszString;
  1314. //mark date/time as valid...
  1315. m_bValidDateTime = TRUE;
  1316. return TRUE;
  1317. error:
  1318. //mark date/time as invalid...
  1319. ResetDate(TRUE);
  1320. //Tidy up
  1321. if (pszString)
  1322. delete [] pszString;
  1323. return FALSE;
  1324. }
  1325. //=============================================================================
  1326. // Checks for date in the following format...
  1327. // dd{/-.}[yy]yy{/-.}[M]M ->Has to be same separator!
  1328. // passes remaining string on to time parser if bCheckTimeAfter is set
  1329. //=============================================================================
  1330. BOOL CDateTimeParser::DateFormat12(const TCHAR *pszDateTime,
  1331. const TCHAR *pszDateSeparator,
  1332. BOOL bCheckTimeAfter)
  1333. {
  1334. //Copy of string which we can change...
  1335. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1336. if (!pszString)
  1337. goto error;
  1338. lstrcpy(pszString, pszDateTime);
  1339. if (IsValidDayNumber(pszString, pszDateSeparator) != ok)
  1340. goto error;
  1341. if (IsValidYearNumber(NULL, pszDateSeparator, FALSE) != ok)
  1342. goto error;
  1343. if (IsValidMonthNumber(NULL, __TEXT(" ")) != ok)
  1344. goto error;
  1345. if (bCheckTimeAfter)
  1346. {
  1347. //Get the remaining string
  1348. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1349. if (pszRemainingString)
  1350. {
  1351. //Skip white space
  1352. while (*pszRemainingString == __TEXT(' '))
  1353. pszRemainingString++;
  1354. //if we are not at the end of the string pass on to the time
  1355. //parser
  1356. if (*pszRemainingString != __TEXT('\0'))
  1357. {
  1358. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1359. {
  1360. goto error;
  1361. }
  1362. }
  1363. }
  1364. }
  1365. delete [] pszString;
  1366. //mark date/time as valid...
  1367. m_bValidDateTime = TRUE;
  1368. return TRUE;
  1369. error:
  1370. //mark date/time as invalid...
  1371. ResetDate(TRUE);
  1372. //Tidy up
  1373. if (pszString)
  1374. delete [] pszString;
  1375. return FALSE;
  1376. }
  1377. //=============================================================================
  1378. // Checks for date in the following format...
  1379. // [yy]yy{/-.}dd{/-.}[M]M ->Has to be same separator!
  1380. // passes remaining string on to time parser if bCheckTimeAfter is set
  1381. //=============================================================================
  1382. BOOL CDateTimeParser::DateFormat13(const TCHAR *pszDateTime,
  1383. const TCHAR *pszDateSeparator,
  1384. BOOL bCheckTimeAfter)
  1385. {
  1386. //Copy of string which we can change...
  1387. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1388. if (!pszString)
  1389. goto error;
  1390. lstrcpy(pszString, pszDateTime);
  1391. if (IsValidYearNumber(pszString, pszDateSeparator, FALSE) != ok)
  1392. goto error;
  1393. if (IsValidDayNumber(NULL, pszDateSeparator) != ok)
  1394. goto error;
  1395. if (IsValidMonthNumber(NULL, __TEXT(" ")) != ok)
  1396. goto error;
  1397. if (bCheckTimeAfter)
  1398. {
  1399. //Get the remaining string
  1400. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1401. if (pszRemainingString)
  1402. {
  1403. //Skip white space
  1404. while (*pszRemainingString == __TEXT(' '))
  1405. pszRemainingString++;
  1406. //if we are not at the end of the string pass on to the time
  1407. //parser
  1408. if (*pszRemainingString != __TEXT('\0'))
  1409. {
  1410. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1411. {
  1412. goto error;
  1413. }
  1414. }
  1415. }
  1416. }
  1417. delete [] pszString;
  1418. //mark date/time as valid...
  1419. m_bValidDateTime = TRUE;
  1420. return TRUE;
  1421. error:
  1422. //mark date/time as invalid...
  1423. ResetDate(TRUE);
  1424. //Tidy up
  1425. if (pszString)
  1426. delete [] pszString;
  1427. return FALSE;
  1428. }
  1429. //=============================================================================
  1430. // Checks for date in the following format...
  1431. // [yy]yy{/-.}[M]M{/-.}dd ->Has to be same separator!
  1432. // passes remaining string on to time parser if bCheckTimeAfter is set
  1433. //=============================================================================
  1434. BOOL CDateTimeParser::DateFormat14(const TCHAR *pszDateTime,
  1435. const TCHAR *pszDateSeparator,
  1436. BOOL bCheckTimeAfter)
  1437. {
  1438. //Copy of string which we can change...
  1439. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1440. if (!pszString)
  1441. goto error;
  1442. lstrcpy(pszString, pszDateTime);
  1443. if (IsValidYearNumber(pszString, pszDateSeparator, FALSE) != ok)
  1444. goto error;
  1445. if (IsValidMonthNumber(NULL, pszDateSeparator) != ok)
  1446. goto error;
  1447. if (IsValidDayNumber(NULL, __TEXT(" ")) != ok)
  1448. goto error;
  1449. if (bCheckTimeAfter)
  1450. {
  1451. //Get the remaining string
  1452. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1453. if (pszRemainingString)
  1454. {
  1455. //Skip white space
  1456. while (*pszRemainingString == __TEXT(' '))
  1457. pszRemainingString++;
  1458. //if we are not at the end of the string pass on to the time
  1459. //parser
  1460. if (*pszRemainingString != __TEXT('\0'))
  1461. {
  1462. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1463. {
  1464. goto error;
  1465. }
  1466. }
  1467. }
  1468. }
  1469. delete [] pszString;
  1470. //mark date/time as valid...
  1471. m_bValidDateTime = TRUE;
  1472. return TRUE;
  1473. error:
  1474. //mark date/time as invalid...
  1475. ResetDate(TRUE);
  1476. //Tidy up
  1477. if (pszString)
  1478. delete [] pszString;
  1479. return FALSE;
  1480. }
  1481. //=============================================================================
  1482. // Checks for date in the following format...
  1483. // [yy]yyMMdd
  1484. // yyyy[MM[dd]]
  1485. // passes remaining string on to time parser if bCheckTimeAfter is set
  1486. //=============================================================================
  1487. BOOL CDateTimeParser::DateFormat15(const TCHAR *pszDateTime,
  1488. BOOL bCheckTimeAfter)
  1489. {
  1490. //Copy of string which we can change...
  1491. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1492. if (!pszString)
  1493. goto error;
  1494. lstrcpy(pszString, pszDateTime);
  1495. if (IsValidYearMonthDayNumber(pszString) != ok)
  1496. goto error;
  1497. if (bCheckTimeAfter)
  1498. {
  1499. //Get the remaining string
  1500. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1501. if (pszRemainingString)
  1502. {
  1503. //Skip white space
  1504. while (*pszRemainingString == __TEXT(' '))
  1505. pszRemainingString++;
  1506. //if we are not at the end of the string pass on to the time
  1507. //parser
  1508. if (*pszRemainingString != __TEXT('\0'))
  1509. {
  1510. if (!CheckTimeFormat(pszRemainingString, FALSE))
  1511. {
  1512. goto error;
  1513. }
  1514. }
  1515. }
  1516. }
  1517. delete [] pszString;
  1518. //mark date/time as valid...
  1519. m_bValidDateTime = TRUE;
  1520. return TRUE;
  1521. error:
  1522. //mark date/time as invalid...
  1523. ResetDate(TRUE);
  1524. //Tidy up
  1525. if (pszString)
  1526. delete [] pszString;
  1527. return FALSE;
  1528. }
  1529. //=============================================================================
  1530. // Checks for time in the following format...
  1531. // hh[ ]{AP}M
  1532. // passes remaining string on to date parser if bCheckDateAfter is set
  1533. //=============================================================================
  1534. BOOL CDateTimeParser::TimeFormat1(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1535. {
  1536. //Copy of string which we can change...
  1537. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1],
  1538. *pszAP = AllocAmPm();
  1539. if (!pszString || !pszAP)
  1540. goto error;
  1541. lstrcpy(pszString, pszDateTime);
  1542. if (IsValidHourNumber(pszString, pszAP) != ok)
  1543. goto error;
  1544. if (IsValidAmPmString(NULL, __TEXT(" "), m_pszAmPm) != ok)
  1545. goto error;
  1546. if (bCheckDateAfter)
  1547. {
  1548. //Get the remaining string
  1549. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1550. if (pszRemainingString)
  1551. {
  1552. //Skip white space
  1553. while (*pszRemainingString == __TEXT(' '))
  1554. pszRemainingString++;
  1555. //if we are not at the end of the string pass on to the date
  1556. //parser
  1557. if (*pszRemainingString != __TEXT('\0'))
  1558. {
  1559. if (!CheckDateFormat(pszRemainingString, FALSE))
  1560. {
  1561. goto error;
  1562. }
  1563. }
  1564. }
  1565. }
  1566. delete [] pszString;
  1567. delete [] pszAP;
  1568. //mark date/time as valid...
  1569. m_bValidDateTime = TRUE;
  1570. return TRUE;
  1571. error:
  1572. //mark date/time as invalid...
  1573. ResetTime(TRUE);
  1574. //Tidy up
  1575. if (pszString)
  1576. delete [] pszString;
  1577. if (pszAP)
  1578. delete [] pszAP;
  1579. return FALSE;
  1580. }
  1581. //=============================================================================
  1582. // Checks for time in the following format...
  1583. // hh:mm
  1584. // passes remaining string on to date parser if bCheckDateAfter is set
  1585. //=============================================================================
  1586. BOOL CDateTimeParser::TimeFormat2(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1587. {
  1588. //Copy of string which we can change...
  1589. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1590. if (!pszString)
  1591. goto error;
  1592. lstrcpy(pszString, pszDateTime);
  1593. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1594. goto error;
  1595. if (IsValidMinuteNumber(NULL, __TEXT(" ")) != ok)
  1596. goto error;
  1597. if (bCheckDateAfter)
  1598. {
  1599. //Get the remaining string
  1600. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1601. if (pszRemainingString)
  1602. {
  1603. //Skip white space
  1604. while (*pszRemainingString == __TEXT(' '))
  1605. pszRemainingString++;
  1606. //if we are not at the end of the string pass on to the date
  1607. //parser
  1608. if (*pszRemainingString != __TEXT('\0'))
  1609. {
  1610. if (!CheckDateFormat(pszRemainingString, FALSE))
  1611. {
  1612. goto error;
  1613. }
  1614. }
  1615. }
  1616. }
  1617. delete [] pszString;
  1618. //mark date/time as valid...
  1619. m_bValidDateTime = TRUE;
  1620. return TRUE;
  1621. error:
  1622. //mark date/time as invalid...
  1623. ResetTime(TRUE);
  1624. //Tidy up
  1625. if (pszString)
  1626. delete [] pszString;
  1627. return FALSE;
  1628. }
  1629. //=============================================================================
  1630. // Checks for time in the following format...
  1631. // hh:mm[ ]{AP}M
  1632. // passes remaining string on to date parser if bCheckDateAfter is set
  1633. //=============================================================================
  1634. BOOL CDateTimeParser::TimeFormat3(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1635. {
  1636. //Copy of string which we can change...
  1637. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1],
  1638. *pszAP = AllocAmPm();
  1639. if (!pszString || !pszAP)
  1640. goto error;
  1641. lstrcpy(pszString, pszDateTime);
  1642. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1643. goto error;
  1644. if (IsValidMinuteNumber(NULL, pszAP) != ok)
  1645. goto error;
  1646. if (IsValidAmPmString(NULL, __TEXT(" "), m_pszAmPm) != ok)
  1647. goto error;
  1648. if (bCheckDateAfter)
  1649. {
  1650. //Get the remaining string
  1651. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1652. if (pszRemainingString)
  1653. {
  1654. //Skip white space
  1655. while (*pszRemainingString == __TEXT(' '))
  1656. pszRemainingString++;
  1657. //if we are not at the end of the string pass on to the date
  1658. //parser
  1659. if (*pszRemainingString != __TEXT('\0'))
  1660. {
  1661. if (!CheckDateFormat(pszRemainingString, FALSE))
  1662. {
  1663. goto error;
  1664. }
  1665. }
  1666. }
  1667. }
  1668. delete [] pszString;
  1669. delete [] pszAP;
  1670. //mark date/time as valid...
  1671. m_bValidDateTime = TRUE;
  1672. return TRUE;
  1673. error:
  1674. //mark date/time as invalid...
  1675. ResetTime(TRUE);
  1676. //Tidy up
  1677. if (pszString)
  1678. delete [] pszString;
  1679. if (pszAP)
  1680. delete [] pszAP;
  1681. return FALSE;
  1682. }
  1683. //=============================================================================
  1684. // Checks for time in the following format...
  1685. // hh:mm:ss
  1686. // passes remaining string on to date parser if bCheckDateAfter is set
  1687. //=============================================================================
  1688. BOOL CDateTimeParser::TimeFormat4(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1689. {
  1690. //Copy of string which we can change...
  1691. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1692. if (!pszString)
  1693. goto error;
  1694. lstrcpy(pszString, pszDateTime);
  1695. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1696. goto error;
  1697. if (IsValidMinuteNumber(NULL, __TEXT(":")) != ok)
  1698. goto error;
  1699. if (IsValidSecondNumber(NULL, __TEXT(" ")) != ok)
  1700. goto error;
  1701. if (bCheckDateAfter)
  1702. {
  1703. //Get the remaining string
  1704. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1705. if (pszRemainingString)
  1706. {
  1707. //Skip white space
  1708. while (*pszRemainingString == __TEXT(' '))
  1709. pszRemainingString++;
  1710. //if we are not at the end of the string pass on to the date
  1711. //parser
  1712. if (*pszRemainingString != __TEXT('\0'))
  1713. {
  1714. if (!CheckDateFormat(pszRemainingString, FALSE))
  1715. {
  1716. goto error;
  1717. }
  1718. }
  1719. }
  1720. }
  1721. delete [] pszString;
  1722. //mark date/time as valid...
  1723. m_bValidDateTime = TRUE;
  1724. return TRUE;
  1725. error:
  1726. //mark date/time as invalid...
  1727. ResetTime(TRUE);
  1728. //Tidy up
  1729. if (pszString)
  1730. delete [] pszString;
  1731. return FALSE;
  1732. }
  1733. //=============================================================================
  1734. // Checks for time in the following format...
  1735. // hh:mm:ss[ ]{AP}M
  1736. // passes remaining string on to date parser if bCheckDateAfter is set
  1737. //=============================================================================
  1738. BOOL CDateTimeParser::TimeFormat5(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1739. {
  1740. //Copy of string which we can change...
  1741. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1],
  1742. *pszAP = AllocAmPm();
  1743. if (!pszString || !pszAP)
  1744. goto error;
  1745. lstrcpy(pszString, pszDateTime);
  1746. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1747. goto error;
  1748. if (IsValidMinuteNumber(NULL, __TEXT(":")) != ok)
  1749. goto error;
  1750. if (IsValidSecondNumber(NULL, pszAP) != ok)
  1751. goto error;
  1752. if (IsValidAmPmString(NULL, __TEXT(" "), m_pszAmPm) != ok)
  1753. goto error;
  1754. if (bCheckDateAfter)
  1755. {
  1756. //Get the remaining string
  1757. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1758. if (pszRemainingString)
  1759. {
  1760. //Skip white space
  1761. while (*pszRemainingString == __TEXT(' '))
  1762. pszRemainingString++;
  1763. //if we are not at the end of the string pass on to the date
  1764. //parser
  1765. if (*pszRemainingString != __TEXT('\0'))
  1766. {
  1767. if (!CheckDateFormat(pszRemainingString, FALSE))
  1768. {
  1769. goto error;
  1770. }
  1771. }
  1772. }
  1773. }
  1774. delete [] pszString;
  1775. delete [] pszAP;
  1776. //mark date/time as valid...
  1777. m_bValidDateTime = TRUE;
  1778. return TRUE;
  1779. error:
  1780. //mark date/time as invalid...
  1781. ResetTime(TRUE);
  1782. //Tidy up
  1783. if (pszString)
  1784. delete [] pszString;
  1785. if (pszAP)
  1786. delete [] pszAP;
  1787. return FALSE;
  1788. }
  1789. //=============================================================================
  1790. // Checks for time in the following format...
  1791. // hh:mm:ss:uuu
  1792. // passes remaining string on to date parser if bCheckDateAfter is set
  1793. //=============================================================================
  1794. BOOL CDateTimeParser::TimeFormat6(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1795. {
  1796. //Copy of string which we can change...
  1797. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1798. if (!pszString)
  1799. goto error;
  1800. lstrcpy(pszString, pszDateTime);
  1801. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1802. goto error;
  1803. if (IsValidMinuteNumber(NULL, __TEXT(":")) != ok)
  1804. goto error;
  1805. if (IsValidSecondNumber(NULL, __TEXT(":")) != ok)
  1806. goto error;
  1807. if (IsValidColonMillisecond(NULL, __TEXT(" ")) != ok)
  1808. goto error;
  1809. if (bCheckDateAfter)
  1810. {
  1811. //Get the remaining string
  1812. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1813. if (pszRemainingString)
  1814. {
  1815. //Skip white space
  1816. while (*pszRemainingString == __TEXT(' '))
  1817. pszRemainingString++;
  1818. //if we are not at the end of the string pass on to the date
  1819. //parser
  1820. if (*pszRemainingString != __TEXT('\0'))
  1821. {
  1822. if (!CheckDateFormat(pszRemainingString, FALSE))
  1823. {
  1824. goto error;
  1825. }
  1826. }
  1827. }
  1828. }
  1829. delete [] pszString;
  1830. //mark date/time as valid...
  1831. m_bValidDateTime = TRUE;
  1832. return TRUE;
  1833. error:
  1834. //mark date/time as invalid...
  1835. ResetTime(TRUE);
  1836. //Tidy up
  1837. if (pszString)
  1838. delete [] pszString;
  1839. return FALSE;
  1840. }
  1841. //=============================================================================
  1842. // Checks for time in the following format...
  1843. // hh:mm:ss.[[u]u]u
  1844. // passes remaining string on to date parser if bCheckDateAfter is set
  1845. //=============================================================================
  1846. BOOL CDateTimeParser::TimeFormat7(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1847. {
  1848. //Copy of string which we can change...
  1849. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1];
  1850. if (!pszString)
  1851. goto error;
  1852. lstrcpy(pszString, pszDateTime);
  1853. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1854. goto error;
  1855. if (IsValidMinuteNumber(NULL, __TEXT(":")) != ok)
  1856. goto error;
  1857. if (IsValidSecondNumber(NULL, __TEXT(".")) != ok)
  1858. goto error;
  1859. if (IsValidDotMillisecond(NULL, __TEXT(" ")) != ok)
  1860. goto error;
  1861. if (bCheckDateAfter)
  1862. {
  1863. //Get the remaining string
  1864. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1865. if (pszRemainingString)
  1866. {
  1867. //Skip white space
  1868. while (*pszRemainingString == __TEXT(' '))
  1869. pszRemainingString++;
  1870. //if we are not at the end of the string pass on to the date
  1871. //parser
  1872. if (*pszRemainingString != __TEXT('\0'))
  1873. {
  1874. if (!CheckDateFormat(pszRemainingString, FALSE))
  1875. {
  1876. goto error;
  1877. }
  1878. }
  1879. }
  1880. }
  1881. delete [] pszString;
  1882. //mark date/time as valid...
  1883. m_bValidDateTime = TRUE;
  1884. return TRUE;
  1885. error:
  1886. //mark date/time as invalid...
  1887. ResetTime(TRUE);
  1888. //Tidy up
  1889. if (pszString)
  1890. delete [] pszString;
  1891. return FALSE;
  1892. }
  1893. //=============================================================================
  1894. // Checks for time in the following format...
  1895. // hh:mm:ss:uuu[ ]{AP}M
  1896. // passes remaining string on to date parser if bCheckDateAfter is set
  1897. //=============================================================================
  1898. BOOL CDateTimeParser::TimeFormat8(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1899. {
  1900. //Copy of string which we can change...
  1901. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1],
  1902. *pszAP = AllocAmPm();
  1903. if (!pszString || !pszAP)
  1904. goto error;
  1905. lstrcpy(pszString, pszDateTime);
  1906. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1907. goto error;
  1908. if (IsValidMinuteNumber(NULL, __TEXT(":")) != ok)
  1909. goto error;
  1910. if (IsValidSecondNumber(NULL, __TEXT(":")) != ok)
  1911. goto error;
  1912. if (IsValidColonMillisecond(NULL, pszAP) != ok)
  1913. goto error;
  1914. if (IsValidAmPmString(NULL, __TEXT(" "), m_pszAmPm) != ok)
  1915. goto error;
  1916. if (bCheckDateAfter)
  1917. {
  1918. //Get the remaining string
  1919. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1920. if (pszRemainingString)
  1921. {
  1922. //Skip white space
  1923. while (*pszRemainingString == __TEXT(' '))
  1924. pszRemainingString++;
  1925. //if we are not at the end of the string pass on to the date
  1926. //parser
  1927. if (*pszRemainingString != __TEXT('\0'))
  1928. {
  1929. if (!CheckDateFormat(pszRemainingString, FALSE))
  1930. {
  1931. goto error;
  1932. }
  1933. }
  1934. }
  1935. }
  1936. delete [] pszString;
  1937. delete [] pszAP;
  1938. //mark date/time as valid...
  1939. m_bValidDateTime = TRUE;
  1940. return TRUE;
  1941. error:
  1942. //mark date/time as invalid...
  1943. ResetTime(TRUE);
  1944. //Tidy up
  1945. if (pszString)
  1946. delete [] pszString;
  1947. if (pszAP)
  1948. delete [] pszAP;
  1949. return FALSE;
  1950. }
  1951. //=============================================================================
  1952. // Checks for time in the following format...
  1953. // hh:mm:ss.[[u]u]u[ ]{AP}M
  1954. // passes remaining string on to date parser if bCheckDateAfter is set
  1955. //=============================================================================
  1956. BOOL CDateTimeParser::TimeFormat9(const TCHAR *pszDateTime, BOOL bCheckDateAfter)
  1957. {
  1958. //Copy of string which we can change...
  1959. TCHAR *pszString = new TCHAR[lstrlen(pszDateTime) + 1],
  1960. *pszAP = AllocAmPm();
  1961. if (!pszString || !pszAP)
  1962. goto error;
  1963. lstrcpy(pszString, pszDateTime);
  1964. if (IsValidHourNumber(pszString, __TEXT(":")) != ok)
  1965. goto error;
  1966. if (IsValidMinuteNumber(NULL, __TEXT(":")) != ok)
  1967. goto error;
  1968. if (IsValidSecondNumber(NULL, __TEXT(".")) != ok)
  1969. goto error;
  1970. if (IsValidDotMillisecond(NULL, pszAP) != ok)
  1971. goto error;
  1972. if (IsValidAmPmString(NULL, __TEXT(" "), m_pszAmPm) != ok)
  1973. goto error;
  1974. if (bCheckDateAfter)
  1975. {
  1976. //Get the remaining string
  1977. TCHAR *pszRemainingString = _tcstok(NULL, __TEXT(""));
  1978. if (pszRemainingString)
  1979. {
  1980. //Skip white space
  1981. while (*pszRemainingString == __TEXT(' '))
  1982. pszRemainingString++;
  1983. //if we are not at the end of the string pass on to the date
  1984. //parser
  1985. if (*pszRemainingString != __TEXT('\0'))
  1986. {
  1987. if (!CheckDateFormat(pszRemainingString, FALSE))
  1988. {
  1989. goto error;
  1990. }
  1991. }
  1992. }
  1993. }
  1994. delete [] pszString;
  1995. delete [] pszAP;
  1996. //mark date/time as valid...
  1997. m_bValidDateTime = TRUE;
  1998. return TRUE;
  1999. error:
  2000. //mark date/time as invalid...
  2001. ResetTime(TRUE);
  2002. //Tidy up
  2003. if (pszString)
  2004. delete [] pszString;
  2005. if (pszAP)
  2006. delete [] pszAP;
  2007. return FALSE;
  2008. }
  2009. //=========================================================================
  2010. //Check the month.
  2011. //=========================================================================
  2012. int CDateTimeParser::IsValidMonthString(TCHAR *pszString,
  2013. const TCHAR *pszSeparator,
  2014. TCHAR *pszFullMonth[],
  2015. TCHAR *pszShortMonth[])
  2016. {
  2017. BOOL bOK = FALSE;
  2018. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2019. if (pszToken == NULL)
  2020. return nothingLeft;
  2021. //Skip spaces
  2022. while (*pszToken == __TEXT(' '))
  2023. pszToken++;
  2024. if (*pszToken == __TEXT('\0'))
  2025. return nothingLeft;
  2026. //Work through the possible months...
  2027. for (int i = 0; i < 12; i++)
  2028. {
  2029. if ((lstrcmpi(pszShortMonth[i], pszToken) == 0) ||
  2030. (lstrcmpi(pszFullMonth[i], pszToken) == 0))
  2031. {
  2032. //That is valid...
  2033. bOK = TRUE;
  2034. break;
  2035. }
  2036. }
  2037. //Is this a valid month?
  2038. if (!bOK)
  2039. {
  2040. return failed;
  2041. }
  2042. m_nMonth = i + 1;
  2043. return ok;
  2044. }
  2045. //=========================================================================
  2046. //Check the month as a number.
  2047. //=========================================================================
  2048. int CDateTimeParser::IsValidMonthNumber(TCHAR *pszString,
  2049. const TCHAR *pszSeparator)
  2050. {
  2051. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2052. if (pszToken == NULL)
  2053. return nothingLeft;
  2054. //Skip spaces...
  2055. while (*pszToken == __TEXT(' '))
  2056. pszToken++;
  2057. if (*pszToken == __TEXT('\0'))
  2058. return nothingLeft;
  2059. //Check it is digits...
  2060. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2061. {
  2062. if (!isdigit(pszToken[i]))
  2063. return failed;
  2064. }
  2065. //convert it to a number
  2066. i = _ttoi(pszToken);
  2067. if ((i < 1) || (i > 12))
  2068. return failed;
  2069. m_nMonth = (unsigned char)i;
  2070. return ok;
  2071. }
  2072. //=========================================================================
  2073. //Check the day.
  2074. //=========================================================================
  2075. int CDateTimeParser::IsValidDayNumber(TCHAR *pszString,
  2076. const TCHAR *pszSeparator)
  2077. {
  2078. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2079. if (pszToken == NULL)
  2080. return nothingLeft;
  2081. //Skip spaces...
  2082. while (*pszToken == __TEXT(' '))
  2083. pszToken++;
  2084. if (*pszToken == __TEXT('\0'))
  2085. return nothingLeft;
  2086. //Check it is digits...
  2087. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2088. {
  2089. if (!isdigit(pszToken[i]))
  2090. return failed;
  2091. }
  2092. //convert it to a number
  2093. i = _ttoi(pszToken);
  2094. if ((i < 1) || (i > 31))
  2095. return failed;
  2096. m_nDay = (unsigned char)i;
  2097. return ok;
  2098. }
  2099. //=========================================================================
  2100. //Check the year.
  2101. //=========================================================================
  2102. int CDateTimeParser::IsValidYearNumber(TCHAR *pszString,
  2103. const TCHAR *pszSeparator,
  2104. BOOL bFourDigitsOnly)
  2105. {
  2106. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2107. if (pszToken == NULL)
  2108. return nothingLeft;
  2109. //Skip space
  2110. while (*pszToken == __TEXT(' '))
  2111. pszToken++;
  2112. if (*pszToken == __TEXT('\0'))
  2113. return nothingLeft;
  2114. //Check it is digits...
  2115. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2116. {
  2117. if (!isdigit(pszToken[i]))
  2118. return failed;
  2119. }
  2120. //Needs to be 2 or 4 digits
  2121. if ((i != 2) && (i != 4))
  2122. return failed;
  2123. if ((i == 2) && bFourDigitsOnly)
  2124. return failed;
  2125. //convert it to a number
  2126. m_nYear = _ttoi(pszToken);
  2127. //Do any conversions for 2 digit years...
  2128. if ((i == 2) && (m_nYear < 50))
  2129. {
  2130. m_nYear += 2000;
  2131. }
  2132. else if (i == 2)
  2133. {
  2134. m_nYear += 1900;
  2135. }
  2136. return ok;
  2137. }
  2138. //=========================================================================
  2139. //Check the hours.
  2140. //=========================================================================
  2141. int CDateTimeParser::IsValidHourNumber(TCHAR *pszString,
  2142. const TCHAR *pszSeparator)
  2143. {
  2144. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2145. if (pszToken == NULL)
  2146. return nothingLeft;
  2147. //Skip space
  2148. while (*pszToken == __TEXT(' '))
  2149. pszToken++;
  2150. if (*pszToken == __TEXT('\0'))
  2151. return nothingLeft;
  2152. //Check it is digits...
  2153. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2154. {
  2155. if (!isdigit(pszToken[i]))
  2156. return failed;
  2157. }
  2158. //convert it to a number
  2159. i = _ttoi(pszToken);
  2160. //Validate a little
  2161. if ((i < 0) || (i > 23))
  2162. return failed;
  2163. m_nHours = (unsigned char)i;
  2164. return ok;
  2165. }
  2166. //=========================================================================
  2167. //Check the Minutes.
  2168. //=========================================================================
  2169. int CDateTimeParser::IsValidMinuteNumber(TCHAR *pszString,
  2170. const TCHAR *pszSeparator)
  2171. {
  2172. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2173. if (pszToken == NULL)
  2174. return nothingLeft;
  2175. if (*pszToken == __TEXT('\0'))
  2176. return nothingLeft;
  2177. //Check it is digits...
  2178. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2179. {
  2180. if (!isdigit(pszToken[i]))
  2181. return failed;
  2182. }
  2183. //convert it to a number
  2184. i = _ttoi(pszToken);
  2185. //Validate a little
  2186. if ((i < 0) || (i > 59))
  2187. return failed;
  2188. m_nMinutes = (unsigned char)i;
  2189. return ok;
  2190. }
  2191. //=========================================================================
  2192. //Check the Seconds.
  2193. //=========================================================================
  2194. int CDateTimeParser::IsValidSecondNumber(TCHAR *pszString,
  2195. const TCHAR *pszSeparator)
  2196. {
  2197. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2198. if (pszToken == NULL)
  2199. return nothingLeft;
  2200. if (*pszToken == __TEXT('\0'))
  2201. return nothingLeft;
  2202. //Check it is digits...
  2203. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2204. {
  2205. if (!isdigit(pszToken[i]))
  2206. return failed;
  2207. }
  2208. //convert it to a number
  2209. i = _ttoi(pszToken);
  2210. //Validate a little
  2211. if ((i < 0) || (i > 59))
  2212. return failed;
  2213. m_nSeconds = (unsigned char)i;
  2214. return ok;
  2215. }
  2216. //=========================================================================
  2217. //Check the milliseconds. This is a colon prefix version
  2218. //=========================================================================
  2219. int CDateTimeParser::IsValidColonMillisecond(TCHAR *pszString,
  2220. const TCHAR *pszSeparator)
  2221. {
  2222. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2223. if (pszToken == NULL)
  2224. return nothingLeft;
  2225. if (*pszToken == __TEXT('\0'))
  2226. return nothingLeft;
  2227. //Check it is digits...
  2228. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2229. {
  2230. if (!isdigit(pszToken[i]))
  2231. return failed;
  2232. }
  2233. //convert it to a number
  2234. i = _ttoi(pszToken);
  2235. //Validate a little
  2236. if ((i < 0) || (i > 999))
  2237. return failed;
  2238. //milliseconds to microseconds
  2239. m_nMicroseconds = i * 1000;
  2240. return ok;
  2241. }
  2242. //=========================================================================
  2243. //Check the milliseconds. This is a dot prefix (decimal) version
  2244. //=========================================================================
  2245. int CDateTimeParser::IsValidDotMillisecond(TCHAR *pszString,
  2246. const TCHAR *pszSeparator)
  2247. {
  2248. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2249. if (pszToken == NULL)
  2250. return nothingLeft;
  2251. if (*pszToken == __TEXT('\0'))
  2252. return nothingLeft;
  2253. //Check it is digits...
  2254. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2255. {
  2256. if (!isdigit(pszToken[i]))
  2257. return failed;
  2258. }
  2259. //convert it to a number
  2260. int nVal = _ttoi(pszToken);
  2261. //Convert the value into thousandths of a second.
  2262. if (i < 3)
  2263. nVal *= 10;
  2264. if (i < 2)
  2265. nVal *= 10;
  2266. //Validate a little
  2267. if ((nVal < 0) || (nVal > 999))
  2268. return failed;
  2269. //milliseconds to microseconds
  2270. m_nMicroseconds = nVal * 1000;
  2271. return ok;
  2272. }
  2273. //=========================================================================
  2274. //Check the AM/PM part.
  2275. //=========================================================================
  2276. int CDateTimeParser::IsValidAmPmString(TCHAR *pszString,
  2277. const TCHAR *pszSeparator,
  2278. TCHAR *pszAmPm[])
  2279. {
  2280. TCHAR *pszToken = _tcstok(pszString, pszSeparator);
  2281. if (pszToken == NULL)
  2282. return nothingLeft;
  2283. BOOL bOK = FALSE;
  2284. //Skip spaces
  2285. while (*pszToken == __TEXT(' '))
  2286. {
  2287. pszToken++;
  2288. }
  2289. if (*pszToken == __TEXT('\0'))
  2290. return nothingLeft;
  2291. //Check it is digits...
  2292. //Work through the possible AM/PM items...
  2293. for (int i = 0; i < 2; i++)
  2294. {
  2295. if (lstrcmpi(pszAmPm[i], pszToken) == 0)
  2296. {
  2297. //That is valid...
  2298. bOK = TRUE;
  2299. break;
  2300. }
  2301. }
  2302. if (!bOK)
  2303. return failed;
  2304. if (i == 1)
  2305. {
  2306. //PM adds 12 hours
  2307. m_nHours += 12;
  2308. }
  2309. else if (m_nHours == 12)
  2310. {
  2311. //for AM, 12 o'clock equals 0 in 24 hour time.
  2312. m_nHours = 0;
  2313. }
  2314. //Does this make the number too large now?
  2315. if (m_nHours > 23)
  2316. return failed;
  2317. return ok;
  2318. }
  2319. //=========================================================================
  2320. // Check the purely numeric year, month, day format...
  2321. // [yy]yyMMdd
  2322. // yyyy[MMdd]
  2323. // NOTE: 6 and 8 digit dates are always ymd.
  2324. // 4 digits is always year
  2325. //=========================================================================
  2326. int CDateTimeParser::IsValidYearMonthDayNumber(TCHAR *pszString)
  2327. {
  2328. int j;
  2329. TCHAR *pszToken = _tcstok(pszString, __TEXT(" "));
  2330. if (pszToken == NULL)
  2331. return nothingLeft;
  2332. BOOL bOK = FALSE;
  2333. //Skip spaces
  2334. while (*pszToken == __TEXT(' '))
  2335. {
  2336. pszToken++;
  2337. }
  2338. if (*pszToken == __TEXT('\0'))
  2339. return nothingLeft;
  2340. //Check it is digits...
  2341. for (int i = 0; pszToken[i] != __TEXT('\0'); i++)
  2342. {
  2343. if (!isdigit(pszToken[i]))
  2344. return failed;
  2345. }
  2346. //We support 4, 6 and 8 digits
  2347. if ((i != 4) && (i != 6) && (i != 8))
  2348. return failed;
  2349. //4 digit years...
  2350. if ((i == 4) || (i == 8))
  2351. {
  2352. m_nYear = 0;
  2353. for (j = 0;j < 4; j++)
  2354. {
  2355. m_nYear *= 10;
  2356. m_nYear += (*pszToken - '0');
  2357. pszToken++;
  2358. }
  2359. }
  2360. else
  2361. {
  2362. //2 digit years
  2363. m_nYear = 0;
  2364. for (j = 0;j < 2; j++)
  2365. {
  2366. m_nYear *= 10;
  2367. m_nYear += (*pszToken - '0');
  2368. pszToken++;
  2369. }
  2370. if (m_nYear >= 50)
  2371. {
  2372. m_nYear += 1900;
  2373. }
  2374. else
  2375. {
  2376. m_nYear += 2000;
  2377. }
  2378. }
  2379. //If we have month and year...
  2380. if (i > 4)
  2381. {
  2382. m_nMonth = ((*pszToken - __TEXT('0')) * 10) + (*(pszToken+1) - __TEXT('0'));
  2383. pszToken += 2;
  2384. if ((m_nMonth < 0) && (m_nMonth > 12))
  2385. return failed;
  2386. m_nDay = ((*pszToken - __TEXT('0')) * 10) + (*(pszToken+1) - __TEXT('0'));
  2387. if ((m_nDay < 0) && (m_nDay > 31))
  2388. return failed;
  2389. }
  2390. return ok;
  2391. }
  2392. int CDateTimeParser::FillDMTF(WCHAR* pwszBuffer)
  2393. {
  2394. if(!IsValidDateTime())
  2395. return failed;
  2396. swprintf(pwszBuffer, L"%04d%02d%02d%02d%02d%02d.%06d%c%03d",
  2397. m_nYear, m_nMonth, m_nDay, m_nHours, m_nMinutes, m_nSeconds,
  2398. m_nMicroseconds,
  2399. ((m_nUTC >= 0)?L'+':L'-'),
  2400. ((m_nUTC >= 0)?m_nUTC:-m_nUTC));
  2401. return ok;
  2402. }
  2403. BOOL NormalizeCimDateTime(
  2404. IN LPCWSTR pszSrc,
  2405. OUT BSTR *strAdjusted
  2406. )
  2407. {
  2408. int yr = 0, mo = 0, da = 0, hh = 0, mm = 0, ss = 0, micro = 0, utcOffset = 0;
  2409. wchar_t wcSign = 0;
  2410. if (pszSrc == 0 || strAdjusted == 0)
  2411. return FALSE;
  2412. // Parse DMTF format.
  2413. // yyyymmddhhmmss.mmmmmmsuuu
  2414. // =========================
  2415. swscanf(pszSrc, L"%04d%02d%02d%02d%02d%02d.%06d%C%03d",
  2416. &yr, &mo, &da, &hh, &mm, &ss, &micro, &wcSign, &utcOffset
  2417. );
  2418. if (wcSign == 0)
  2419. return FALSE;
  2420. // Convert to Win32 time for adjustment.
  2421. // =====================================
  2422. SYSTEMTIME st;
  2423. FILETIME ft;
  2424. st.wYear = WORD(yr);
  2425. st.wMonth = WORD(mo);
  2426. st.wDay = WORD(da);
  2427. st.wDayOfWeek = 0;
  2428. st.wHour = WORD(hh);
  2429. st.wMinute = WORD(mm);
  2430. st.wSecond = WORD(ss);
  2431. st.wMilliseconds = WORD(micro / 1000);
  2432. BOOL bRes = SystemTimeToFileTime(&st, &ft);
  2433. if (!bRes)
  2434. return bRes;
  2435. ULARGE_INTEGER ul;
  2436. ul.HighPart = ft.dwHighDateTime;
  2437. ul.LowPart = ft.dwLowDateTime;
  2438. unsigned __int64 u64 = ul.QuadPart;
  2439. // Adjust rest of time so that we normalize to UTC
  2440. if (wcSign == L'-')
  2441. u64 += (unsigned __int64) 600000000 * (unsigned __int64) utcOffset;
  2442. else
  2443. u64 -= (unsigned __int64) 600000000 * (unsigned __int64) utcOffset;
  2444. ul.QuadPart = u64;
  2445. ft.dwHighDateTime = ul.HighPart;
  2446. ft.dwLowDateTime = ul.LowPart;
  2447. bRes = FileTimeToSystemTime(&ft, &st);
  2448. if (!bRes)
  2449. return bRes;
  2450. wchar_t buf[128];
  2451. swprintf(buf, L"%04d%02d%02d%02d%02d%02d.%06d+000",
  2452. st.wYear, st.wMonth, st.wDay,
  2453. st.wHour, st.wMinute, st.wSecond, st.wMilliseconds*1000
  2454. );
  2455. *strAdjusted = SysAllocString(buf);
  2456. if (*strAdjusted == 0)
  2457. return FALSE;
  2458. return TRUE;
  2459. }