|
|
1.1 ! root 1: /* ! 2: * strftime.c ! 3: * ! 4: * Public-domain relatively quick-and-dirty implemenation of ! 5: * ANSI library routine for System V Unix systems. ! 6: * ! 7: * It's written in old-style C for maximal portability. ! 8: * ! 9: * The code for %c, %x, and %X is my best guess as to what's "appropriate". ! 10: * This version ignores LOCALE information. ! 11: * It also doesn't worry about multi-byte characters. ! 12: * So there. ! 13: * ! 14: * Arnold Robbins ! 15: * January, February, 1991 ! 16: * ! 17: * Fixes from [email protected] ! 18: * February 1991 ! 19: *----------------------------------------------------------------------------- ! 20: * $Id: strftime.c,v 2.0 1992/10/16 04:52:16 markd Rel $ ! 21: *----------------------------------------------------------------------------- ! 22: */ ! 23: ! 24: /* ! 25: * To avoid Unix version problems, this code has been simplified to avoid ! 26: * const and size_t, however this can cause an incompatible definition on ! 27: * ansi-C systems, so a game is played with defines to ignore a strftime ! 28: * declaration in time.h ! 29: */ ! 30: ! 31: #define strftime ___srtftime ! 32: ! 33: #include <stdio.h> ! 34: #include <string.h> ! 35: #include <time.h> ! 36: #include <sys/types.h> ! 37: ! 38: #undef strftime ! 39: ! 40: extern char *strchr(); ! 41: static int weeknumber(); ! 42: ! 43: #ifndef TCL_HAS_TM_ZONE ! 44: extern char *tzname[2]; ! 45: extern int daylight; ! 46: #endif ! 47: ! 48: /* strftime --- produce formatted time */ ! 49: ! 50: int ! 51: strftime(s, maxsize, format, timeptr) ! 52: char *s; ! 53: int maxsize; ! 54: char *format; ! 55: struct tm *timeptr; ! 56: { ! 57: char *endp = s + maxsize; ! 58: char *start = s; ! 59: char tbuf[100]; ! 60: int i; ! 61: ! 62: /* various tables, useful in North America */ ! 63: static char *days_a[] = { ! 64: "Sun", "Mon", "Tue", "Wed", ! 65: "Thu", "Fri", "Sat", ! 66: }; ! 67: static char *days_l[] = { ! 68: "Sunday", "Monday", "Tuesday", "Wednesday", ! 69: "Thursday", "Friday", "Saturday", ! 70: }; ! 71: static char *months_a[] = { ! 72: "Jan", "Feb", "Mar", "Apr", "May", "Jun", ! 73: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ! 74: }; ! 75: static char *months_l[] = { ! 76: "January", "February", "March", "April", ! 77: "May", "June", "July", "August", "September", ! 78: "October", "November", "December", ! 79: }; ! 80: static char *ampm[] = { "AM", "PM", }; ! 81: ! 82: if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0) ! 83: return 0; ! 84: ! 85: if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize) ! 86: return 0; ! 87: ! 88: for (; *format && s < endp - 1; format++) { ! 89: tbuf[0] = '\0'; ! 90: if (*format != '%') { ! 91: *s++ = *format; ! 92: continue; ! 93: } ! 94: switch (*++format) { ! 95: case '\0': ! 96: *s++ = '%'; ! 97: goto out; ! 98: ! 99: case '%': ! 100: *s++ = '%'; ! 101: continue; ! 102: ! 103: case 'a': /* abbreviated weekday name */ ! 104: if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) ! 105: strcpy(tbuf, "?"); ! 106: else ! 107: strcpy(tbuf, days_a[timeptr->tm_wday]); ! 108: break; ! 109: ! 110: case 'A': /* full weekday name */ ! 111: if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) ! 112: strcpy(tbuf, "?"); ! 113: else ! 114: strcpy(tbuf, days_l[timeptr->tm_wday]); ! 115: break; ! 116: ! 117: case 'h': /* abbreviated month name */ ! 118: case 'b': /* abbreviated month name */ ! 119: if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) ! 120: strcpy(tbuf, "?"); ! 121: else ! 122: strcpy(tbuf, months_a[timeptr->tm_mon]); ! 123: break; ! 124: ! 125: case 'B': /* full month name */ ! 126: if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) ! 127: strcpy(tbuf, "?"); ! 128: else ! 129: strcpy(tbuf, months_l[timeptr->tm_mon]); ! 130: break; ! 131: ! 132: case 'c': /* appropriate date and time representation */ ! 133: sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d", ! 134: days_a[timeptr->tm_wday], ! 135: months_a[timeptr->tm_mon], ! 136: timeptr->tm_mday, ! 137: timeptr->tm_hour, ! 138: timeptr->tm_min, ! 139: timeptr->tm_sec, ! 140: timeptr->tm_year + 1900); ! 141: break; ! 142: ! 143: case 'd': /* day of the month, 01 - 31 */ ! 144: sprintf(tbuf, "%02d", timeptr->tm_mday); ! 145: break; ! 146: ! 147: case 'H': /* hour, 24-hour clock, 00 - 23 */ ! 148: sprintf(tbuf, "%02d", timeptr->tm_hour); ! 149: break; ! 150: ! 151: case 'I': /* hour, 12-hour clock, 01 - 12 */ ! 152: i = timeptr->tm_hour; ! 153: if (i == 0) ! 154: i = 12; ! 155: else if (i > 12) ! 156: i -= 12; ! 157: sprintf(tbuf, "%02d", i); ! 158: break; ! 159: ! 160: case 'j': /* day of the year, 001 - 366 */ ! 161: sprintf(tbuf, "%03d", timeptr->tm_yday + 1); ! 162: break; ! 163: ! 164: case 'm': /* month, 01 - 12 */ ! 165: sprintf(tbuf, "%02d", timeptr->tm_mon + 1); ! 166: break; ! 167: ! 168: case 'M': /* minute, 00 - 59 */ ! 169: sprintf(tbuf, "%02d", timeptr->tm_min); ! 170: break; ! 171: ! 172: case 'p': /* am or pm based on 12-hour clock */ ! 173: if (timeptr->tm_hour < 12) ! 174: strcpy(tbuf, ampm[0]); ! 175: else ! 176: strcpy(tbuf, ampm[1]); ! 177: break; ! 178: ! 179: case 'S': /* second, 00 - 61 */ ! 180: sprintf(tbuf, "%02d", timeptr->tm_sec); ! 181: break; ! 182: ! 183: case 'U': /* week of year, Sunday is first day of week */ ! 184: sprintf(tbuf, "%d", weeknumber(timeptr, 0)); ! 185: break; ! 186: ! 187: case 'w': /* weekday, Sunday == 0, 0 - 6 */ ! 188: sprintf(tbuf, "%d", timeptr->tm_wday); ! 189: break; ! 190: ! 191: case 'W': /* week of year, Monday is first day of week */ ! 192: sprintf(tbuf, "%d", weeknumber(timeptr, 1)); ! 193: break; ! 194: ! 195: case 'x': /* appropriate date representation */ ! 196: sprintf(tbuf, "%s %s %2d %d", ! 197: days_a[timeptr->tm_wday], ! 198: months_a[timeptr->tm_mon], ! 199: timeptr->tm_mday, ! 200: timeptr->tm_year + 1900); ! 201: break; ! 202: ! 203: case 'X': /* appropriate time representation */ ! 204: sprintf(tbuf, "%02d:%02d:%02d", ! 205: timeptr->tm_hour, ! 206: timeptr->tm_min, ! 207: timeptr->tm_sec); ! 208: break; ! 209: ! 210: case 'y': /* year without a century, 00 - 99 */ ! 211: i = timeptr->tm_year % 100; ! 212: sprintf(tbuf, "%d", i); ! 213: break; ! 214: ! 215: case 'Y': /* year with century */ ! 216: sprintf(tbuf, "%d", 1900 + timeptr->tm_year); ! 217: break; ! 218: ! 219: case 'Z': /* time zone name or abbrevation */ ! 220: #ifdef TCL_HAS_TM_ZONE ! 221: strcpy(tbuf, timeptr->tm_zone); ! 222: #else ! 223: i = 0; ! 224: if (daylight && timeptr->tm_isdst) ! 225: i = 1; ! 226: strcpy(tbuf, tzname[i]); ! 227: #endif ! 228: break; ! 229: ! 230: case 'n': /* same as \n */ ! 231: tbuf[0] = '\n'; ! 232: tbuf[1] = '\0'; ! 233: break; ! 234: ! 235: case 't': /* same as \t */ ! 236: tbuf[0] = '\t'; ! 237: tbuf[1] = '\0'; ! 238: break; ! 239: ! 240: case 'D': /* date as %m/%d/%y */ ! 241: strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr); ! 242: break; ! 243: ! 244: case 'e': /* day of month, blank padded */ ! 245: sprintf(tbuf, "%2d", timeptr->tm_mday); ! 246: break; ! 247: ! 248: case 'r': /* time as %I:%M:%S %p */ ! 249: strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr); ! 250: break; ! 251: ! 252: case 'R': /* time as %H:%M */ ! 253: strftime(tbuf, sizeof tbuf, "%H:%M", timeptr); ! 254: break; ! 255: ! 256: case 'T': /* time as %H:%M:%S */ ! 257: strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr); ! 258: break; ! 259: ! 260: default: ! 261: tbuf[0] = '%'; ! 262: tbuf[1] = *format; ! 263: tbuf[2] = '\0'; ! 264: break; ! 265: } ! 266: i = strlen(tbuf); ! 267: if (i) ! 268: if (s + i < endp - 1) { ! 269: strcpy(s, tbuf); ! 270: s += i; ! 271: } else ! 272: return 0; ! 273: } ! 274: out: ! 275: if (s < endp && *format == '\0') { ! 276: *s = '\0'; ! 277: return (s - start); ! 278: } else ! 279: return 0; ! 280: } ! 281: ! 282: /* weeknumber --- figure how many weeks into the year */ ! 283: ! 284: /* With thanks and tip of the hatlo to [email protected] */ ! 285: ! 286: static int ! 287: weeknumber(timeptr, firstweekday) ! 288: struct tm *timeptr; ! 289: int firstweekday; ! 290: { ! 291: if (firstweekday == 0) ! 292: return (timeptr->tm_yday + 7 - timeptr->tm_wday) / 7; ! 293: else ! 294: return (timeptr->tm_yday + 7 - ! 295: (timeptr->tm_wday ? (timeptr->tm_wday - 1) : 6)) / 7; ! 296: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.