|
1 /* glpmpl05.c */ |
|
2 |
|
3 /*********************************************************************** |
|
4 * This code is part of GLPK (GNU Linear Programming Kit). |
|
5 * |
|
6 * Authors: Andrew Makhorin <mao@gnu.org> |
|
7 * Heinrich Schuchardt <xypron.glpk@gmx.de> |
|
8 * |
|
9 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |
|
10 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics, |
|
11 * Moscow Aviation Institute, Moscow, Russia. All rights reserved. |
|
12 * E-mail: <mao@gnu.org>. |
|
13 * |
|
14 * GLPK is free software: you can redistribute it and/or modify it |
|
15 * under the terms of the GNU General Public License as published by |
|
16 * the Free Software Foundation, either version 3 of the License, or |
|
17 * (at your option) any later version. |
|
18 * |
|
19 * GLPK is distributed in the hope that it will be useful, but WITHOUT |
|
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
|
22 * License for more details. |
|
23 * |
|
24 * You should have received a copy of the GNU General Public License |
|
25 * along with GLPK. If not, see <http://www.gnu.org/licenses/>. |
|
26 ***********************************************************************/ |
|
27 |
|
28 #define _GLPSTD_STDIO |
|
29 #define _GLPSTD_TIME |
|
30 #include "glpmpl.h" |
|
31 |
|
32 double fn_gmtime(MPL *mpl) |
|
33 { /* obtain the current calendar time (UTC) */ |
|
34 time_t timer; |
|
35 struct tm *tm; |
|
36 int j; |
|
37 time(&timer); |
|
38 if (timer == (time_t)(-1)) |
|
39 err: error(mpl, "gmtime(); unable to obtain current calendar time"); |
|
40 tm = gmtime(&timer); |
|
41 if (tm == NULL) goto err; |
|
42 j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); |
|
43 if (j < 0) goto err; |
|
44 return (((double)(j - jday(1, 1, 1970)) * 24.0 + |
|
45 (double)tm->tm_hour) * 60.0 + (double)tm->tm_min) * 60.0 + |
|
46 (double)tm->tm_sec; |
|
47 } |
|
48 |
|
49 static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", |
|
50 "Friday", "Saturday", "Sunday" }; |
|
51 |
|
52 static char *moon[] = { "January", "February", "March", "April", "May", |
|
53 "June", "July", "August", "September", "October", "November", |
|
54 "December" }; |
|
55 |
|
56 static void error1(MPL *mpl, const char *str, const char *s, |
|
57 const char *fmt, const char *f, const char *msg) |
|
58 { xprintf("Input string passed to str2time:\n"); |
|
59 xprintf("%s\n", str); |
|
60 xprintf("%*s\n", (s - str) + 1, "^"); |
|
61 xprintf("Format string passed to str2time:\n"); |
|
62 xprintf("%s\n", fmt); |
|
63 xprintf("%*s\n", (f - fmt) + 1, "^"); |
|
64 error(mpl, "%s", msg); |
|
65 /* no return */ |
|
66 } |
|
67 |
|
68 double fn_str2time(MPL *mpl, const char *str, const char *fmt) |
|
69 { /* convert character string to the calendar time */ |
|
70 int j, year, month, day, hh, mm, ss, zone; |
|
71 const char *s, *f; |
|
72 year = month = day = hh = mm = ss = -1, zone = INT_MAX; |
|
73 s = str; |
|
74 for (f = fmt; *f != '\0'; f++) |
|
75 { if (*f == '%') |
|
76 { f++; |
|
77 if (*f == 'b' || *f == 'h') |
|
78 { /* the abbreviated month name */ |
|
79 int k; |
|
80 char *name; |
|
81 if (month >= 0) |
|
82 error1(mpl, str, s, fmt, f, "month multiply specified" |
|
83 ); |
|
84 while (*s == ' ') s++; |
|
85 for (month = 1; month <= 12; month++) |
|
86 { name = moon[month-1]; |
|
87 for (k = 0; k <= 2; k++) |
|
88 { if (toupper((unsigned char)s[k]) != |
|
89 toupper((unsigned char)name[k])) goto next; |
|
90 } |
|
91 s += 3; |
|
92 for (k = 3; name[k] != '\0'; k++) |
|
93 { if (toupper((unsigned char)*s) != |
|
94 toupper((unsigned char)name[k])) break; |
|
95 s++; |
|
96 } |
|
97 break; |
|
98 next: ; |
|
99 } |
|
100 if (month > 12) |
|
101 error1(mpl, str, s, fmt, f, "abbreviated month name m" |
|
102 "issing or invalid"); |
|
103 } |
|
104 else if (*f == 'd') |
|
105 { /* the day of the month as a decimal number (01..31) */ |
|
106 if (day >= 0) |
|
107 error1(mpl, str, s, fmt, f, "day multiply specified"); |
|
108 while (*s == ' ') s++; |
|
109 if (!('0' <= *s && *s <= '9')) |
|
110 error1(mpl, str, s, fmt, f, "day missing or invalid"); |
|
111 day = (*s++) - '0'; |
|
112 if ('0' <= *s && *s <= '9') |
|
113 day = 10 * day + ((*s++) - '0'); |
|
114 if (!(1 <= day && day <= 31)) |
|
115 error1(mpl, str, s, fmt, f, "day out of range"); |
|
116 } |
|
117 else if (*f == 'H') |
|
118 { /* the hour as a decimal number, using a 24-hour clock |
|
119 (00..23) */ |
|
120 if (hh >= 0) |
|
121 error1(mpl, str, s, fmt, f, "hour multiply specified") |
|
122 ; |
|
123 while (*s == ' ') s++; |
|
124 if (!('0' <= *s && *s <= '9')) |
|
125 error1(mpl, str, s, fmt, f, "hour missing or invalid") |
|
126 ; |
|
127 hh = (*s++) - '0'; |
|
128 if ('0' <= *s && *s <= '9') |
|
129 hh = 10 * hh + ((*s++) - '0'); |
|
130 if (!(0 <= hh && hh <= 23)) |
|
131 error1(mpl, str, s, fmt, f, "hour out of range"); |
|
132 } |
|
133 else if (*f == 'm') |
|
134 { /* the month as a decimal number (01..12) */ |
|
135 if (month >= 0) |
|
136 error1(mpl, str, s, fmt, f, "month multiply specified" |
|
137 ); |
|
138 while (*s == ' ') s++; |
|
139 if (!('0' <= *s && *s <= '9')) |
|
140 error1(mpl, str, s, fmt, f, "month missing or invalid" |
|
141 ); |
|
142 month = (*s++) - '0'; |
|
143 if ('0' <= *s && *s <= '9') |
|
144 month = 10 * month + ((*s++) - '0'); |
|
145 if (!(1 <= month && month <= 12)) |
|
146 error1(mpl, str, s, fmt, f, "month out of range"); |
|
147 } |
|
148 else if (*f == 'M') |
|
149 { /* the minute as a decimal number (00..59) */ |
|
150 if (mm >= 0) |
|
151 error1(mpl, str, s, fmt, f, "minute multiply specifie" |
|
152 "d"); |
|
153 while (*s == ' ') s++; |
|
154 if (!('0' <= *s && *s <= '9')) |
|
155 error1(mpl, str, s, fmt, f, "minute missing or invali" |
|
156 "d"); |
|
157 mm = (*s++) - '0'; |
|
158 if ('0' <= *s && *s <= '9') |
|
159 mm = 10 * mm + ((*s++) - '0'); |
|
160 if (!(0 <= mm && mm <= 59)) |
|
161 error1(mpl, str, s, fmt, f, "minute out of range"); |
|
162 } |
|
163 else if (*f == 'S') |
|
164 { /* the second as a decimal number (00..60) */ |
|
165 if (ss >= 0) |
|
166 error1(mpl, str, s, fmt, f, "second multiply specifie" |
|
167 "d"); |
|
168 while (*s == ' ') s++; |
|
169 if (!('0' <= *s && *s <= '9')) |
|
170 error1(mpl, str, s, fmt, f, "second missing or invali" |
|
171 "d"); |
|
172 ss = (*s++) - '0'; |
|
173 if ('0' <= *s && *s <= '9') |
|
174 ss = 10 * ss + ((*s++) - '0'); |
|
175 if (!(0 <= ss && ss <= 60)) |
|
176 error1(mpl, str, s, fmt, f, "second out of range"); |
|
177 } |
|
178 else if (*f == 'y') |
|
179 { /* the year without a century as a decimal number |
|
180 (00..99); the values 00 to 68 mean the years 2000 to |
|
181 2068 while the values 69 to 99 mean the years 1969 to |
|
182 1999 */ |
|
183 if (year >= 0) |
|
184 error1(mpl, str, s, fmt, f, "year multiply specified") |
|
185 ; |
|
186 while (*s == ' ') s++; |
|
187 if (!('0' <= *s && *s <= '9')) |
|
188 error1(mpl, str, s, fmt, f, "year missing or invalid") |
|
189 ; |
|
190 year = (*s++) - '0'; |
|
191 if ('0' <= *s && *s <= '9') |
|
192 year = 10 * year + ((*s++) - '0'); |
|
193 year += (year >= 69 ? 1900 : 2000); |
|
194 } |
|
195 else if (*f == 'Y') |
|
196 { /* the year as a decimal number, using the Gregorian |
|
197 calendar */ |
|
198 if (year >= 0) |
|
199 error1(mpl, str, s, fmt, f, "year multiply specified") |
|
200 ; |
|
201 while (*s == ' ') s++; |
|
202 if (!('0' <= *s && *s <= '9')) |
|
203 error1(mpl, str, s, fmt, f, "year missing or invalid") |
|
204 ; |
|
205 year = 0; |
|
206 for (j = 1; j <= 4; j++) |
|
207 { if (!('0' <= *s && *s <= '9')) break; |
|
208 year = 10 * year + ((*s++) - '0'); |
|
209 } |
|
210 if (!(1 <= year && year <= 4000)) |
|
211 error1(mpl, str, s, fmt, f, "year out of range"); |
|
212 } |
|
213 else if (*f == 'z') |
|
214 { /* time zone offset in the form zhhmm */ |
|
215 int z, hh, mm; |
|
216 if (zone != INT_MAX) |
|
217 error1(mpl, str, s, fmt, f, "time zone offset multipl" |
|
218 "y specified"); |
|
219 while (*s == ' ') s++; |
|
220 if (*s == 'Z') |
|
221 { z = hh = mm = 0, s++; |
|
222 goto skip; |
|
223 } |
|
224 if (*s == '+') |
|
225 z = +1, s++; |
|
226 else if (*s == '-') |
|
227 z = -1, s++; |
|
228 else |
|
229 error1(mpl, str, s, fmt, f, "time zone offset sign mi" |
|
230 "ssing"); |
|
231 hh = 0; |
|
232 for (j = 1; j <= 2; j++) |
|
233 { if (!('0' <= *s && *s <= '9')) |
|
234 err1: error1(mpl, str, s, fmt, f, "time zone offset valu" |
|
235 "e incomplete or invalid"); |
|
236 hh = 10 * hh + ((*s++) - '0'); |
|
237 } |
|
238 if (hh > 23) |
|
239 err2: error1(mpl, str, s, fmt, f, "time zone offset value o" |
|
240 "ut of range"); |
|
241 if (*s == ':') |
|
242 { s++; |
|
243 if (!('0' <= *s && *s <= '9')) goto err1; |
|
244 } |
|
245 mm = 0; |
|
246 if (!('0' <= *s && *s <= '9')) goto skip; |
|
247 for (j = 1; j <= 2; j++) |
|
248 { if (!('0' <= *s && *s <= '9')) goto err1; |
|
249 mm = 10 * mm + ((*s++) - '0'); |
|
250 } |
|
251 if (mm > 59) goto err2; |
|
252 skip: zone = z * (60 * hh + mm); |
|
253 } |
|
254 else if (*f == '%') |
|
255 { /* literal % character */ |
|
256 goto test; |
|
257 } |
|
258 else |
|
259 error1(mpl, str, s, fmt, f, "invalid conversion specifie" |
|
260 "r"); |
|
261 } |
|
262 else if (*f == ' ') |
|
263 ; |
|
264 else |
|
265 test: { /* check a matching character in the input string */ |
|
266 if (*s != *f) |
|
267 error1(mpl, str, s, fmt, f, "character mismatch"); |
|
268 s++; |
|
269 } |
|
270 } |
|
271 if (year < 0) year = 1970; |
|
272 if (month < 0) month = 1; |
|
273 if (day < 0) day = 1; |
|
274 if (hh < 0) hh = 0; |
|
275 if (mm < 0) mm = 0; |
|
276 if (ss < 0) ss = 0; |
|
277 if (zone == INT_MAX) zone = 0; |
|
278 j = jday(day, month, year); |
|
279 xassert(j >= 0); |
|
280 return (((double)(j - jday(1, 1, 1970)) * 24.0 + (double)hh) * |
|
281 60.0 + (double)mm) * 60.0 + (double)ss - 60.0 * (double)zone; |
|
282 } |
|
283 |
|
284 static void error2(MPL *mpl, const char *fmt, const char *f, |
|
285 const char *msg) |
|
286 { xprintf("Format string passed to time2str:\n"); |
|
287 xprintf("%s\n", fmt); |
|
288 xprintf("%*s\n", (f - fmt) + 1, "^"); |
|
289 error(mpl, "%s", msg); |
|
290 /* no return */ |
|
291 } |
|
292 |
|
293 static int weekday(int j) |
|
294 { /* determine weekday number (1 = Mon, ..., 7 = Sun) */ |
|
295 return (j + jday(1, 1, 1970)) % 7 + 1; |
|
296 } |
|
297 |
|
298 static int firstday(int year) |
|
299 { /* determine the first day of the first week for a specified year |
|
300 according to ISO 8601 */ |
|
301 int j; |
|
302 /* if 1 January is Monday, Tuesday, Wednesday or Thursday, it is |
|
303 in week 01; if 1 January is Friday, Saturday or Sunday, it is |
|
304 in week 52 or 53 of the previous year */ |
|
305 j = jday(1, 1, year) - jday(1, 1, 1970); |
|
306 switch (weekday(j)) |
|
307 { case 1: /* 1 Jan is Mon */ j += 0; break; |
|
308 case 2: /* 1 Jan is Tue */ j -= 1; break; |
|
309 case 3: /* 1 Jan is Wed */ j -= 2; break; |
|
310 case 4: /* 1 Jan is Thu */ j -= 3; break; |
|
311 case 5: /* 1 Jan is Fri */ j += 3; break; |
|
312 case 6: /* 1 Jan is Sat */ j += 2; break; |
|
313 case 7: /* 1 Jan is Sun */ j += 1; break; |
|
314 default: xassert(j != j); |
|
315 } |
|
316 /* the first day of the week must be Monday */ |
|
317 xassert(weekday(j) == 1); |
|
318 return j; |
|
319 } |
|
320 |
|
321 void fn_time2str(MPL *mpl, char *str, double t, const char *fmt) |
|
322 { /* convert the calendar time to character string */ |
|
323 int j, year, month, day, hh, mm, ss, len; |
|
324 double temp; |
|
325 const char *f; |
|
326 char buf[MAX_LENGTH+1]; |
|
327 if (!(-62135596800.0 <= t && t <= 64092211199.0)) |
|
328 error(mpl, "time2str(%.*g,...); argument out of range", |
|
329 DBL_DIG, t); |
|
330 t = floor(t + 0.5); |
|
331 temp = fabs(t) / 86400.0; |
|
332 j = (int)floor(temp); |
|
333 if (t < 0.0) |
|
334 { if (temp == floor(temp)) |
|
335 j = - j; |
|
336 else |
|
337 j = - (j + 1); |
|
338 } |
|
339 xassert(jdate(j + jday(1, 1, 1970), &day, &month, &year) == 0); |
|
340 ss = (int)(t - 86400.0 * (double)j); |
|
341 xassert(0 <= ss && ss < 86400); |
|
342 mm = ss / 60, ss %= 60; |
|
343 hh = mm / 60, mm %= 60; |
|
344 len = 0; |
|
345 for (f = fmt; *f != '\0'; f++) |
|
346 { if (*f == '%') |
|
347 { f++; |
|
348 if (*f == 'a') |
|
349 { /* the abbreviated weekday name */ |
|
350 memcpy(buf, week[weekday(j)-1], 3), buf[3] = '\0'; |
|
351 } |
|
352 else if (*f == 'A') |
|
353 { /* the full weekday name */ |
|
354 strcpy(buf, week[weekday(j)-1]); |
|
355 } |
|
356 else if (*f == 'b' || *f == 'h') |
|
357 { /* the abbreviated month name */ |
|
358 memcpy(buf, moon[month-1], 3), buf[3] = '\0'; |
|
359 } |
|
360 else if (*f == 'B') |
|
361 { /* the full month name */ |
|
362 strcpy(buf, moon[month-1]); |
|
363 } |
|
364 else if (*f == 'C') |
|
365 { /* the century of the year */ |
|
366 sprintf(buf, "%02d", year / 100); |
|
367 } |
|
368 else if (*f == 'd') |
|
369 { /* the day of the month as a decimal number (01..31) */ |
|
370 sprintf(buf, "%02d", day); |
|
371 } |
|
372 else if (*f == 'D') |
|
373 { /* the date using the format %m/%d/%y */ |
|
374 sprintf(buf, "%02d/%02d/%02d", month, day, year % 100); |
|
375 } |
|
376 else if (*f == 'e') |
|
377 { /* the day of the month like with %d, but padded with |
|
378 blank (1..31) */ |
|
379 sprintf(buf, "%2d", day); |
|
380 } |
|
381 else if (*f == 'F') |
|
382 { /* the date using the format %Y-%m-%d */ |
|
383 sprintf(buf, "%04d-%02d-%02d", year, month, day); |
|
384 } |
|
385 else if (*f == 'g') |
|
386 { /* the year corresponding to the ISO week number, but |
|
387 without the century (range 00 through 99); this has |
|
388 the same format and value as %y, except that if the |
|
389 ISO week number (see %V) belongs to the previous or |
|
390 next year, that year is used instead */ |
|
391 int iso; |
|
392 if (j < firstday(year)) |
|
393 iso = year - 1; |
|
394 else if (j < firstday(year + 1)) |
|
395 iso = year; |
|
396 else |
|
397 iso = year + 1; |
|
398 sprintf(buf, "%02d", iso % 100); |
|
399 } |
|
400 else if (*f == 'G') |
|
401 { /* the year corresponding to the ISO week number; this |
|
402 has the same format and value as %Y, excepth that if |
|
403 the ISO week number (see %V) belongs to the previous |
|
404 or next year, that year is used instead */ |
|
405 int iso; |
|
406 if (j < firstday(year)) |
|
407 iso = year - 1; |
|
408 else if (j < firstday(year + 1)) |
|
409 iso = year; |
|
410 else |
|
411 iso = year + 1; |
|
412 sprintf(buf, "%04d", iso); |
|
413 } |
|
414 else if (*f == 'H') |
|
415 { /* the hour as a decimal number, using a 24-hour clock |
|
416 (00..23) */ |
|
417 sprintf(buf, "%02d", hh); |
|
418 } |
|
419 else if (*f == 'I') |
|
420 { /* the hour as a decimal number, using a 12-hour clock |
|
421 (01..12) */ |
|
422 sprintf(buf, "%02d", |
|
423 hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); |
|
424 } |
|
425 else if (*f == 'j') |
|
426 { /* the day of the year as a decimal number (001..366) */ |
|
427 sprintf(buf, "%03d", |
|
428 jday(day, month, year) - jday(1, 1, year) + 1); |
|
429 } |
|
430 else if (*f == 'k') |
|
431 { /* the hour as a decimal number, using a 24-hour clock |
|
432 like %H, but padded with blank (0..23) */ |
|
433 sprintf(buf, "%2d", hh); |
|
434 } |
|
435 else if (*f == 'l') |
|
436 { /* the hour as a decimal number, using a 12-hour clock |
|
437 like %I, but padded with blank (1..12) */ |
|
438 sprintf(buf, "%2d", |
|
439 hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); |
|
440 } |
|
441 else if (*f == 'm') |
|
442 { /* the month as a decimal number (01..12) */ |
|
443 sprintf(buf, "%02d", month); |
|
444 } |
|
445 else if (*f == 'M') |
|
446 { /* the minute as a decimal number (00..59) */ |
|
447 sprintf(buf, "%02d", mm); |
|
448 } |
|
449 else if (*f == 'p') |
|
450 { /* either AM or PM, according to the given time value; |
|
451 noon is treated as PM and midnight as AM */ |
|
452 strcpy(buf, hh <= 11 ? "AM" : "PM"); |
|
453 } |
|
454 else if (*f == 'P') |
|
455 { /* either am or pm, according to the given time value; |
|
456 noon is treated as pm and midnight as am */ |
|
457 strcpy(buf, hh <= 11 ? "am" : "pm"); |
|
458 } |
|
459 else if (*f == 'r') |
|
460 { /* the calendar time using the format %I:%M:%S %p */ |
|
461 sprintf(buf, "%02d:%02d:%02d %s", |
|
462 hh == 0 ? 12 : hh <= 12 ? hh : hh - 12, |
|
463 mm, ss, hh <= 11 ? "AM" : "PM"); |
|
464 } |
|
465 else if (*f == 'R') |
|
466 { /* the hour and minute using the format %H:%M */ |
|
467 sprintf(buf, "%02d:%02d", hh, mm); |
|
468 } |
|
469 else if (*f == 'S') |
|
470 { /* the second as a decimal number (00..59) */ |
|
471 sprintf(buf, "%02d", ss); |
|
472 } |
|
473 else if (*f == 'T') |
|
474 { /* the time of day using the format %H:%M:%S */ |
|
475 sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); |
|
476 } |
|
477 else if (*f == 'u') |
|
478 { /* the day of the week as a decimal number (1..7), |
|
479 Monday being 1 */ |
|
480 sprintf(buf, "%d", weekday(j)); |
|
481 } |
|
482 else if (*f == 'U') |
|
483 { /* the week number of the current year as a decimal |
|
484 number (range 00 through 53), starting with the first |
|
485 Sunday as the first day of the first week; days |
|
486 preceding the first Sunday in the year are considered |
|
487 to be in week 00 */ |
|
488 #if 1 /* 09/I-2009 */ |
|
489 #undef sun |
|
490 /* causes compilation error in SunOS */ |
|
491 #endif |
|
492 int sun; |
|
493 /* sun = the first Sunday of the year */ |
|
494 sun = jday(1, 1, year) - jday(1, 1, 1970); |
|
495 sun += (7 - weekday(sun)); |
|
496 sprintf(buf, "%02d", (j + 7 - sun) / 7); |
|
497 } |
|
498 else if (*f == 'V') |
|
499 { /* the ISO week number as a decimal number (range 01 |
|
500 through 53); ISO weeks start with Monday and end with |
|
501 Sunday; week 01 of a year is the first week which has |
|
502 the majority of its days in that year; week 01 of |
|
503 a year can contain days from the previous year; the |
|
504 week before week 01 of a year is the last week (52 or |
|
505 53) of the previous year even if it contains days |
|
506 from the new year */ |
|
507 int iso; |
|
508 if (j < firstday(year)) |
|
509 iso = j - firstday(year - 1); |
|
510 else if (j < firstday(year + 1)) |
|
511 iso = j - firstday(year); |
|
512 else |
|
513 iso = j - firstday(year + 1); |
|
514 sprintf(buf, "%02d", iso / 7 + 1); |
|
515 } |
|
516 else if (*f == 'w') |
|
517 { /* the day of the week as a decimal number (0..6), |
|
518 Sunday being 0 */ |
|
519 sprintf(buf, "%d", weekday(j) % 7); |
|
520 } |
|
521 else if (*f == 'W') |
|
522 { /* the week number of the current year as a decimal |
|
523 number (range 00 through 53), starting with the first |
|
524 Monday as the first day of the first week; days |
|
525 preceding the first Monday in the year are considered |
|
526 to be in week 00 */ |
|
527 int mon; |
|
528 /* mon = the first Monday of the year */ |
|
529 mon = jday(1, 1, year) - jday(1, 1, 1970); |
|
530 mon += (8 - weekday(mon)) % 7; |
|
531 sprintf(buf, "%02d", (j + 7 - mon) / 7); |
|
532 } |
|
533 else if (*f == 'y') |
|
534 { /* the year without a century as a decimal number |
|
535 (00..99) */ |
|
536 sprintf(buf, "%02d", year % 100); |
|
537 } |
|
538 else if (*f == 'Y') |
|
539 { /* the year as a decimal number, using the Gregorian |
|
540 calendar */ |
|
541 sprintf(buf, "%04d", year); |
|
542 } |
|
543 else if (*f == '%') |
|
544 { /* a literal % character */ |
|
545 buf[0] = '%', buf[1] = '\0'; |
|
546 } |
|
547 else |
|
548 error2(mpl, fmt, f, "invalid conversion specifier"); |
|
549 } |
|
550 else |
|
551 buf[0] = *f, buf[1] = '\0'; |
|
552 if (len + strlen(buf) > MAX_LENGTH) |
|
553 error(mpl, "time2str; output string length exceeds %d chara" |
|
554 "cters", MAX_LENGTH); |
|
555 memcpy(str+len, buf, strlen(buf)); |
|
556 len += strlen(buf); |
|
557 } |
|
558 str[len] = '\0'; |
|
559 return; |
|
560 } |
|
561 |
|
562 /* eof */ |