]> git.zerfleddert.de Git - micropolis/blame - src/tclx/ossupp/strftime.c
don't wreck ships when disasters are disabled
[micropolis] / src / tclx / ossupp / strftime.c
CommitLineData
6a5fa4e0
MG
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 ado@elsie.nci.nih.gov
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
40extern char *strchr();
41static int weeknumber();
42
43#ifndef TCL_HAS_TM_ZONE
44extern char *tzname[2];
45extern int daylight;
46#endif
47
48/* strftime --- produce formatted time */
49
50int
51strftime(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 }
274out:
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 ado@elsie.nci.nih.gov */
285
286static int
287weeknumber(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}
Impressum, Datenschutz