URI:
       tdate.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tdate.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 }