Advertisement
Guest User

Windows implementation for strptime()

a guest
May 22nd, 2014
1,631
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.09 KB | None | 0 0
  1. ===================================================================
  2. File: timesupport.h
  3. ===================================================================
  4.  
  5. // Copyright 2009 Google Inc.
  6. //
  7. // Licensed under the Apache License, Version 2.0 (the "License");
  8. // you may not use this file except in compliance with the License.
  9. // You may obtain a copy of the License at
  10. //
  11. //      http://www.apache.org/licenses/LICENSE-2.0
  12. //
  13. // Unless required by applicable law or agreed to in writing, software
  14. // distributed under the License is distributed on an "AS IS" BASIS,
  15. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. // See the License for the specific language governing permissions and
  17. // limitations under the License.
  18.  
  19.  
  20. // This files includes functions to support time related operations.
  21. // It defines common functions, which are only available on platforms.
  22. // It also provides functions to parse RFC times.
  23.  
  24. #ifndef COMMON_TIMESUPPORT_H__
  25. #define COMMON_TIMESUPPORT_H__
  26.  
  27. #include <time.h>
  28. #include <string>
  29.  
  30. #ifdef WIN32
  31. // Convert a string representation time to a time tm structure.
  32. // It is the conversion function of strftime().
  33. // Linux provides this function.
  34. char *strptime(const char *buf, const char *fmt, struct tm *tm);
  35. #endif
  36.  
  37. #if defined(__linux__) || defined(__unix__)
  38. // Convert GMT time to UTC time value.
  39. // It is like mktime(), but interprets the fields as GMT rather than local.
  40. // This is the inverse of gmtime().
  41. // Windows provides this function.
  42. time_t _mkgmtime(const struct tm *tm);
  43. #endif
  44.  
  45. // Tries various rfc&#039;s to convert a buffer to a struct tm.
  46. // Warning: this function only handles a few cases and completely ignores
  47. // time zones!
  48. bool ParseRfcTime(const char* buf, struct tm *tm);
  49.  
  50. // Covert the time to W3C Datetime formats.
  51. // See http://www.w3.org/TR/NOTE-datetime
  52. const std::string FormatW3CTime(const time_t &time);
  53.  
  54. // A helper method used to format HttpDate.
  55. std::string FormatHttpDate(time_t t);
  56.  
  57. ===================================================================
  58. File: timesupport.cc
  59. ===================================================================
  60. // Copyright 2009 Google Inc.
  61. //
  62. // Licensed under the Apache License, Version 2.0 (the "License");
  63. // you may not use this file except in compliance with the License.
  64. // You may obtain a copy of the License at
  65. //
  66. //      http://www.apache.org/licenses/LICENSE-2.0
  67. //
  68. // Unless required by applicable law or agreed to in writing, software
  69. // distributed under the License is distributed on an "AS IS" BASIS,
  70. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  71. // See the License for the specific language governing permissions and
  72. // limitations under the License.
  73.  
  74.  
  75. #include "stdafx.h"
  76.  
  77. #include "timesupport.h"
  78.  
  79. #include <time.h>
  80. #include <ctype.h>
  81. #include <string.h>
  82.  
  83. #ifdef WIN32
  84. // Implement strptime under windows
  85. static const char* kWeekFull[] = {
  86.   "Sunday", "Monday", "Tuesday", "Wednesday",
  87.   "Thursday", "Friday", "Saturday"
  88. };
  89.  
  90. static const char* kWeekAbbr[] = {
  91.   "Sun", "Mon", "Tue", "Wed",
  92.   "Thu", "Fri", "Sat"
  93. };
  94.  
  95. static const char* kMonthFull[] = {
  96.   "January", "February", "March", "April", "May", "June",
  97.   "July", "August", "September", "October", "November", "December"
  98. };
  99.  
  100. static const char* kMonthAbbr[] = {
  101.   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  102.   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  103. };
  104.  
  105. static const char* _parse_num(const char* s, int low, int high, int* value) {
  106.   const char* p = s;
  107.   for (*value = 0; *p != NULL && isdigit(*p); ++p) {
  108.     *value = (*value) * 10 + static_cast<int>(*p) - static_cast<int>(&#039;0&#039;);
  109.   }
  110.  
  111.   if (p == s || *value < low || *value > high) return NULL;
  112.   return p;
  113. }
  114.  
  115. static char* _strptime(const char *s, const char *format, struct tm *tm) {
  116.   while (*format != NULL && *s != NULL) {
  117.     if (*format != &#039;%&#039;) {
  118.       if (*s != *format) return NULL;
  119.  
  120.       ++format;
  121.       ++s;
  122.       continue;
  123.     }
  124.  
  125.     ++format;
  126.     int len = 0;
  127.     switch (*format) {
  128.       // weekday name.
  129.       case &#039;a&#039;:
  130.       case &#039;A&#039;:
  131.         tm->tm_wday = -1;
  132.         for (int i = 0; i < 7; ++i) {
  133.           len = static_cast<int>(strlen(kWeekAbbr[i]));
  134.           if (strnicmp(kWeekAbbr[i], s, len) == 0) {
  135.             tm->tm_wday = i;
  136.             break;
  137.           }
  138.  
  139.           len = static_cast<int>(strlen(kWeekFull[i]));
  140.           if (strnicmp(kWeekFull[i], s, len) == 0) {
  141.             tm->tm_wday = i;
  142.             break;
  143.           }
  144.         }
  145.         if (tm->tm_wday == -1) return NULL;
  146.         s += len;
  147.         break;
  148.      
  149.       // month name.
  150.       case &#039;b&#039;:
  151.       case &#039;B&#039;:
  152.       case &#039;h&#039;:
  153.         tm->tm_mon = -1;
  154.         for (int i = 0; i < 12; ++i) {
  155.           len = static_cast<int>(strlen(kMonthAbbr[i]));
  156.           if (strnicmp(kMonthAbbr[i], s, len) == 0) {
  157.             tm->tm_mon = i;
  158.             break;
  159.           }
  160.  
  161.           len = static_cast<int>(strlen(kMonthFull[i]));
  162.           if (strnicmp(kMonthFull[i], s, len) == 0) {
  163.             tm->tm_mon = i;
  164.             break;
  165.           }
  166.         }
  167.         if (tm->tm_mon == -1) return NULL;
  168.         s += len;
  169.         break;
  170.  
  171.       // month [1, 12].
  172.       case &#039;m&#039;:
  173.         s = _parse_num(s, 1, 12, &tm->tm_mon);
  174.         if (s == NULL) return NULL;
  175.         --tm->tm_mon;
  176.         break;
  177.  
  178.       // day [1, 31].
  179.       case &#039;d&#039;:
  180.       case &#039;e&#039;:
  181.         s = _parse_num(s, 1, 31, &tm->tm_mday);
  182.         if (s == NULL) return NULL;
  183.         break;
  184.  
  185.       // hour [0, 23].
  186.       case &#039;H&#039;:
  187.         s = _parse_num(s, 0, 23, &tm->tm_hour);
  188.         if (s == NULL) return NULL;
  189.         break;
  190.  
  191.       // minute [0, 59]
  192.       case &#039;M&#039;:
  193.         s = _parse_num(s, 0, 59, &tm->tm_min);
  194.         if (s == NULL) return NULL;
  195.         break;
  196.  
  197.       // seconds [0, 60]. 60 is for leap year.
  198.       case &#039;S&#039;:
  199.         s = _parse_num(s, 0, 60, &tm->tm_sec);
  200.         if (s == NULL) return NULL;
  201.         break;
  202.  
  203.       // year [1900, 9999].
  204.       case &#039;Y&#039;:
  205.         s = _parse_num(s, 1900, 9999, &tm->tm_year);
  206.         if (s == NULL) return NULL;
  207.         tm->tm_year -= 1900;
  208.         break;
  209.  
  210.       // year [0, 99].
  211.       case &#039;y&#039;:
  212.         s = _parse_num(s, 0, 99, &tm->tm_year);
  213.         if (s == NULL) return NULL;
  214.         if (tm->tm_year <= 68) {
  215.           tm->tm_year += 100;
  216.         }
  217.         break;
  218.  
  219.       // arbitray whitespace.
  220.       case &#039;t&#039;:
  221.       case &#039;n&#039;:
  222.         while (isspace(*s)) ++s;
  223.         break;
  224.  
  225.       // &#039;%&#039;.
  226.       case &#039;%&#039;:
  227.         if (*s != &#039;%&#039;) return NULL;
  228.         ++s;
  229.         break;
  230.  
  231.       // All the other format are not supported.
  232.       default:
  233.         return NULL;
  234.     }
  235.     ++format;
  236.   }
  237.  
  238.   if (*format != NULL) {
  239.     return NULL;
  240.   } else {
  241.     return const_cast<char*>(s);
  242.   }
  243. }
  244.  
  245. char* strptime(const char *buf, const char *fmt, struct tm *tm) {
  246.   return _strptime(buf, fmt, tm);
  247. }
  248. #endif  // WIN32
  249.  
  250. #if defined(__linux__) || defined(__unix__)
  251.  
  252. time_t _mkgmtime(const struct tm *tm) {
  253.   // Month-to-day offset for non-leap-years.
  254.   static const int month_day[12] =
  255.     {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  256.  
  257.   // Most of the calculation is easy; leap years are the main difficulty.
  258.   int month = tm->tm_mon % 12;
  259.   int year = tm->tm_year + tm->tm_mon / 12;
  260.   if (month < 0) {   // Negative values % 12 are still negative.
  261.     month += 12;
  262.     --year;
  263.   }
  264.  
  265.   // This is the number of Februaries since 1900.
  266.   const int year_for_leap = (month > 1) ? year + 1 : year;
  267.  
  268.   time_t rt = tm->tm_sec                             // Seconds
  269.        + 60 * (tm->tm_min                          // Minute = 60 seconds
  270.        + 60 * (tm->tm_hour                         // Hour = 60 minutes
  271.        + 24 * (month_day[month] + tm->tm_mday - 1  // Day = 24 hours
  272.        + 365 * (year - 70)                         // Year = 365 days
  273.        + (year_for_leap - 69) / 4                  // Every 4 years is leap...
  274.        - (year_for_leap - 1) / 100                 // Except centuries...
  275.        + (year_for_leap + 299) / 400)));           // Except 400s.
  276.   return rt < 0 ? -1 : rt;
  277. }
  278.  
  279. #endif
  280.  
  281. bool ParseRfcTime(const char* buf, struct tm *tm) {
  282.   memset(tm, 0, sizeof(*tm));
  283.   return
  284.     strptime(buf, "%a, %e %b %Y %H:%M:%S", tm) ||  // RFC 822/1123
  285.     strptime(buf, "%a, %e-%b-%y %H:%M:%S", tm) ||  // RFC 850/1036
  286.     strptime(buf, "%a %b %e %H:%M:%S %Y",  tm);    // asctime()
  287. }
  288.  
  289. // Covert the time to W3C Datetime formats.
  290. // See http://www.w3.org/TR/NOTE-datetime
  291. const std::string FormatW3CTime(const time_t &time) {
  292.   char buffer[80];
  293.   strftime(buffer, 80,
  294.            "%Y-%m-%dT%H:%M:%SZ",  // like 2001-12-31T23:59:59Z
  295.            gmtime(&time));
  296.   return buffer;
  297. }
  298.  
  299. std::string FormatHttpDate(time_t t) {
  300.   // Convert &#039;time_t&#039; to struct tm (GMT)
  301.   tm* gmt_p = gmtime(&t);
  302.  
  303.   // Convert struct tm to HTTP-date string
  304.   char buff[256];
  305.   strftime(buff, sizeof(buff), "%a, %d %b %Y %H:%M:%S GMT", gmt_p);
  306.   return buff;
  307. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement