strftime.c
上传用户:shbosideng
上传日期:2013-05-04
资源大小:1555k
文件大小:10k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /**
  2.  *
  3.  * strftime.c
  4.  *
  5.  * implements the ansi c function strftime()
  6.  *
  7.  * written 6 september 1989 by jim nutt
  8.  * released into the public domain by jim nutt
  9.  *
  10.  * modified 21-Oct-89 by Rob Duff
  11.  *
  12.  * modified 08-Dec-04 by Tobi Oetiker (added %V)
  13. **/
  14. #include <stddef.h>     /* for size_t */
  15. #include <stdarg.h>     /* for va_arg */
  16. #include <time.h>       /* for struct tm */
  17. #include "strftime.h"
  18. static char *aday[] = {
  19.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  20. };
  21. static char *day[] = {
  22.     "Sunday", "Monday", "Tuesday", "Wednesday",
  23.     "Thursday", "Friday", "Saturday"
  24. };
  25. static char *amonth[] = {
  26.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  27.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  28. };
  29. static char *month[] = {
  30.     "January", "February", "March", "April", "May", "June",
  31.     "July", "August", "September", "October", "November", "December"
  32. };
  33. char *tzname_[2] = {"CST", "CDT"};        /* Add your own defaults here */
  34. static char buf[26];
  35. static void strfmt(char *str, const char *fmt, ...);
  36. /**
  37.  *
  38.  * size_t strftime_(char *str,
  39.  *                  size_t maxs,
  40.  *                  const char *fmt,
  41.  *                  const struct tm *t)
  42.  *
  43.  *      this functions acts much like a sprintf for time/date output.
  44.  *      given a pointer to an output buffer, a format string and a
  45.  *      time, it copies the time to the output buffer formatted in
  46.  *      accordance with the format string.  the parameters are used
  47.  *      as follows:
  48.  *
  49.  *          str is a pointer to the output buffer, there should
  50.  *          be at least maxs characters available at the address
  51.  *          pointed to by str.
  52.  *
  53.  *          maxs is the maximum number of characters to be copied
  54.  *          into the output buffer, included the '' terminator
  55.  *
  56.  *          fmt is the format string.  a percent sign (%) is used
  57.  *          to indicate that the following character is a special
  58.  *          format character.  the following are valid format
  59.  *          characters:
  60.  *
  61.  *              %A      full weekday name (Monday)
  62.  *              %a      abbreviated weekday name (Mon)
  63.  *              %B      full month name (January)
  64.  *              %b      abbreviated month name (Jan)
  65.  *              %c      standard date and time representation
  66.  *              %d      day-of-month (01-31)
  67.  *              %H      hour (24 hour clock) (00-23)
  68.  *              %I      hour (12 hour clock) (01-12)
  69.  *              %j      day-of-year (001-366)
  70.  *              %M      minute (00-59)
  71.  *              %m      month (01-12)
  72.  *              %p      local equivalent of AM or PM
  73.  *              %S      second (00-59)
  74.  *              %U      week-of-year, first day sunday (00-53)
  75.  *              %W      week-of-year, first day monday (00-53)
  76.  *              %V      ISO 8601 Week number 
  77.  *              %w      weekday (0-6, sunday is 0)
  78.  *              %X      standard time representation
  79.  *              %x      standard date representation
  80.  *              %Y      year with century
  81.  *              %y      year without century (00-99)
  82.  *              %Z      timezone name
  83.  *              %%      percent sign
  84.  *
  85.  *      the standard date string is equivalent to:
  86.  *
  87.  *          %a %b %d %Y
  88.  *
  89.  *      the standard time string is equivalent to:
  90.  *
  91.  *          %H:%M:%S
  92.  *
  93.  *      the standard date and time string is equivalent to:
  94.  *
  95.  *          %a %b %d %H:%M:%S %Y
  96.  *
  97.  *      strftime_() returns the number of characters placed in the
  98.  *      buffer, not including the terminating , or zero if more
  99.  *      than maxs characters were produced.
  100.  *
  101. **/
  102. size_t strftime_(char *s, size_t maxs, const char *f, const struct tm *t)
  103. {
  104.       int w,d;
  105.       char *p, *q, *r;
  106.       p = s;
  107.       q = s + maxs - 1;
  108.       while ((*f != ''))
  109.       {
  110.             if (*f++ == '%')
  111.             {
  112.                   r = buf;
  113.                   switch (*f++)
  114.                   {
  115.                   case '%' :
  116.                         r = "%";
  117.                         break;
  118.                   case 'a' :
  119.                         r = aday[t->tm_wday];
  120.                         break;
  121.                   case 'A' :
  122.                         r = day[t->tm_wday];
  123.                         break;
  124.                   case 'b' :
  125.                         r = amonth[t->tm_mon];
  126.                         break;
  127.                   case 'B' :
  128.                         r = month[t->tm_mon];
  129.                         break;
  130.                   case 'c' :
  131.                         strfmt(r, "%0 %0 %2 %2:%2:%2 %4",
  132.                               aday[t->tm_wday], amonth[t->tm_mon],
  133.                               t->tm_mday,t->tm_hour, t->tm_min,
  134.                               t->tm_sec, t->tm_year+1900);
  135.                         break;
  136.                   case 'd' :
  137.                         strfmt(r,"%2",t->tm_mday);
  138.                         break;
  139.                   case 'H' :
  140.                         strfmt(r,"%2",t->tm_hour);
  141.                         break;
  142.                   case 'I' :
  143.                         strfmt(r,"%2",(t->tm_hour%12)?t->tm_hour%12:12);
  144.                         break;
  145.                   case 'j' :
  146.                         strfmt(r,"%3",t->tm_yday+1);
  147.                         break;
  148.                   case 'm' :
  149.                         strfmt(r,"%2",t->tm_mon+1);
  150.                         break;
  151.                   case 'M' :
  152.                         strfmt(r,"%2",t->tm_min);
  153.                         break;
  154.                   case 'p' :
  155.                         r = (t->tm_hour>11)?"PM":"AM";
  156.                         break;
  157.                   case 'S' :
  158.                         strfmt(r,"%2",t->tm_sec);
  159.                         break;
  160.                   case 'U' :
  161.                         w = t->tm_yday/7;
  162.                         if (t->tm_yday%7 > t->tm_wday)
  163.                               w++;
  164.                         strfmt(r, "%2", w);
  165.                         break;
  166.                   case 'W' :
  167.                         w = t->tm_yday/7;
  168.                         if (t->tm_yday%7 > (t->tm_wday+6)%7)
  169.                               w++;
  170.                         strfmt(r, "%2", w);
  171.                         break;
  172.                   case 'V':
  173.                         /* ISO 8601 Week Of Year:
  174.                            If the week (Monday - Sunday) containing January 1 has four or more
  175.                            days in the new year, then it is week 1; otherwise it is week 53 of
  176.                            the previous year and the next week is week one. */
  177.            w  =  (t->tm_yday + 7 - (t->tm_wday ? t->tm_wday - 1 : 6)) / 7;
  178.                         d  =  (t->tm_yday + 7 - (t->tm_wday ? t->tm_wday - 1 : 6)) % 7;
  179.                         if (d >= 4) { w++; } else if (w == 0) { w = 53; }
  180.                         strfmt(r, "%2", w);
  181.                         break;
  182.                   case 'w' :
  183.                         strfmt(r,"%1",t->tm_wday);
  184.                         break;
  185.                   case 'x' :
  186.                         strfmt(r, "%3s %3s %2 %4", aday[t->tm_wday],
  187.                               amonth[t->tm_mon], t->tm_mday, t->tm_year+1900);
  188.                         break;
  189.                   case 'X' :
  190.                         strfmt(r, "%2:%2:%2", t->tm_hour,
  191.                               t->tm_min, t->tm_sec);
  192.                         break;
  193.                   case 'y' :
  194.                         strfmt(r,"%2",t->tm_year%100);
  195.                         break;
  196.                   case 'Y' :
  197.                         strfmt(r,"%4",t->tm_year+1900);
  198.                         break;
  199.                   case 'Z' :
  200.                         r = (t->tm_isdst && tzname_[1][0]) ?
  201.                               tzname_[1] : tzname_[0];
  202.                         break;
  203.                   default:
  204.                         buf[0] = '%';     /* reconstruct the format */
  205.                         buf[1] = f[-1];
  206.                         buf[2] = '';
  207.                         if (buf[1] == 0)
  208.                               f--;        /* back up if at end of string */
  209.                   }
  210.                   while (*r)
  211.                   {
  212.                         if (p == q)
  213.                         {
  214.                               *q = '';
  215.                               return 0;
  216.                         }
  217.                         *p++ = *r++;
  218.                   }
  219.             }
  220.             else
  221.             {
  222.                   if (p == q)
  223.                   {
  224.                         *q = '';
  225.                         return 0;
  226.                   }
  227.                   *p++ = f[-1];
  228.             }
  229.       }
  230.       *p = '';
  231.       return p - s;
  232. }
  233. /*
  234.  *  stdarg.h
  235.  *
  236. typedef void *va_list;
  237. #define va_start(vp,v) (vp=((char*)&v)+sizeof(v))
  238. #define va_arg(vp,t) (*((t*)(vp))++)
  239. #define va_end(vp)
  240.  *
  241.  */
  242. static int pow[5] = { 1, 10, 100, 1000, 10000 };
  243. /**
  244.  * static void strfmt(char *str, char *fmt);
  245.  *
  246.  * simple sprintf for strftime
  247.  *
  248.  * each format descriptor is of the form %n
  249.  * where n goes from zero to four
  250.  *
  251.  * 0    -- string %s
  252.  * 1..4 -- int %?.?d
  253.  *
  254. **/
  255. static void strfmt(char *str, const char *fmt, ...)
  256. {
  257.       int ival, ilen;
  258.       char *sval;
  259.       va_list vp;
  260.       va_start(vp, fmt);
  261.       while (*fmt)
  262.       {
  263.             if (*fmt++ == '%')
  264.             {
  265.                   ilen = *fmt++ - '0';
  266.                   if (ilen == 0)                /* zero means string arg */
  267.                   {
  268.                         sval = va_arg(vp, char*);
  269.                         while (*sval)
  270.                               *str++ = *sval++;
  271.                   }
  272.                   else                          /* always leading zeros */
  273.                   {
  274.                         ival = va_arg(vp, int);
  275.                         while (ilen)
  276.                         {
  277.                               ival %= pow[ilen--];
  278.                               *str++ = (char)('0' + ival / pow[ilen]);
  279.                         }
  280.                   }
  281.             }
  282.             else  *str++ = fmt[-1];
  283.       }
  284.       *str = '';
  285.       va_end(vp);
  286. }
  287. #ifdef TEST
  288. #include <stdio.h>      /* for printf */
  289. #include <time.h>       /* for strftime */
  290. char test[80];
  291. int main(int argc, char *argv[])
  292. {
  293.       int len;
  294.       char *fmt;
  295.       time_t now;
  296.       time(&now);
  297.       fmt = (argc == 1) ? "%I:%M %pn%cn" : argv[1];
  298.       len = strftime_(test,sizeof test, fmt, localtime(&now));
  299.       printf("%d: %sn", len, test);
  300.       return !len;
  301. }
  302. #endif /* TEST */