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