summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/gen/strftime.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/ape/lib/ap/gen/strftime.c202
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);
+}