home *** CD-ROM | disk | FTP | other *** search
- From: arnold@audiofax.com (Arnold Robbins)
- Newsgroups: alt.sources
- Subject: beta release, pd ANSI strftime routine
- Message-ID: <325@audfax.audiofax.com>
- Date: 25 Jan 91 20:54:28 GMT
-
- The other day I wanted to use the ANSI C routine strftime. It's not
- in my C library, unfortunately. So I cobbled one up. Here it is. Please
- try it out, and let me know if you find any bugs. If there are none
- reported in the next week or so, I'll ship it out over one of the moderated
- source groups.
-
- As this is alt.sources, there is no man page or makefile. This compiles
- fine with both gcc and cc on my ESIX V.3.2 rev D system.
-
- It does assume System V for the timezone information.
- ---------------- cut here ---------------------
- /*
- * strftime.c
- *
- * Public-domain relatively quick-and-dirty implemenation of
- * ANSI library routine for System V Unix systems.
- *
- * It's written in old-style C for maximal portability.
- *
- * The code for %c, %x, and %X is my best guess as to what's "appropriate".
- * This version ignores LOCALE information.
- * It also doesn't worry about multi-byte characters.
- * So there.
- *
- * Arnold Robbins
- * January, 1991
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <time.h>
- #include <sys/types.h>
-
- #ifndef NULL
- #define NULL 0 /* the real programmer's definition */
- #endif
-
- #ifndef __STDC__
- #define const /**/
- #endif
-
- #ifndef __STDC__
- extern void tzset();
- extern int abs();
- static int weeknumber();
- #else
- extern void tzset(void);
- extern int abs(int val);
- static int weeknumber(const struct tm *timeptr, int firstweekday);
- #endif
-
- extern char *tzname[2];
- extern int daylight;
-
- #define L_DAYA 3 /* length of an abbreviated day name */
- #define L_MONA 3 /* length of an abbreviated month name */
-
-
- /* strftime --- produce formatted time */
-
- #ifndef __STDC__
- size_t
- strftime(s, maxsize, format, timeptr)
- char *s;
- size_t maxsize;
- const char *format;
- const struct tm *timeptr;
- #else
- size_t
- strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
- #endif
- {
- char *endp = s + maxsize;
- char *start = s;
- char tbuf[100];
- int i;
- static short first = 1;
-
- /* various tables, useful in North America */
- static char *days_a[] = {
- "Sun", "Mon", "Tue", "Wed",
- "Thu", "Fri", "Sat",
- };
- static char *days_l[] = {
- "Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday",
- };
- static char *months_a[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
- };
- static char *months_l[] = {
- "January", "February", "March", "April",
- "May", "June", "July", "August", "September",
- "October", "November", "December",
- };
-
- if (s == NULL || format == NULL || timeptr == NULL || maxsize <= 0)
- return 0;
-
- if (first) {
- first = 0;
- tzset();
- }
-
- for (; *format && s < endp - 1; format++) {
- tbuf[0] = '\0';
- if (*format != '%') {
- *s++ = *format;
- continue;
- }
- switch (*++format) {
- case '\0':
- break;
-
- case '%':
- *s++ = '%';
- continue;
-
- case 'a': /* abbreviated weekday name */
- if (s + L_DAYA < endp - 1) {
- *s++ = days_a[timeptr->tm_wday][0];
- *s++ = days_a[timeptr->tm_wday][1];
- *s++ = days_a[timeptr->tm_wday][2];
- } else
- goto out;
- break;
-
- case 'A': /* full weekday name */
- i = strlen(days_l[timeptr->tm_wday]);
- if (s + i < endp - 1) {
- strcpy(s, days_l[timeptr->tm_wday]);
- s += i;
- } else
- goto out;
- break;
-
- case 'b': /* abbreviated month name */
- if (s + L_MONA < endp - 1) {
- *s++ = months_a[timeptr->tm_mon][0];
- *s++ = months_a[timeptr->tm_mon][1];
- *s++ = months_a[timeptr->tm_mon][2];
- } else
- goto out;
- break;
-
- case 'B': /* full month name */
- i = strlen(months_l[timeptr->tm_mon]);
- if (s + i < endp - 1) {
- strcpy(s, months_l[timeptr->tm_mon]);
- s += i;
- } else
- goto out;
- break;
-
- case 'c': /* appropriate date and time representation */
- sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
- days_a[timeptr->tm_wday],
- months_a[timeptr->tm_mon],
- timeptr->tm_mday,
- timeptr->tm_hour,
- timeptr->tm_min,
- timeptr->tm_sec,
- timeptr->tm_year + 1900);
- break;
-
- case 'd': /* day of the month, 01 - 31 */
- sprintf(tbuf, "%02d", timeptr->tm_mday);
- break;
-
- case 'H': /* hour, 24-hour clock, 00 - 23 */
- sprintf(tbuf, "%02d", timeptr->tm_hour);
- break;
-
- case 'I': /* hour, 12-hour clock, 01 - 12 */
- i = timeptr->tm_hour;
- if (i == 0)
- i = 12;
- else if (i > 12)
- i -= 12;
- sprintf(tbuf, "%02d", i);
- break;
-
- case 'j': /* day of the year, 001 - 366 */
- sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
- break;
-
- case 'm': /* month, 01 - 12 */
- sprintf(tbuf, "%02d", timeptr->tm_mon + 1);
- break;
-
- case 'M': /* minute, 00 - 59 */
- sprintf(tbuf, "%02d", timeptr->tm_min);
- break;
-
- case 'p': /* am or pm based on 12-hour clock */
- if (timeptr->tm_hour < 12)
- strcpy(tbuf, "a.m.");
- else
- strcpy(tbuf, "p.m.");
- break;
-
- case 'S': /* second, 00 - 61 */
- sprintf(tbuf, "%02d", timeptr->tm_sec);
- break;
-
- case 'U': /* week of year, Sunday is first day of week */
- sprintf(tbuf, "%d", weeknumber(timeptr, 0));
- break;
-
- case 'w': /* weekday, Sunday == 0, 0 - 6 */
- sprintf(tbuf, "%d", timeptr->tm_wday);
- break;
-
- case 'W': /* week of year, Monday is first day of week */
- sprintf(tbuf, "%d", weeknumber(timeptr, 1));
- break;
-
- case 'x': /* appropriate date representation */
- sprintf(tbuf, "%s %s %2d %d",
- days_a[timeptr->tm_wday],
- months_a[timeptr->tm_mon],
- timeptr->tm_mday,
- timeptr->tm_year + 1900);
- break;
-
- case 'X': /* appropriate time representation */
- sprintf(tbuf, "%02d:%02d:%02d",
- timeptr->tm_hour,
- timeptr->tm_min,
- timeptr->tm_sec);
- break;
-
- case 'y': /* year without a century, 00 - 99 */
- i = timeptr->tm_year % 100;
- sprintf(tbuf, "%d", i);
- break;
-
- case 'Y': /* year with century */
- sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
- break;
-
- case 'Z': /* time zone name or abbrevation */
- i = 0;
- if (daylight && timeptr->tm_isdst)
- i = 1;
- strcpy(tbuf, tzname[i]);
- break;
-
- default:
- /* do something reasonable */
- if (s + 2 < endp - 1) {
- *s++ = '%';
- *s++ = *format;
- } else
- goto out;
- continue;
- }
- i = strlen(tbuf);
- if (i)
- if (s + i < endp - 1) {
- strcpy(s, tbuf);
- s += i;
- } else
- break; /* the for loop */
- }
- out:
- if (s < endp) {
- *s = '\0';
- return (s - start - 1);
- } else
- return 0;
- }
-
- /* weeknumber --- figure how many weeks into the year */
-
- #ifndef __STDC__
- static int
- weeknumber(timeptr, firstweekday)
- const struct tm *timeptr;
- int firstweekday;
- #else
- static int
- weeknumber(const struct tm *timeptr, int firstweekday)
- #endif
- {
- int m, drift, r;
-
- /* days into the current 7-day period */
- m = timeptr->tm_yday % 7;
-
- /* special case the first week */
- if (m == timeptr->tm_yday)
- if (timeptr->tm_wday >= firstweekday)
- return 1;
- else
- return 0;
-
- /* how many days away from Sunday or Monday the year started */
- drift = timeptr->tm_wday - m + firstweekday;
- drift = abs(drift);
-
- r = (timeptr->tm_yday - drift) / 7;
-
- return r;
- }
- --
- Arnold Robbins AudioFAX, Inc. | Laundry increases
- 2000 Powers Ferry Road, #200 / Marietta, GA. 30067 | exponentially in the
- INTERNET: arnold@audiofax.com Phone: +1 404 933 7612 | number of children.
- UUCP: emory!audfax!arnold Fax-box: +1 404 618 4581 | -- Miriam Robbins
-