lemon-project-template-glpk
view deps/glpk/src/glpmpl05.c @ 9:33de93886c88
Import GLPK 4.47
author | Alpar Juttner <alpar@cs.elte.hu> |
---|---|
date | Sun, 06 Nov 2011 20:59:10 +0100 |
parents | |
children |
line source
1 /* glpmpl05.c */
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, 2011 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 ***********************************************************************/
28 #define _GLPSTD_STDIO
29 #define _GLPSTD_TIME
30 #include "glpmpl.h"
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 }
49 static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday",
50 "Friday", "Saturday", "Sunday" };
52 static char *moon[] = { "January", "February", "March", "April", "May",
53 "June", "July", "August", "September", "October", "November",
54 "December" };
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 }
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 }
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 }
293 static int weekday(int j)
294 { /* determine weekday number (1 = Mon, ..., 7 = Sun) */
295 return (j + jday(1, 1, 1970)) % 7 + 1;
296 }
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 }
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 }
562 /* eof */