COIN-OR::LEMON - Graph Library

source: glpk-cmake/src/glpmpl05.c @ 2:4c8956a7bdf4

Last change on this file since 2:4c8956a7bdf4 was 1:c445c931472f, checked in by Alpar Juttner <alpar@…>, 13 years ago

Import glpk-4.45

  • Generated files and doc/notes are removed
File size: 21.7 KB
Line 
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
32double 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))
39err:     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
49static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday",
50      "Friday", "Saturday", "Sunday" };
51
52static char *moon[] = { "January", "February", "March", "April", "May",
53      "June", "July", "August", "September", "October", "November",
54      "December" };
55
56static 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
68double 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;
98next:             ;
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'))
234err1:                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)
239err2:             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;
252skip:          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
265test:    {  /* 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
284static 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
293static int weekday(int j)
294{     /* determine weekday number (1 = Mon, ..., 7 = Sun) */
295      return (j + jday(1, 1, 1970)) % 7 + 1;
296}
297
298static 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
321void 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 */
Note: See TracBrowser for help on using the repository browser.