|
Packit |
667938 |
/**
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* strftime.c
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* implements the ansi c function strftime()
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* written 6 september 1989 by jim nutt
|
|
Packit |
667938 |
* released into the public domain by jim nutt
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* modified 21-Oct-89 by Rob Duff
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* modified 08-Dec-04 by Tobi Oetiker (added %V)
|
|
Packit |
667938 |
**/
|
|
Packit |
667938 |
|
|
Packit |
667938 |
#include <stddef.h> /* for size_t */
|
|
Packit |
667938 |
#include <stdarg.h> /* for va_arg */
|
|
Packit |
667938 |
#include <time.h> /* for struct tm */
|
|
Packit |
667938 |
#include "strftime.h"
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static char *aday[] = {
|
|
Packit |
667938 |
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
|
Packit |
667938 |
};
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static char *day[] = {
|
|
Packit |
667938 |
"Sunday", "Monday", "Tuesday", "Wednesday",
|
|
Packit |
667938 |
"Thursday", "Friday", "Saturday"
|
|
Packit |
667938 |
};
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static char *amonth[] = {
|
|
Packit |
667938 |
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
Packit |
667938 |
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|
Packit |
667938 |
};
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static char *month[] = {
|
|
Packit |
667938 |
"January", "February", "March", "April", "May", "June",
|
|
Packit |
667938 |
"July", "August", "September", "October", "November", "December"
|
|
Packit |
667938 |
};
|
|
Packit |
667938 |
|
|
Packit |
667938 |
char *tzname_[2] = {"CST", "CDT"}; /* Add your own defaults here */
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static char buf[26];
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static void strfmt(char *str, const char *fmt, ...);
|
|
Packit |
667938 |
|
|
Packit |
667938 |
/**
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* size_t strftime_(char *str,
|
|
Packit |
667938 |
* size_t maxs,
|
|
Packit |
667938 |
* const char *fmt,
|
|
Packit |
667938 |
* const struct tm *t)
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* this functions acts much like a sprintf for time/date output.
|
|
Packit |
667938 |
* given a pointer to an output buffer, a format string and a
|
|
Packit |
667938 |
* time, it copies the time to the output buffer formatted in
|
|
Packit |
667938 |
* accordance with the format string. the parameters are used
|
|
Packit |
667938 |
* as follows:
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* str is a pointer to the output buffer, there should
|
|
Packit |
667938 |
* be at least maxs characters available at the address
|
|
Packit |
667938 |
* pointed to by str.
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* maxs is the maximum number of characters to be copied
|
|
Packit |
667938 |
* into the output buffer, included the '\0' terminator
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* fmt is the format string. a percent sign (%) is used
|
|
Packit |
667938 |
* to indicate that the following character is a special
|
|
Packit |
667938 |
* format character. the following are valid format
|
|
Packit |
667938 |
* characters:
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* %A full weekday name (Monday)
|
|
Packit |
667938 |
* %a abbreviated weekday name (Mon)
|
|
Packit |
667938 |
* %B full month name (January)
|
|
Packit |
667938 |
* %b abbreviated month name (Jan)
|
|
Packit |
667938 |
* %c standard date and time representation
|
|
Packit |
667938 |
* %d day-of-month (01-31)
|
|
Packit |
667938 |
* %H hour (24 hour clock) (00-23)
|
|
Packit |
667938 |
* %I hour (12 hour clock) (01-12)
|
|
Packit |
667938 |
* %j day-of-year (001-366)
|
|
Packit |
667938 |
* %M minute (00-59)
|
|
Packit |
667938 |
* %m month (01-12)
|
|
Packit |
667938 |
* %p local equivalent of AM or PM
|
|
Packit |
667938 |
* %S second (00-59)
|
|
Packit |
667938 |
* %U week-of-year, first day sunday (00-53)
|
|
Packit |
667938 |
* %W week-of-year, first day monday (00-53)
|
|
Packit |
667938 |
* %V ISO 8601 Week number
|
|
Packit |
667938 |
* %w weekday (0-6, sunday is 0)
|
|
Packit |
667938 |
* %X standard time representation
|
|
Packit |
667938 |
* %x standard date representation
|
|
Packit |
667938 |
* %Y year with century
|
|
Packit |
667938 |
* %y year without century (00-99)
|
|
Packit |
667938 |
* %Z timezone name
|
|
Packit |
667938 |
* %% percent sign
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* the standard date string is equivalent to:
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* %a %b %d %Y
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* the standard time string is equivalent to:
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* %H:%M:%S
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* the standard date and time string is equivalent to:
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* %a %b %d %H:%M:%S %Y
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* strftime_() returns the number of characters placed in the
|
|
Packit |
667938 |
* buffer, not including the terminating \0, or zero if more
|
|
Packit |
667938 |
* than maxs characters were produced.
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
**/
|
|
Packit |
667938 |
|
|
Packit |
667938 |
size_t strftime_(char *s, size_t maxs, const char *f, const struct tm *t)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
int w,d;
|
|
Packit |
667938 |
char *p, *q, *r;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
p = s;
|
|
Packit |
667938 |
q = s + maxs - 1;
|
|
Packit |
667938 |
while ((*f != '\0'))
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
if (*f++ == '%')
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
r = buf;
|
|
Packit |
667938 |
switch (*f++)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
case '%' :
|
|
Packit |
667938 |
r = "%";
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'a' :
|
|
Packit |
667938 |
r = aday[t->tm_wday];
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'A' :
|
|
Packit |
667938 |
r = day[t->tm_wday];
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'b' :
|
|
Packit |
667938 |
r = amonth[t->tm_mon];
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'B' :
|
|
Packit |
667938 |
r = month[t->tm_mon];
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'c' :
|
|
Packit |
667938 |
strfmt(r, "%0 %0 %2 %2:%2:%2 %4",
|
|
Packit |
667938 |
aday[t->tm_wday], amonth[t->tm_mon],
|
|
Packit |
667938 |
t->tm_mday,t->tm_hour, t->tm_min,
|
|
Packit |
667938 |
t->tm_sec, t->tm_year+1900);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'd' :
|
|
Packit |
667938 |
strfmt(r,"%2",t->tm_mday);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'H' :
|
|
Packit |
667938 |
strfmt(r,"%2",t->tm_hour);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'I' :
|
|
Packit |
667938 |
strfmt(r,"%2",(t->tm_hour%12)?t->tm_hour%12:12);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'j' :
|
|
Packit |
667938 |
strfmt(r,"%3",t->tm_yday+1);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'm' :
|
|
Packit |
667938 |
strfmt(r,"%2",t->tm_mon+1);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'M' :
|
|
Packit |
667938 |
strfmt(r,"%2",t->tm_min);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'p' :
|
|
Packit |
667938 |
r = (t->tm_hour>11)?"PM":"AM";
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'S' :
|
|
Packit |
667938 |
strfmt(r,"%2",t->tm_sec);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'U' :
|
|
Packit |
667938 |
w = t->tm_yday/7;
|
|
Packit |
667938 |
if (t->tm_yday%7 > t->tm_wday)
|
|
Packit |
667938 |
w++;
|
|
Packit |
667938 |
strfmt(r, "%2", w);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'W' :
|
|
Packit |
667938 |
w = t->tm_yday/7;
|
|
Packit |
667938 |
if (t->tm_yday%7 > (t->tm_wday+6)%7)
|
|
Packit |
667938 |
w++;
|
|
Packit |
667938 |
strfmt(r, "%2", w);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'V':
|
|
Packit |
667938 |
|
|
Packit |
667938 |
/* ISO 8601 Week Of Year:
|
|
Packit |
667938 |
If the week (Monday - Sunday) containing January 1 has four or more
|
|
Packit |
667938 |
days in the new year, then it is week 1; otherwise it is week 53 of
|
|
Packit |
667938 |
the previous year and the next week is week one. */
|
|
Packit |
667938 |
|
|
Packit |
667938 |
w = (t->tm_yday + 7 - (t->tm_wday ? t->tm_wday - 1 : 6)) / 7;
|
|
Packit |
667938 |
d = (t->tm_yday + 7 - (t->tm_wday ? t->tm_wday - 1 : 6)) % 7;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
if (d >= 4) { w++; } else if (w == 0) { w = 53; }
|
|
Packit |
667938 |
strfmt(r, "%2", w);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'w' :
|
|
Packit |
667938 |
strfmt(r,"%1",t->tm_wday);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'x' :
|
|
Packit |
667938 |
strfmt(r, "%3s %3s %2 %4", aday[t->tm_wday],
|
|
Packit |
667938 |
amonth[t->tm_mon], t->tm_mday, t->tm_year+1900);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'X' :
|
|
Packit |
667938 |
strfmt(r, "%2:%2:%2", t->tm_hour,
|
|
Packit |
667938 |
t->tm_min, t->tm_sec);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'y' :
|
|
Packit |
667938 |
strfmt(r,"%2",t->tm_year%100);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'Y' :
|
|
Packit |
667938 |
strfmt(r,"%4",t->tm_year+1900);
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
case 'Z' :
|
|
Packit |
667938 |
r = (t->tm_isdst && tzname_[1][0]) ?
|
|
Packit |
667938 |
tzname_[1] : tzname_[0];
|
|
Packit |
667938 |
break;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
default:
|
|
Packit |
667938 |
buf[0] = '%'; /* reconstruct the format */
|
|
Packit |
667938 |
buf[1] = f[-1];
|
|
Packit |
667938 |
buf[2] = '\0';
|
|
Packit |
667938 |
if (buf[1] == 0)
|
|
Packit |
667938 |
f--; /* back up if at end of string */
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
while (*r)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
if (p == q)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
*q = '\0';
|
|
Packit |
667938 |
return 0;
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
*p++ = *r++;
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
else
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
if (p == q)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
*q = '\0';
|
|
Packit |
667938 |
return 0;
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
*p++ = f[-1];
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
*p = '\0';
|
|
Packit |
667938 |
return p - s;
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
|
|
Packit |
667938 |
/*
|
|
Packit |
667938 |
* stdarg.h
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
typedef void *va_list;
|
|
Packit |
667938 |
#define va_start(vp,v) (vp=((char*)&v)+sizeof(v))
|
|
Packit |
667938 |
#define va_arg(vp,t) (*((t*)(vp))++)
|
|
Packit |
667938 |
#define va_end(vp)
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
*/
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static int pow[5] = { 1, 10, 100, 1000, 10000 };
|
|
Packit |
667938 |
|
|
Packit |
667938 |
/**
|
|
Packit |
667938 |
* static void strfmt(char *str, char *fmt);
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* simple sprintf for strftime
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* each format descriptor is of the form %n
|
|
Packit |
667938 |
* where n goes from zero to four
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
* 0 -- string %s
|
|
Packit |
667938 |
* 1..4 -- int %?.?d
|
|
Packit |
667938 |
*
|
|
Packit |
667938 |
**/
|
|
Packit |
667938 |
|
|
Packit |
667938 |
static void strfmt(char *str, const char *fmt, ...)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
int ival, ilen;
|
|
Packit |
667938 |
char *sval;
|
|
Packit |
667938 |
va_list vp;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
va_start(vp, fmt);
|
|
Packit |
667938 |
while (*fmt)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
if (*fmt++ == '%')
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
ilen = *fmt++ - '0';
|
|
Packit |
667938 |
if (ilen == 0) /* zero means string arg */
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
sval = va_arg(vp, char*);
|
|
Packit |
667938 |
while (*sval)
|
|
Packit |
667938 |
*str++ = *sval++;
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
else /* always leading zeros */
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
ival = va_arg(vp, int);
|
|
Packit |
667938 |
while (ilen)
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
ival %= pow[ilen--];
|
|
Packit |
667938 |
*str++ = (char)('0' + ival / pow[ilen]);
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
else *str++ = fmt[-1];
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
*str = '\0';
|
|
Packit |
667938 |
va_end(vp);
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
|
|
Packit |
667938 |
#ifdef TEST
|
|
Packit |
667938 |
|
|
Packit |
667938 |
#include <stdio.h> /* for printf */
|
|
Packit |
667938 |
#include <time.h> /* for strftime */
|
|
Packit |
667938 |
|
|
Packit |
667938 |
char test[80];
|
|
Packit |
667938 |
|
|
Packit |
667938 |
int main(int argc, char *argv[])
|
|
Packit |
667938 |
{
|
|
Packit |
667938 |
int len;
|
|
Packit |
667938 |
char *fmt;
|
|
Packit |
667938 |
time_t now;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
time(&now;;
|
|
Packit |
667938 |
|
|
Packit |
667938 |
fmt = (argc == 1) ? "%I:%M %p\n%c\n" : argv[1];
|
|
Packit |
667938 |
len = strftime_(test,sizeof test, fmt, localtime(&now));
|
|
Packit |
667938 |
printf("%d: %s\n", len, test);
|
|
Packit |
667938 |
return !len;
|
|
Packit |
667938 |
}
|
|
Packit |
667938 |
|
|
Packit |
667938 |
#endif /* TEST */
|