|
|
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.