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