plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }