date.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <httpd.h>
  4. /*
  5. * print dates in the format
  6. * Wkd, DD Mon YYYY HH:MM:SS GMT
  7. * parse dates of formats
  8. * Wkd, DD Mon YYYY HH:MM:SS GMT
  9. * Weekday, DD-Mon-YY HH:MM:SS GMT
  10. * Wkd Mon ( D|DD) HH:MM:SS YYYY
  11. * plus anything similar
  12. */
  13. static char *
  14. weekdayname[7] =
  15. {
  16. "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
  17. };
  18. static char *
  19. wdayname[7] =
  20. {
  21. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  22. };
  23. static char *
  24. monname[12] =
  25. {
  26. "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  27. };
  28. static int dateindex(char*, char**, int);
  29. static int
  30. dtolower(int c)
  31. {
  32. if(c >= 'A' && c <= 'Z')
  33. return c - 'A' + 'a';
  34. return c;
  35. }
  36. static int
  37. disalpha(int c)
  38. {
  39. return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
  40. }
  41. static int
  42. disdig(int c)
  43. {
  44. return c >= '0' && c <= '9';
  45. }
  46. int
  47. hdatefmt(Fmt *f)
  48. {
  49. Tm *tm;
  50. ulong t;
  51. t = va_arg(f->args, ulong);
  52. tm = gmtime(t);
  53. return fmtprint(f, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
  54. wdayname[tm->wday], tm->mday, monname[tm->mon], tm->year+1900,
  55. tm->hour, tm->min, tm->sec);
  56. }
  57. static char*
  58. dateword(char *date, char *buf)
  59. {
  60. char *p;
  61. int c;
  62. p = buf;
  63. while(!disalpha(c = *date) && !disdig(c) && c)
  64. date++;
  65. while(disalpha(c = *date)){
  66. if(p - buf < 30)
  67. *p++ = dtolower(c);
  68. date++;
  69. }
  70. *p = 0;
  71. return date;
  72. }
  73. static int
  74. datenum(char **d)
  75. {
  76. char *date;
  77. int c, n;
  78. date = *d;
  79. while(!disdig(c = *date) && c)
  80. date++;
  81. if(c == 0){
  82. *d = date;
  83. return -1;
  84. }
  85. n = 0;
  86. while(disdig(c = *date)){
  87. n = n * 10 + c - '0';
  88. date++;
  89. }
  90. *d = date;
  91. return n;
  92. }
  93. /*
  94. * parse a date and return the seconds since the epoch
  95. * return 0 for a failure
  96. */
  97. ulong
  98. hdate2sec(char *date)
  99. {
  100. Tm tm;
  101. char buf[32];
  102. /*
  103. * Weekday|Wday
  104. */
  105. date = dateword(date, buf);
  106. tm.wday = dateindex(buf, wdayname, 7);
  107. if(tm.wday < 0)
  108. tm.wday = dateindex(buf, weekdayname, 7);
  109. if(tm.wday < 0)
  110. return 0;
  111. /*
  112. * check for the two major formats
  113. */
  114. date = dateword(date, buf);
  115. tm.mon = dateindex(buf, monname, 12);
  116. if(tm.mon >= 0){
  117. /*
  118. * MM
  119. */
  120. tm.mday = datenum(&date);
  121. if(tm.mday < 1 || tm.mday > 31)
  122. return 0;
  123. /*
  124. * HH:MM:SS
  125. */
  126. tm.hour = datenum(&date);
  127. if(tm.hour < 0 || tm.hour >= 24)
  128. return 0;
  129. tm.min = datenum(&date);
  130. if(tm.min < 0 || tm.min >= 60)
  131. return 0;
  132. tm.sec = datenum(&date);
  133. if(tm.sec < 0 || tm.sec >= 60)
  134. return 0;
  135. /*
  136. * YYYY
  137. */
  138. tm.year = datenum(&date);
  139. if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
  140. return 0;
  141. if(tm.year >= 1970)
  142. tm.year -= 1900;
  143. }else{
  144. /*
  145. * MM-Mon-(YY|YYYY)
  146. */
  147. tm.mday = datenum(&date);
  148. if(tm.mday < 1 || tm.mday > 31)
  149. return 0;
  150. date = dateword(date, buf);
  151. tm.mon = dateindex(buf, monname, 12);
  152. if(tm.mon < 0 || tm.mon >= 12)
  153. return 0;
  154. tm.year = datenum(&date);
  155. if(tm.year < 70 || tm.year > 99 && tm.year < 1970)
  156. return 0;
  157. if(tm.year >= 1970)
  158. tm.year -= 1900;
  159. /*
  160. * HH:MM:SS
  161. */
  162. tm.hour = datenum(&date);
  163. if(tm.hour < 0 || tm.hour >= 24)
  164. return 0;
  165. tm.min = datenum(&date);
  166. if(tm.min < 0 || tm.min >= 60)
  167. return 0;
  168. tm.sec = datenum(&date);
  169. if(tm.sec < 0 || tm.sec >= 60)
  170. return 0;
  171. /*
  172. * timezone
  173. */
  174. dateword(date, buf);
  175. if(strncmp(buf, "gmt", 3) != 0)
  176. return 0;
  177. }
  178. strcpy(tm.zone, "GMT");
  179. tm.tzoff = 0;
  180. tm.yday = 0;
  181. return tm2sec(&tm);
  182. }
  183. static int
  184. dateindex(char *d, char **tab, int n)
  185. {
  186. int i;
  187. for(i = 0; i < n; i++)
  188. if(cistrcmp(d, tab[i]) == 0)
  189. return i;
  190. return -1;
  191. }