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