RFCDate.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include "main.h"
  2. #include "RFCDate.h"
  3. #include <strsafe.h>
  4. void MakeDateString(__time64_t convertTime, wchar_t *date_str, size_t len)
  5. {
  6. SYSTEMTIME sysTime = {0};
  7. tm *newtime = _localtime64(&convertTime);
  8. sysTime.wYear = newtime->tm_year + 1900;
  9. sysTime.wMonth = newtime->tm_mon + 1;
  10. sysTime.wDayOfWeek = newtime->tm_wday;
  11. sysTime.wDay = newtime->tm_mday;
  12. sysTime.wHour = newtime->tm_hour;
  13. sysTime.wMinute = newtime->tm_min;
  14. sysTime.wSecond = newtime->tm_sec;
  15. GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &sysTime, NULL, date_str, (int)len);
  16. }
  17. void MakeRFCDateString(__time64_t convertTime, wchar_t *data_str, size_t len)
  18. {
  19. SYSTEMTIME sysTime = {0};
  20. tm *newtime = _gmtime64(&convertTime);
  21. sysTime.wYear = newtime->tm_year + 1900;
  22. sysTime.wMonth = newtime->tm_mon + 1;
  23. sysTime.wDayOfWeek = newtime->tm_wday;
  24. sysTime.wDay = newtime->tm_mday;
  25. sysTime.wHour = newtime->tm_hour;
  26. sysTime.wMinute = newtime->tm_min;
  27. sysTime.wSecond = newtime->tm_sec;
  28. wchar_t rfcDate[64] = {0}, rfcTime[64] = {0};
  29. GetDateFormat(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, &sysTime, L"ddd',' d MMM yyyy ", rfcDate, 64);
  30. GetTimeFormat(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, &sysTime, L"HH':'mm':'ss 'GMT'", rfcTime, 64);
  31. StringCchPrintf(data_str,len,L"%s%s",rfcDate,rfcTime);
  32. }
  33. static int getMonthOfYear(const wchar_t *str);
  34. static int validateTime(struct tm *tmloc, int gmoffset);
  35. static const wchar_t *getNextField(const wchar_t *pos);
  36. static int getGMOffset(const wchar_t *str);
  37. enum
  38. {
  39. DAY_OF_MONTH = 0,
  40. MONTH_OF_YEAR,
  41. YEAR,
  42. TIME,
  43. TIMEZONE,
  44. DATE_END
  45. };
  46. __time64_t MakeRFCDate(const wchar_t *date)
  47. {
  48. __time64_t result = 0;
  49. const wchar_t *pos = date;
  50. tm tmloc = {0};
  51. const wchar_t *strmin;
  52. const wchar_t *strsec;
  53. int gmoffset = 1;
  54. int state = DAY_OF_MONTH;
  55. tzset();
  56. /* skip weekday if present */
  57. while (pos && *pos && !iswdigit(*pos)) pos++;
  58. do
  59. {
  60. switch (state)
  61. {
  62. case DAY_OF_MONTH:
  63. tmloc.tm_mday = _wtoi(pos);
  64. break;
  65. case MONTH_OF_YEAR:
  66. tmloc.tm_mon = getMonthOfYear(pos);
  67. break;
  68. case YEAR:
  69. {
  70. /* TODO: we're only accepting 4-digit dates...*/
  71. const wchar_t *test = pos; int numDigits = 0;
  72. while (iswdigit(*test) && *test) { test++; numDigits++; }
  73. if (numDigits == 2) // let's hope we never have 2 digit years!
  74. tmloc.tm_year = _wtoi(pos) + 100; // assume 2 digit years are 20xx
  75. else
  76. tmloc.tm_year = _wtoi(pos) - 1900;
  77. }
  78. break;
  79. case TIME:
  80. strmin = wcschr(pos, L':');
  81. strsec = strmin ? wcschr(strmin + 1, L':') : 0;
  82. tmloc.tm_hour = _wtoi(pos);
  83. if (!strmin) return _time64(0);
  84. tmloc.tm_min = _wtoi(strmin + 1);
  85. if (!strsec) return _time64(0);
  86. tmloc.tm_sec = _wtoi(strsec + 1);
  87. break;
  88. case TIMEZONE:
  89. gmoffset = getGMOffset(pos);
  90. break;
  91. case DATE_END:
  92. pos = 0;
  93. break;
  94. }
  95. state++;
  96. }
  97. while ((pos = getNextField(pos)));
  98. tmloc.tm_isdst = 0; //_daylight;
  99. if (validateTime(&tmloc, gmoffset))
  100. {
  101. result = _mktime64(&tmloc) - _timezone;
  102. //if (_daylight)
  103. }
  104. return result;
  105. }
  106. const wchar_t *getNextField(const wchar_t *pos)
  107. {
  108. if (!pos)
  109. return 0;
  110. while (pos && *pos && !iswspace(*pos)) pos++;
  111. while (pos && *pos && iswspace(*pos)) pos++;
  112. return ((pos && *pos) ? pos : 0);
  113. }
  114. int validateTime(struct tm *tmloc, int gmoffset)
  115. {
  116. int result = 1;
  117. if (tmloc->tm_mday < 1 || tmloc->tm_mday > 31 ||
  118. tmloc->tm_mon < 0 || tmloc->tm_mon > 11 ||
  119. tmloc->tm_year < 0 || tmloc->tm_year > 2000 ||
  120. tmloc->tm_hour < 0 || tmloc->tm_hour > 23 ||
  121. tmloc->tm_min < 0 || tmloc->tm_min > 59 ||
  122. tmloc->tm_sec < 0 || tmloc->tm_sec > 59 ||
  123. gmoffset == 1)
  124. result = 0;
  125. return result;
  126. }
  127. int getMonthOfYear(const wchar_t *str)
  128. {
  129. int mon = -1;
  130. /* This is not the most efficient way to determine
  131. the month (we could use integer comparisons, for instance)
  132. but I don't think this will be a performance bottleneck :)
  133. */
  134. if (!wcsnicmp(str, L"Jan", 3))
  135. mon = 0;
  136. else if (!wcsnicmp(str, L"Feb", 3))
  137. mon = 1;
  138. else if (!wcsnicmp(str, L"Mar", 3))
  139. mon = 2;
  140. else if (!wcsnicmp(str, L"Apr", 3))
  141. mon = 3;
  142. else if (!wcsnicmp(str, L"May", 3))
  143. mon = 4;
  144. else if (!wcsnicmp(str, L"Jun", 3))
  145. mon = 5;
  146. else if (!wcsnicmp(str, L"Jul", 3))
  147. mon = 6;
  148. else if (!wcsnicmp(str, L"Aug", 3))
  149. mon = 7;
  150. else if (!wcsnicmp(str, L"Sep", 3))
  151. mon = 8;
  152. else if (!wcsnicmp(str, L"Oct", 3))
  153. mon = 9;
  154. else if (!wcsnicmp(str, L"Nov", 3))
  155. mon = 10;
  156. else if (!wcsnicmp(str, L"Dec", 3))
  157. mon = 11;
  158. return mon;
  159. }
  160. int getGMOffset(const wchar_t *str)
  161. {
  162. int secs = 0;
  163. /* See note in getMonthOfYear() */
  164. if (!wcsnicmp(str, L"UT", 2) || !wcsnicmp(str, L"GMT", 3))
  165. secs = 0;
  166. else if (!wcsnicmp(str, L"EDT", 3))
  167. secs = -4 * 3600;
  168. else if (!wcsnicmp(str, L"PST", 3))
  169. secs = -8 * 3600;
  170. else if (!wcsnicmp(str, L"EST", 3) || !wcsnicmp(str, L"CDT", 3))
  171. secs = -5 * 3600;
  172. else if (!wcsnicmp(str, L"MST", 3) || !wcsnicmp(str, L"PDT", 3))
  173. secs = -7 * 3600;
  174. else if (!wcsnicmp(str, L"CST", 3) || !wcsnicmp(str, L"MDT", 3))
  175. secs = -6 * 3600;
  176. else if ( (str[0] == L'+' || str[0] == L'-') &&
  177. iswdigit(str[1]) && iswdigit(str[2]) &&
  178. iswdigit(str[3]) && iswdigit(str[4]))
  179. {
  180. secs = 3600 * (10 * (str[1] - 48) + str[2] - 48);
  181. secs += 60 * (10 * (str[3] - 48) + str[4] - 48);
  182. if (str[0] == L'-')
  183. secs = -secs;
  184. }
  185. else
  186. secs = 1;
  187. return secs;
  188. }