1 #include <time.h> 2 #include <string.h> 3 4 static char *awday[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 5 static char *wday[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", 6 "Friday", "Saturday"}; 7 static char *amon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 8 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 9 static char *mon[12] = {"January", "February", "March", "April", "May", "June", 10 "July", "August", "September", "October", "November", "December"}; 11 static char *ampm[2] = {"AM", "PM"}; 12 static char *tz[2] = {"EST", "EDT"}; 13 14 static int jan1(int); 15 static char *strval(char *, char *, char **, int, int); 16 static char *dval(char *, char *, int, int); 17 18 size_t 19 strftime(char *s, size_t maxsize, const char *format, const struct tm *t) 20 { 21 char *sp, *se, *fp; 22 int i; 23 24 sp = s; 25 se = s+maxsize; 26 for(fp=(char *)format; *fp && sp<se; fp++){ 27 if(*fp != '%') 28 *sp++ = *fp; 29 else switch(*++fp){ 30 case 'a': 31 sp = strval(sp, se, awday, t->tm_wday, 7); 32 break; 33 case 'A': 34 sp = strval(sp, se, wday, t->tm_wday, 7); 35 break; 36 case 'b': 37 sp = strval(sp, se, amon, t->tm_mon, 12); 38 break; 39 case 'B': 40 sp = strval(sp, se, mon, t->tm_mon, 12); 41 break; 42 case 'c': 43 sp += strftime(sp, se-sp, "%a %b %d %H:%M:%S %Y", t); 44 break; 45 case 'd': 46 sp = dval(sp, se, t->tm_mday, 2); 47 break; 48 case 'H': 49 sp = dval(sp, se, t->tm_hour, 2); 50 break; 51 case 'I': 52 i = t->tm_hour; 53 if(i == 0) 54 i = 12; 55 else if(i > 12) 56 i -= 12; 57 sp = dval(sp, se, i, 2); 58 break; 59 case 'j': 60 sp = dval(sp, se, t->tm_yday+1, 3); 61 break; 62 case 'm': 63 sp = dval(sp, se, t->tm_mon+1, 2); 64 break; 65 case 'M': 66 sp = dval(sp, se, t->tm_min, 2); 67 break; 68 case 'p': 69 i = (t->tm_hour < 12)? 0 : 1; 70 sp = strval(sp, se, ampm, i, 2); 71 break; 72 case 'S': 73 sp = dval(sp, se, t->tm_sec, 2); 74 break; 75 case 'U': 76 i = 7-jan1(t->tm_year); 77 if(i == 7) 78 i = 0; 79 /* Now i is yday number of first sunday in year */ 80 if(t->tm_yday < i) 81 i = 0; 82 else 83 i = (t->tm_yday-i)/7 + 1; 84 sp = dval(sp, se, i, 2); 85 break; 86 case 'w': 87 sp = dval(sp, se, t->tm_wday, 1); 88 break; 89 case 'W': 90 i = 8-jan1(t->tm_year); 91 if(i >= 7) 92 i -= 7; 93 /* Now i is yday number of first monday in year */ 94 if(t->tm_yday < i) 95 i = 0; 96 else 97 i = (t->tm_yday-i)/7 + 1; 98 sp = dval(sp, se, i, 2); 99 break; 100 case 'x': 101 sp += strftime(sp, se-sp, "%a %b %d, %Y", t); 102 break; 103 case 'X': 104 sp += strftime(sp, se-sp, "%H:%M:%S", t); 105 break; 106 case 'y': 107 sp = dval(sp, se, t->tm_year%100, 2); 108 break; 109 case 'Y': 110 sp = dval(sp, se, t->tm_year+1900, 4); 111 break; 112 case 'Z': 113 /* hack for now: assume eastern time zone */ 114 i = t->tm_isdst? 1 : 0; 115 sp = strval(sp, se, tz, i, 2); 116 break; 117 case 0: 118 fp--; /* stop loop after next fp incr */ 119 break; 120 default: 121 *sp++ = *fp; 122 } 123 } 124 if(*fp) 125 sp = s; /* format string didn't end: no room for conversion */ 126 if(sp<se) 127 *sp = 0; 128 return sp-s; 129 } 130 131 static char * 132 strval(char *start, char *end, char **array, int index, int alen) 133 { 134 int n; 135 136 if(index<0 || index>=alen){ 137 *start = '?'; 138 return start+1; 139 } 140 n = strlen(array[index]); 141 if(n > end-start) 142 n = end-start; 143 memcpy(start, array[index], n); 144 return start+n; 145 } 146 147 static char * 148 dval(char *start, char *end, int val, int width) 149 { 150 char *p; 151 152 if(val<0 || end-start<width){ 153 *start = '?'; 154 return start+1; 155 } 156 p = start+width-1; 157 while(p>=start){ 158 *p-- = val%10 + '0'; 159 val /= 10; 160 } 161 if(val>0) 162 *start = '*'; 163 return start+width; 164 } 165 166 /* 167 * return day of the week 168 * of jan 1 of given year 169 */ 170 static int 171 jan1(int yr) 172 { 173 int y, d; 174 175 /* 176 * normal gregorian calendar 177 * one extra day per four years 178 */ 179 180 y = yr+1900; 181 d = 4+y+(y+3)/4; 182 183 /* 184 * julian calendar 185 * regular gregorian 186 * less three days per 400 187 */ 188 189 if(y > 1800) { 190 d -= (y-1701)/100; 191 d += (y-1601)/400; 192 } 193 194 /* 195 * great calendar changeover instant 196 */ 197 198 if(y > 1752) 199 d += 3; 200 201 return(d%7); 202 } 203