src/glpmpl05.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

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