/* * aegis - project change supervisor * Copyright (C) 1994, 1996 Peter Miller; * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * MANIFEST: impliment missing functions from <time.h> */ #include <ac/time.h> /* * NAME * strftime - string from time * * SYNOPSIS * size_t strftime(char *s, size_t maxsize, const char *format, * const struct tm *timeptr); * * DESCRIPTION * The strftime function places characters into the array pointed to * by s as controlled by the string pointed to by format. The format * string consists of zero or more directives and ordinary characters. * A directive consists of a % character followed by a character that * determined the dirrective's behaviour. All ordinary characters * (including the terminating null character) are copied unchanged * into the array. No more thaqn maxsize characters are placed into * the array. Each directive is replaced by appropriate characters as * described in the following list. The appropriate characters are * determined by the program's locale and by the values contained in * the structure pointed to by timeptr. * * %a is replaced by the locale's abbreviated weekday name * %A is replaced by the locale's full weekday name * %b is replaced by the locale's abbreviated month name * %B is replaced by the locale's full month name * %c is replaced by the locale's appropriae date and time representation * %d is replaced by the day of the month as decimal number (01-31) * %H is replaced by the hour (24-hour clock) as decimal number (00-23) * %I is replaced by the hour (12-hour clock) as decimal number (01-12) * %j is replaced by the day of te year as decimal number (001-366) * %m is replaced by the month as decomal number (01-12) * %M is replaced by the minute as decimal number (00-59) * %p is replaced by the locale's equivalent of either AM or PM * %S is replaced by the second as decimal number (00-59) * %U is replaced by the week number of they year (Sunday as the first * day of the week) as decimal number (00-52) * %w is replaced by the weekday as decimal number (0=Sunday to 6=Saturday) * %W is replaced by the week number of the year (Monday as the first * day of the week) as decimal number (00-52) * %x is replaced by the locale's appropriate date representation * %X is replaced by the locale's appropriate time representation * %y is replaced by the year without century as decimal number (00-99) * %Y is replaced by the year with century as decimal number * %Z is replaced by the time zone name, or no characters in no time * zone name is available * %% is replaced by % * * RETURNS * If the total number of resulting characters including the terminating * null character is not more than maxsize, the strftime function returns * the number of characters placed into the array pointed to by s not * including the terminating null character. Otherwise, zero is returned * and the contents of the array are indeterminate. * * CAVEAT * This suffers from a serious design flaw: there is no way to * distinguish between a result which is the empty string, and a result * which is more than maxsize characters. * * The behaviour for unknow directivbes is not only undefined, * it is unmentioned! (Normally the standard specifically allows * implementation defined behaviour on weird boundary conditions.) * This implementation will echo unknown directives into the output. */ #ifndef HAVE_STRFTIME #ifndef HAVE_tm_zone extern char *tzname[2]; #endif size_t strftime(buf, max, fmt, tm) char *buf; size_t max; char *fmt; struct tm *tm; { char *cp; char *end; char output[1000]; int n; size_t len; static char *weekday[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", }; static char *month[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }; end = buf + max - 1; cp = buf; while (*fmt) { if (*fmt++ != '%') { if (cp >= end) return 0; *cp++ = fmt[-1]; continue; } switch (*fmt++) { case 0: --fmt; output[0] = '%'; output[1] = 0; break; default: output[0] = '%'; output[1] = fmt[-1]; output[2] = 0; break; case '%': output[0] = '%'; output[1] = 0; break; case 'a': /* * the abbreviated weekday name */ sprintf(output, "%3.3s", weekday[tm->tm_wday]); break; case 'A': /* * the full weekday name */ strcpy(output, weekday[tm->tm_wday]); break; case 'b': case 'h': /* * the abbreviated month name */ sprintf(output, "%3.3s", month[tm->tm_mon]); break; case 'B': /* * the full month name */ strcpy(output, month[tm->tm_mon]); break; case 'c': /* * the date and time */ len = strftime(output, sizeof(output), "%b %e %X %Y", tm); if (!len) output[0] = 0; break; case 'C': /* * This looks like a Sun extra. * Local date. */ len = strftime(output, sizeof(output), "%A, %B %e, %Y", tm); if (!len) output[0] = 0; break; case 'd': /* * the day of the month, * zero padded. */ sprintf(output, "%2.2d", tm->tm_mday); break; case 'D': /* * This looks like a Sun extra. * Local date. */ len = strftime(output, sizeof(output), "%m/%d/%y", tm); if (!len) output[0] = 0; break; case 'e': /* * This looks like a Sun extra. * the day of the month, * blank padded. */ sprintf(output, "%2d", tm->tm_mday); break; case 'H': /* * the hour of a 24-hour day * zero padded */ sprintf(output, "%2.2d", tm->tm_hour); break; case 'I': /* * the hour of a 12-hour day, * zero padded */ n = tm->tm_hour % 12; sprintf(output, "%2.2d", n ? n : 12); break; case 'j': /* * the day of the year, * zero padded, one based */ sprintf(output, "%3.3d", tm->tm_yday + 1); break; case 'k': /* * This looks like a Sun extra. * the hour of the 24-hour day, * blank padded. */ sprintf(output, "%2d", tm->tm_hour); break; case 'l': /* * This looks like a Sun extra. * the hour of the 12-hour day, * blank padded. */ n = tm->tm_hour % 12; sprintf(output, "%2d", n ? n : 12); break; case 'm': /* * the month of the year, * zero padded, one based. */ sprintf(output, "%2.2d", tm->tm_mon + 1); break; case 'M': /* * the minute of the hour, * zero padded */ sprintf(output, "%2.2d", tm->tm_min); break; case 'n': /* * This looks like a Sun extra. * like \n */ output[0] = '\n'; output[1] = 0; break; case 'p': /* * meridian indicator */ if (tm->tm_hour >= 12) strcpy(output, "PM"); else strcpy(output, "AM"); break; case 'r': /* * this looks like a Sun extra. * like %X, but 12-hour clock with meridian. */ len = strftime(output, sizeof(output), "%I:%M:%S %p", tm); if (!len) output[0] = 0; break; case 'R': /* * this looks like a Sun extra. * the 24-hour time as HH:MM */ len = strftime(output, sizeof(output), "%H:%M", tm); if (!len) output[0] = 0; break; case 'S': /* * seconds of the minute */ sprintf(output, "%2.2d", tm->tm_sec); break; case 't': /* * this looks like a Sun extra. * like \t */ output[0] = '\t'; output[1] = 0; break; case 'T': /* * This looks like a Sun extra. * the 24-hour time as HH:MM:SS */ len = strftime(output, sizeof(output), "%H:%M:%S", tm); if (!len) output[0] = 0; break; case 'U': /* * the Sunday week of the year */ n = (tm->tm_yday - tm->tm_wday + 5) / 7; sprintf(output, "%2.2d", n); break; case 'w': /* * the day of the week, * Sunday = 0 */ sprintf(output, "%d", tm->tm_wday); break; case 'W': /* * the Monday week of the year */ n = (tm->tm_yday - ((tm->tm_wday + 6) % 7) + 5) / 7; sprintf(output, "%2.2d", n); break; case 'x': /* * the date, as mmm dd yyyy */ len = strftime(output, sizeof(output), "%b %d %Y", tm); if (!len) output[0] = 0; break; case 'X': /* * the time as hh:mm:ss */ len = strftime(output, sizeof(output), "%H:%M:%S", tm); if (!len) output[0] = 0; break; case 'y': /* * the year of the century */ sprintf(output, "%2.2d", tm->tm_year % 100); break; case 'Y': /* * the year including century */ sprintf(output, "%4.4d", tm->tm_year + 1900); break; case 'Z': /* * the timezone name, if any */ #ifndef HAVE_tm_zone if (tm->tm_isdst >= 0 && tm->tm_isdst <= 1) strcpy(output, tzname[tm->tm_isdst]); else output[0] = 0; #else /* Berkeley derivatives have extra tm field */ strcpy(output, tm->tm_zone); #endif break; } /* * make sure it fits in the buffer */ len = strlen(output); if (cp + len > end) return -1; memcpy(cp, output, len); cp += len; } *cp = 0; return (cp - buf); } #endif /* !HAVE_STRFTIME */