diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/gen/strftime.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/gen/strftime.c')
-rwxr-xr-x | sys/src/ape/lib/ap/gen/strftime.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/gen/strftime.c b/sys/src/ape/lib/ap/gen/strftime.c new file mode 100755 index 000000000..f86606089 --- /dev/null +++ b/sys/src/ape/lib/ap/gen/strftime.c @@ -0,0 +1,202 @@ +#include <time.h> +#include <string.h> + +static char *awday[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +static char *wday[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday"}; +static char *amon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +static char *mon[12] = {"January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; +static char *ampm[2] = {"AM", "PM"}; +static char *tz[2] = {"EST", "EDT"}; + +static int jan1(int); +static char *strval(char *, char *, char **, int, int); +static char *dval(char *, char *, int, int); + +size_t +strftime(char *s, size_t maxsize, const char *format, const struct tm *t) +{ + char *sp, *se, *fp; + int i; + + sp = s; + se = s+maxsize; + for(fp=(char *)format; *fp && sp<se; fp++){ + if(*fp != '%') + *sp++ = *fp; + else switch(*++fp){ + case 'a': + sp = strval(sp, se, awday, t->tm_wday, 7); + break; + case 'A': + sp = strval(sp, se, wday, t->tm_wday, 7); + break; + case 'b': + sp = strval(sp, se, amon, t->tm_mon, 12); + break; + case 'B': + sp = strval(sp, se, mon, t->tm_mon, 12); + break; + case 'c': + sp += strftime(sp, se-sp, "%a %b %d %H:%M:%S %Y", t); + break; + case 'd': + sp = dval(sp, se, t->tm_mday, 2); + break; + case 'H': + sp = dval(sp, se, t->tm_hour, 2); + break; + case 'I': + i = t->tm_hour; + if(i == 0) + i = 12; + else if(i > 12) + i -= 12; + sp = dval(sp, se, i, 2); + break; + case 'j': + sp = dval(sp, se, t->tm_yday+1, 3); + break; + case 'm': + sp = dval(sp, se, t->tm_mon+1, 2); + break; + case 'M': + sp = dval(sp, se, t->tm_min, 2); + break; + case 'p': + i = (t->tm_hour < 12)? 0 : 1; + sp = strval(sp, se, ampm, i, 2); + break; + case 'S': + sp = dval(sp, se, t->tm_sec, 2); + break; + case 'U': + i = 7-jan1(t->tm_year); + if(i == 7) + i = 0; + /* Now i is yday number of first sunday in year */ + if(t->tm_yday < i) + i = 0; + else + i = (t->tm_yday-i)/7 + 1; + sp = dval(sp, se, i, 2); + break; + case 'w': + sp = dval(sp, se, t->tm_wday, 1); + break; + case 'W': + i = 8-jan1(t->tm_year); + if(i >= 7) + i -= 7; + /* Now i is yday number of first monday in year */ + if(t->tm_yday < i) + i = 0; + else + i = (t->tm_yday-i)/7 + 1; + sp = dval(sp, se, i, 2); + break; + case 'x': + sp += strftime(sp, se-sp, "%a %b %d, %Y", t); + break; + case 'X': + sp += strftime(sp, se-sp, "%H:%M:%S", t); + break; + case 'y': + sp = dval(sp, se, t->tm_year%100, 2); + break; + case 'Y': + sp = dval(sp, se, t->tm_year+1900, 4); + break; + case 'Z': + /* hack for now: assume eastern time zone */ + i = t->tm_isdst? 1 : 0; + sp = strval(sp, se, tz, i, 2); + break; + case 0: + fp--; /* stop loop after next fp incr */ + break; + default: + *sp++ = *fp; + } + } + if(*fp) + sp = s; /* format string didn't end: no room for conversion */ + if(sp<se) + *sp = 0; + return sp-s; +} + +static char * +strval(char *start, char *end, char **array, int index, int alen) +{ + int n; + + if(index<0 || index>=alen){ + *start = '?'; + return start+1; + } + n = strlen(array[index]); + if(n > end-start) + n = end-start; + memcpy(start, array[index], n); + return start+n; +} + +static char * +dval(char *start, char *end, int val, int width) +{ + char *p; + + if(val<0 || end-start<width){ + *start = '?'; + return start+1; + } + p = start+width-1; + while(p>=start){ + *p-- = val%10 + '0'; + val /= 10; + } + if(val>0) + *start = '*'; + return start+width; +} + +/* + * return day of the week + * of jan 1 of given year + */ +static int +jan1(int yr) +{ + int y, d; + +/* + * normal gregorian calendar + * one extra day per four years + */ + + y = yr+1900; + d = 4+y+(y+3)/4; + +/* + * julian calendar + * regular gregorian + * less three days per 400 + */ + + if(y > 1800) { + d -= (y-1701)/100; + d += (y-1601)/400; + } + +/* + * great calendar changeover instant + */ + + if(y > 1752) + d += 3; + + return(d%7); +} |