1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/glpmpl05.c Mon Dec 06 13:09:21 2010 +0100
1.3 @@ -0,0 +1,562 @@
1.4 +/* glpmpl05.c */
1.5 +
1.6 +/***********************************************************************
1.7 +* This code is part of GLPK (GNU Linear Programming Kit).
1.8 +*
1.9 +* Authors: Andrew Makhorin <mao@gnu.org>
1.10 +* Heinrich Schuchardt <xypron.glpk@gmx.de>
1.11 +*
1.12 +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
1.13 +* 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
1.14 +* Moscow Aviation Institute, Moscow, Russia. All rights reserved.
1.15 +* E-mail: <mao@gnu.org>.
1.16 +*
1.17 +* GLPK is free software: you can redistribute it and/or modify it
1.18 +* under the terms of the GNU General Public License as published by
1.19 +* the Free Software Foundation, either version 3 of the License, or
1.20 +* (at your option) any later version.
1.21 +*
1.22 +* GLPK is distributed in the hope that it will be useful, but WITHOUT
1.23 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.24 +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1.25 +* License for more details.
1.26 +*
1.27 +* You should have received a copy of the GNU General Public License
1.28 +* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
1.29 +***********************************************************************/
1.30 +
1.31 +#define _GLPSTD_STDIO
1.32 +#define _GLPSTD_TIME
1.33 +#include "glpmpl.h"
1.34 +
1.35 +double fn_gmtime(MPL *mpl)
1.36 +{ /* obtain the current calendar time (UTC) */
1.37 + time_t timer;
1.38 + struct tm *tm;
1.39 + int j;
1.40 + time(&timer);
1.41 + if (timer == (time_t)(-1))
1.42 +err: error(mpl, "gmtime(); unable to obtain current calendar time");
1.43 + tm = gmtime(&timer);
1.44 + if (tm == NULL) goto err;
1.45 + j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year);
1.46 + if (j < 0) goto err;
1.47 + return (((double)(j - jday(1, 1, 1970)) * 24.0 +
1.48 + (double)tm->tm_hour) * 60.0 + (double)tm->tm_min) * 60.0 +
1.49 + (double)tm->tm_sec;
1.50 +}
1.51 +
1.52 +static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday",
1.53 + "Friday", "Saturday", "Sunday" };
1.54 +
1.55 +static char *moon[] = { "January", "February", "March", "April", "May",
1.56 + "June", "July", "August", "September", "October", "November",
1.57 + "December" };
1.58 +
1.59 +static void error1(MPL *mpl, const char *str, const char *s,
1.60 + const char *fmt, const char *f, const char *msg)
1.61 +{ xprintf("Input string passed to str2time:\n");
1.62 + xprintf("%s\n", str);
1.63 + xprintf("%*s\n", (s - str) + 1, "^");
1.64 + xprintf("Format string passed to str2time:\n");
1.65 + xprintf("%s\n", fmt);
1.66 + xprintf("%*s\n", (f - fmt) + 1, "^");
1.67 + error(mpl, "%s", msg);
1.68 + /* no return */
1.69 +}
1.70 +
1.71 +double fn_str2time(MPL *mpl, const char *str, const char *fmt)
1.72 +{ /* convert character string to the calendar time */
1.73 + int j, year, month, day, hh, mm, ss, zone;
1.74 + const char *s, *f;
1.75 + year = month = day = hh = mm = ss = -1, zone = INT_MAX;
1.76 + s = str;
1.77 + for (f = fmt; *f != '\0'; f++)
1.78 + { if (*f == '%')
1.79 + { f++;
1.80 + if (*f == 'b' || *f == 'h')
1.81 + { /* the abbreviated month name */
1.82 + int k;
1.83 + char *name;
1.84 + if (month >= 0)
1.85 + error1(mpl, str, s, fmt, f, "month multiply specified"
1.86 + );
1.87 + while (*s == ' ') s++;
1.88 + for (month = 1; month <= 12; month++)
1.89 + { name = moon[month-1];
1.90 + for (k = 0; k <= 2; k++)
1.91 + { if (toupper((unsigned char)s[k]) !=
1.92 + toupper((unsigned char)name[k])) goto next;
1.93 + }
1.94 + s += 3;
1.95 + for (k = 3; name[k] != '\0'; k++)
1.96 + { if (toupper((unsigned char)*s) !=
1.97 + toupper((unsigned char)name[k])) break;
1.98 + s++;
1.99 + }
1.100 + break;
1.101 +next: ;
1.102 + }
1.103 + if (month > 12)
1.104 + error1(mpl, str, s, fmt, f, "abbreviated month name m"
1.105 + "issing or invalid");
1.106 + }
1.107 + else if (*f == 'd')
1.108 + { /* the day of the month as a decimal number (01..31) */
1.109 + if (day >= 0)
1.110 + error1(mpl, str, s, fmt, f, "day multiply specified");
1.111 + while (*s == ' ') s++;
1.112 + if (!('0' <= *s && *s <= '9'))
1.113 + error1(mpl, str, s, fmt, f, "day missing or invalid");
1.114 + day = (*s++) - '0';
1.115 + if ('0' <= *s && *s <= '9')
1.116 + day = 10 * day + ((*s++) - '0');
1.117 + if (!(1 <= day && day <= 31))
1.118 + error1(mpl, str, s, fmt, f, "day out of range");
1.119 + }
1.120 + else if (*f == 'H')
1.121 + { /* the hour as a decimal number, using a 24-hour clock
1.122 + (00..23) */
1.123 + if (hh >= 0)
1.124 + error1(mpl, str, s, fmt, f, "hour multiply specified")
1.125 + ;
1.126 + while (*s == ' ') s++;
1.127 + if (!('0' <= *s && *s <= '9'))
1.128 + error1(mpl, str, s, fmt, f, "hour missing or invalid")
1.129 + ;
1.130 + hh = (*s++) - '0';
1.131 + if ('0' <= *s && *s <= '9')
1.132 + hh = 10 * hh + ((*s++) - '0');
1.133 + if (!(0 <= hh && hh <= 23))
1.134 + error1(mpl, str, s, fmt, f, "hour out of range");
1.135 + }
1.136 + else if (*f == 'm')
1.137 + { /* the month as a decimal number (01..12) */
1.138 + if (month >= 0)
1.139 + error1(mpl, str, s, fmt, f, "month multiply specified"
1.140 + );
1.141 + while (*s == ' ') s++;
1.142 + if (!('0' <= *s && *s <= '9'))
1.143 + error1(mpl, str, s, fmt, f, "month missing or invalid"
1.144 + );
1.145 + month = (*s++) - '0';
1.146 + if ('0' <= *s && *s <= '9')
1.147 + month = 10 * month + ((*s++) - '0');
1.148 + if (!(1 <= month && month <= 12))
1.149 + error1(mpl, str, s, fmt, f, "month out of range");
1.150 + }
1.151 + else if (*f == 'M')
1.152 + { /* the minute as a decimal number (00..59) */
1.153 + if (mm >= 0)
1.154 + error1(mpl, str, s, fmt, f, "minute multiply specifie"
1.155 + "d");
1.156 + while (*s == ' ') s++;
1.157 + if (!('0' <= *s && *s <= '9'))
1.158 + error1(mpl, str, s, fmt, f, "minute missing or invali"
1.159 + "d");
1.160 + mm = (*s++) - '0';
1.161 + if ('0' <= *s && *s <= '9')
1.162 + mm = 10 * mm + ((*s++) - '0');
1.163 + if (!(0 <= mm && mm <= 59))
1.164 + error1(mpl, str, s, fmt, f, "minute out of range");
1.165 + }
1.166 + else if (*f == 'S')
1.167 + { /* the second as a decimal number (00..60) */
1.168 + if (ss >= 0)
1.169 + error1(mpl, str, s, fmt, f, "second multiply specifie"
1.170 + "d");
1.171 + while (*s == ' ') s++;
1.172 + if (!('0' <= *s && *s <= '9'))
1.173 + error1(mpl, str, s, fmt, f, "second missing or invali"
1.174 + "d");
1.175 + ss = (*s++) - '0';
1.176 + if ('0' <= *s && *s <= '9')
1.177 + ss = 10 * ss + ((*s++) - '0');
1.178 + if (!(0 <= ss && ss <= 60))
1.179 + error1(mpl, str, s, fmt, f, "second out of range");
1.180 + }
1.181 + else if (*f == 'y')
1.182 + { /* the year without a century as a decimal number
1.183 + (00..99); the values 00 to 68 mean the years 2000 to
1.184 + 2068 while the values 69 to 99 mean the years 1969 to
1.185 + 1999 */
1.186 + if (year >= 0)
1.187 + error1(mpl, str, s, fmt, f, "year multiply specified")
1.188 + ;
1.189 + while (*s == ' ') s++;
1.190 + if (!('0' <= *s && *s <= '9'))
1.191 + error1(mpl, str, s, fmt, f, "year missing or invalid")
1.192 + ;
1.193 + year = (*s++) - '0';
1.194 + if ('0' <= *s && *s <= '9')
1.195 + year = 10 * year + ((*s++) - '0');
1.196 + year += (year >= 69 ? 1900 : 2000);
1.197 + }
1.198 + else if (*f == 'Y')
1.199 + { /* the year as a decimal number, using the Gregorian
1.200 + calendar */
1.201 + if (year >= 0)
1.202 + error1(mpl, str, s, fmt, f, "year multiply specified")
1.203 + ;
1.204 + while (*s == ' ') s++;
1.205 + if (!('0' <= *s && *s <= '9'))
1.206 + error1(mpl, str, s, fmt, f, "year missing or invalid")
1.207 + ;
1.208 + year = 0;
1.209 + for (j = 1; j <= 4; j++)
1.210 + { if (!('0' <= *s && *s <= '9')) break;
1.211 + year = 10 * year + ((*s++) - '0');
1.212 + }
1.213 + if (!(1 <= year && year <= 4000))
1.214 + error1(mpl, str, s, fmt, f, "year out of range");
1.215 + }
1.216 + else if (*f == 'z')
1.217 + { /* time zone offset in the form zhhmm */
1.218 + int z, hh, mm;
1.219 + if (zone != INT_MAX)
1.220 + error1(mpl, str, s, fmt, f, "time zone offset multipl"
1.221 + "y specified");
1.222 + while (*s == ' ') s++;
1.223 + if (*s == 'Z')
1.224 + { z = hh = mm = 0, s++;
1.225 + goto skip;
1.226 + }
1.227 + if (*s == '+')
1.228 + z = +1, s++;
1.229 + else if (*s == '-')
1.230 + z = -1, s++;
1.231 + else
1.232 + error1(mpl, str, s, fmt, f, "time zone offset sign mi"
1.233 + "ssing");
1.234 + hh = 0;
1.235 + for (j = 1; j <= 2; j++)
1.236 + { if (!('0' <= *s && *s <= '9'))
1.237 +err1: error1(mpl, str, s, fmt, f, "time zone offset valu"
1.238 + "e incomplete or invalid");
1.239 + hh = 10 * hh + ((*s++) - '0');
1.240 + }
1.241 + if (hh > 23)
1.242 +err2: error1(mpl, str, s, fmt, f, "time zone offset value o"
1.243 + "ut of range");
1.244 + if (*s == ':')
1.245 + { s++;
1.246 + if (!('0' <= *s && *s <= '9')) goto err1;
1.247 + }
1.248 + mm = 0;
1.249 + if (!('0' <= *s && *s <= '9')) goto skip;
1.250 + for (j = 1; j <= 2; j++)
1.251 + { if (!('0' <= *s && *s <= '9')) goto err1;
1.252 + mm = 10 * mm + ((*s++) - '0');
1.253 + }
1.254 + if (mm > 59) goto err2;
1.255 +skip: zone = z * (60 * hh + mm);
1.256 + }
1.257 + else if (*f == '%')
1.258 + { /* literal % character */
1.259 + goto test;
1.260 + }
1.261 + else
1.262 + error1(mpl, str, s, fmt, f, "invalid conversion specifie"
1.263 + "r");
1.264 + }
1.265 + else if (*f == ' ')
1.266 + ;
1.267 + else
1.268 +test: { /* check a matching character in the input string */
1.269 + if (*s != *f)
1.270 + error1(mpl, str, s, fmt, f, "character mismatch");
1.271 + s++;
1.272 + }
1.273 + }
1.274 + if (year < 0) year = 1970;
1.275 + if (month < 0) month = 1;
1.276 + if (day < 0) day = 1;
1.277 + if (hh < 0) hh = 0;
1.278 + if (mm < 0) mm = 0;
1.279 + if (ss < 0) ss = 0;
1.280 + if (zone == INT_MAX) zone = 0;
1.281 + j = jday(day, month, year);
1.282 + xassert(j >= 0);
1.283 + return (((double)(j - jday(1, 1, 1970)) * 24.0 + (double)hh) *
1.284 + 60.0 + (double)mm) * 60.0 + (double)ss - 60.0 * (double)zone;
1.285 +}
1.286 +
1.287 +static void error2(MPL *mpl, const char *fmt, const char *f,
1.288 + const char *msg)
1.289 +{ xprintf("Format string passed to time2str:\n");
1.290 + xprintf("%s\n", fmt);
1.291 + xprintf("%*s\n", (f - fmt) + 1, "^");
1.292 + error(mpl, "%s", msg);
1.293 + /* no return */
1.294 +}
1.295 +
1.296 +static int weekday(int j)
1.297 +{ /* determine weekday number (1 = Mon, ..., 7 = Sun) */
1.298 + return (j + jday(1, 1, 1970)) % 7 + 1;
1.299 +}
1.300 +
1.301 +static int firstday(int year)
1.302 +{ /* determine the first day of the first week for a specified year
1.303 + according to ISO 8601 */
1.304 + int j;
1.305 + /* if 1 January is Monday, Tuesday, Wednesday or Thursday, it is
1.306 + in week 01; if 1 January is Friday, Saturday or Sunday, it is
1.307 + in week 52 or 53 of the previous year */
1.308 + j = jday(1, 1, year) - jday(1, 1, 1970);
1.309 + switch (weekday(j))
1.310 + { case 1: /* 1 Jan is Mon */ j += 0; break;
1.311 + case 2: /* 1 Jan is Tue */ j -= 1; break;
1.312 + case 3: /* 1 Jan is Wed */ j -= 2; break;
1.313 + case 4: /* 1 Jan is Thu */ j -= 3; break;
1.314 + case 5: /* 1 Jan is Fri */ j += 3; break;
1.315 + case 6: /* 1 Jan is Sat */ j += 2; break;
1.316 + case 7: /* 1 Jan is Sun */ j += 1; break;
1.317 + default: xassert(j != j);
1.318 + }
1.319 + /* the first day of the week must be Monday */
1.320 + xassert(weekday(j) == 1);
1.321 + return j;
1.322 +}
1.323 +
1.324 +void fn_time2str(MPL *mpl, char *str, double t, const char *fmt)
1.325 +{ /* convert the calendar time to character string */
1.326 + int j, year, month, day, hh, mm, ss, len;
1.327 + double temp;
1.328 + const char *f;
1.329 + char buf[MAX_LENGTH+1];
1.330 + if (!(-62135596800.0 <= t && t <= 64092211199.0))
1.331 + error(mpl, "time2str(%.*g,...); argument out of range",
1.332 + DBL_DIG, t);
1.333 + t = floor(t + 0.5);
1.334 + temp = fabs(t) / 86400.0;
1.335 + j = (int)floor(temp);
1.336 + if (t < 0.0)
1.337 + { if (temp == floor(temp))
1.338 + j = - j;
1.339 + else
1.340 + j = - (j + 1);
1.341 + }
1.342 + xassert(jdate(j + jday(1, 1, 1970), &day, &month, &year) == 0);
1.343 + ss = (int)(t - 86400.0 * (double)j);
1.344 + xassert(0 <= ss && ss < 86400);
1.345 + mm = ss / 60, ss %= 60;
1.346 + hh = mm / 60, mm %= 60;
1.347 + len = 0;
1.348 + for (f = fmt; *f != '\0'; f++)
1.349 + { if (*f == '%')
1.350 + { f++;
1.351 + if (*f == 'a')
1.352 + { /* the abbreviated weekday name */
1.353 + memcpy(buf, week[weekday(j)-1], 3), buf[3] = '\0';
1.354 + }
1.355 + else if (*f == 'A')
1.356 + { /* the full weekday name */
1.357 + strcpy(buf, week[weekday(j)-1]);
1.358 + }
1.359 + else if (*f == 'b' || *f == 'h')
1.360 + { /* the abbreviated month name */
1.361 + memcpy(buf, moon[month-1], 3), buf[3] = '\0';
1.362 + }
1.363 + else if (*f == 'B')
1.364 + { /* the full month name */
1.365 + strcpy(buf, moon[month-1]);
1.366 + }
1.367 + else if (*f == 'C')
1.368 + { /* the century of the year */
1.369 + sprintf(buf, "%02d", year / 100);
1.370 + }
1.371 + else if (*f == 'd')
1.372 + { /* the day of the month as a decimal number (01..31) */
1.373 + sprintf(buf, "%02d", day);
1.374 + }
1.375 + else if (*f == 'D')
1.376 + { /* the date using the format %m/%d/%y */
1.377 + sprintf(buf, "%02d/%02d/%02d", month, day, year % 100);
1.378 + }
1.379 + else if (*f == 'e')
1.380 + { /* the day of the month like with %d, but padded with
1.381 + blank (1..31) */
1.382 + sprintf(buf, "%2d", day);
1.383 + }
1.384 + else if (*f == 'F')
1.385 + { /* the date using the format %Y-%m-%d */
1.386 + sprintf(buf, "%04d-%02d-%02d", year, month, day);
1.387 + }
1.388 + else if (*f == 'g')
1.389 + { /* the year corresponding to the ISO week number, but
1.390 + without the century (range 00 through 99); this has
1.391 + the same format and value as %y, except that if the
1.392 + ISO week number (see %V) belongs to the previous or
1.393 + next year, that year is used instead */
1.394 + int iso;
1.395 + if (j < firstday(year))
1.396 + iso = year - 1;
1.397 + else if (j < firstday(year + 1))
1.398 + iso = year;
1.399 + else
1.400 + iso = year + 1;
1.401 + sprintf(buf, "%02d", iso % 100);
1.402 + }
1.403 + else if (*f == 'G')
1.404 + { /* the year corresponding to the ISO week number; this
1.405 + has the same format and value as %Y, excepth that if
1.406 + the ISO week number (see %V) belongs to the previous
1.407 + or next year, that year is used instead */
1.408 + int iso;
1.409 + if (j < firstday(year))
1.410 + iso = year - 1;
1.411 + else if (j < firstday(year + 1))
1.412 + iso = year;
1.413 + else
1.414 + iso = year + 1;
1.415 + sprintf(buf, "%04d", iso);
1.416 + }
1.417 + else if (*f == 'H')
1.418 + { /* the hour as a decimal number, using a 24-hour clock
1.419 + (00..23) */
1.420 + sprintf(buf, "%02d", hh);
1.421 + }
1.422 + else if (*f == 'I')
1.423 + { /* the hour as a decimal number, using a 12-hour clock
1.424 + (01..12) */
1.425 + sprintf(buf, "%02d",
1.426 + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12);
1.427 + }
1.428 + else if (*f == 'j')
1.429 + { /* the day of the year as a decimal number (001..366) */
1.430 + sprintf(buf, "%03d",
1.431 + jday(day, month, year) - jday(1, 1, year) + 1);
1.432 + }
1.433 + else if (*f == 'k')
1.434 + { /* the hour as a decimal number, using a 24-hour clock
1.435 + like %H, but padded with blank (0..23) */
1.436 + sprintf(buf, "%2d", hh);
1.437 + }
1.438 + else if (*f == 'l')
1.439 + { /* the hour as a decimal number, using a 12-hour clock
1.440 + like %I, but padded with blank (1..12) */
1.441 + sprintf(buf, "%2d",
1.442 + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12);
1.443 + }
1.444 + else if (*f == 'm')
1.445 + { /* the month as a decimal number (01..12) */
1.446 + sprintf(buf, "%02d", month);
1.447 + }
1.448 + else if (*f == 'M')
1.449 + { /* the minute as a decimal number (00..59) */
1.450 + sprintf(buf, "%02d", mm);
1.451 + }
1.452 + else if (*f == 'p')
1.453 + { /* either AM or PM, according to the given time value;
1.454 + noon is treated as PM and midnight as AM */
1.455 + strcpy(buf, hh <= 11 ? "AM" : "PM");
1.456 + }
1.457 + else if (*f == 'P')
1.458 + { /* either am or pm, according to the given time value;
1.459 + noon is treated as pm and midnight as am */
1.460 + strcpy(buf, hh <= 11 ? "am" : "pm");
1.461 + }
1.462 + else if (*f == 'r')
1.463 + { /* the calendar time using the format %I:%M:%S %p */
1.464 + sprintf(buf, "%02d:%02d:%02d %s",
1.465 + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12,
1.466 + mm, ss, hh <= 11 ? "AM" : "PM");
1.467 + }
1.468 + else if (*f == 'R')
1.469 + { /* the hour and minute using the format %H:%M */
1.470 + sprintf(buf, "%02d:%02d", hh, mm);
1.471 + }
1.472 + else if (*f == 'S')
1.473 + { /* the second as a decimal number (00..59) */
1.474 + sprintf(buf, "%02d", ss);
1.475 + }
1.476 + else if (*f == 'T')
1.477 + { /* the time of day using the format %H:%M:%S */
1.478 + sprintf(buf, "%02d:%02d:%02d", hh, mm, ss);
1.479 + }
1.480 + else if (*f == 'u')
1.481 + { /* the day of the week as a decimal number (1..7),
1.482 + Monday being 1 */
1.483 + sprintf(buf, "%d", weekday(j));
1.484 + }
1.485 + else if (*f == 'U')
1.486 + { /* the week number of the current year as a decimal
1.487 + number (range 00 through 53), starting with the first
1.488 + Sunday as the first day of the first week; days
1.489 + preceding the first Sunday in the year are considered
1.490 + to be in week 00 */
1.491 +#if 1 /* 09/I-2009 */
1.492 +#undef sun
1.493 +/* causes compilation error in SunOS */
1.494 +#endif
1.495 + int sun;
1.496 + /* sun = the first Sunday of the year */
1.497 + sun = jday(1, 1, year) - jday(1, 1, 1970);
1.498 + sun += (7 - weekday(sun));
1.499 + sprintf(buf, "%02d", (j + 7 - sun) / 7);
1.500 + }
1.501 + else if (*f == 'V')
1.502 + { /* the ISO week number as a decimal number (range 01
1.503 + through 53); ISO weeks start with Monday and end with
1.504 + Sunday; week 01 of a year is the first week which has
1.505 + the majority of its days in that year; week 01 of
1.506 + a year can contain days from the previous year; the
1.507 + week before week 01 of a year is the last week (52 or
1.508 + 53) of the previous year even if it contains days
1.509 + from the new year */
1.510 + int iso;
1.511 + if (j < firstday(year))
1.512 + iso = j - firstday(year - 1);
1.513 + else if (j < firstday(year + 1))
1.514 + iso = j - firstday(year);
1.515 + else
1.516 + iso = j - firstday(year + 1);
1.517 + sprintf(buf, "%02d", iso / 7 + 1);
1.518 + }
1.519 + else if (*f == 'w')
1.520 + { /* the day of the week as a decimal number (0..6),
1.521 + Sunday being 0 */
1.522 + sprintf(buf, "%d", weekday(j) % 7);
1.523 + }
1.524 + else if (*f == 'W')
1.525 + { /* the week number of the current year as a decimal
1.526 + number (range 00 through 53), starting with the first
1.527 + Monday as the first day of the first week; days
1.528 + preceding the first Monday in the year are considered
1.529 + to be in week 00 */
1.530 + int mon;
1.531 + /* mon = the first Monday of the year */
1.532 + mon = jday(1, 1, year) - jday(1, 1, 1970);
1.533 + mon += (8 - weekday(mon)) % 7;
1.534 + sprintf(buf, "%02d", (j + 7 - mon) / 7);
1.535 + }
1.536 + else if (*f == 'y')
1.537 + { /* the year without a century as a decimal number
1.538 + (00..99) */
1.539 + sprintf(buf, "%02d", year % 100);
1.540 + }
1.541 + else if (*f == 'Y')
1.542 + { /* the year as a decimal number, using the Gregorian
1.543 + calendar */
1.544 + sprintf(buf, "%04d", year);
1.545 + }
1.546 + else if (*f == '%')
1.547 + { /* a literal % character */
1.548 + buf[0] = '%', buf[1] = '\0';
1.549 + }
1.550 + else
1.551 + error2(mpl, fmt, f, "invalid conversion specifier");
1.552 + }
1.553 + else
1.554 + buf[0] = *f, buf[1] = '\0';
1.555 + if (len + strlen(buf) > MAX_LENGTH)
1.556 + error(mpl, "time2str; output string length exceeds %d chara"
1.557 + "cters", MAX_LENGTH);
1.558 + memcpy(str+len, buf, strlen(buf));
1.559 + len += strlen(buf);
1.560 + }
1.561 + str[len] = '\0';
1.562 + return;
1.563 +}
1.564 +
1.565 +/* eof */