src/glpmpl05.c
changeset 1 c445c931472f
equal deleted inserted replaced
-1:000000000000 0:3cc40fb903b8
       
     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 
       
    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 }
       
    48 
       
    49 static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday",
       
    50       "Friday", "Saturday", "Sunday" };
       
    51 
       
    52 static char *moon[] = { "January", "February", "March", "April", "May",
       
    53       "June", "July", "August", "September", "October", "November",
       
    54       "December" };
       
    55 
       
    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 }
       
    67 
       
    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 }
       
   283 
       
   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 }
       
   292 
       
   293 static int weekday(int j)
       
   294 {     /* determine weekday number (1 = Mon, ..., 7 = Sun) */
       
   295       return (j + jday(1, 1, 1970)) % 7 + 1;
       
   296 }
       
   297 
       
   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 }
       
   320 
       
   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 }
       
   561 
       
   562 /* eof */