home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib25.zoo / strftime.c < prev    next >
C/C++ Source or Header  |  1992-09-05  |  7KB  |  230 lines

  1. /*
  2.  * strftime: print formatted information about a given time
  3.  * Written by Eric R. Smith and placed in the public domain.
  4.  *
  5.  * With further modifications by Michal Jaegermann.
  6.  * Formats in SYSV_EXT from PD strftime source by Arnold Robins.
  7.  * 
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <time.h>
  13. #include <ctype.h>
  14. #include <string.h>
  15.  
  16. #define BIG_LEN 80
  17.  
  18. static int weeknumber __PROTO((const struct tm *timeptr, int firstweekday));
  19.  
  20.  
  21. extern char **_LC_Mth_name;     /* in setlocale.c */
  22. extern char **_LC_Day_name;
  23.  
  24. /*
  25.  * FIXME: I'm not sure what the formats for 'c', 'x', and 'X' should be
  26.  * for various locales, or even for the "C" locale. I've assumed that
  27.  * 'c' gives the same as asctime(), 'x' is e.g. Jan 01 1970, and
  28.  * 'X' is e.g. 12:20:37.
  29.  *
  30.  * I would venture that for "C" locale these formats are fine - mj.
  31.  */
  32.  
  33. size_t
  34. strftime(str, maxsize, fmt, ts)
  35.         char *str;
  36.         size_t maxsize;
  37.         const char *fmt;
  38.         const struct tm *ts;
  39. {
  40.         long    num = 0;
  41.         long    len = 0;
  42.     int n;
  43.         char    q;
  44.         char    buf[BIG_LEN], *putstr, *s;
  45.  
  46.         for(;;) {
  47.                 if (num >= maxsize) return 0;
  48.                 if ((q = *fmt++) == 0)  break;
  49.                 if (q != '%') {
  50.                         *str++ = q;
  51.                         num++;
  52.                         continue;
  53.                 }
  54.                 if ((q = *fmt++) == 0) break;       /* get format command */
  55.  
  56. /* assume that sprintf will be used, with a variable length */
  57. /* this is the most common case, so it saves us some coding to do it here */
  58.                 putstr = buf;
  59.  
  60.                 switch(q) {
  61.                   case 'A':
  62.                   case 'a':
  63.           /*
  64.            * cases 'a' and 'b' are still wrong -
  65.            * in some locale short names do not have to be
  66.            * 3 characters wide - still works in North America.
  67.            */
  68.                     if (ts->tm_wday < 0 || ts->tm_wday > 6)
  69.                     putstr = "?";
  70.             else
  71.                     if ( 'A' == q)
  72.                         putstr = _LC_Day_name[ts->tm_wday];
  73.                 else
  74.                         sprintf(buf, "%-.3s",
  75.                         _LC_Day_name[ts->tm_wday]);
  76.                         break;
  77.                   case 'B':
  78.                   case 'b':
  79. #ifdef SYSV_EXT
  80.                   case 'h':    /* same as 'b' */
  81. #endif
  82.                     if (ts->tm_mon < 0 || ts->tm_mon > 11)
  83.                     putstr = "?";
  84.             else
  85.                     if ( 'B' == q)
  86.                         putstr = _LC_Mth_name[ts->tm_mon];
  87.                 else
  88.                         sprintf(buf, "%-.3s",
  89.                         _LC_Mth_name[ts->tm_mon]);
  90.                         break;
  91.                   case 'c':
  92.             /* this format should be set in setlocale.c */
  93.                         strftime(buf, sizeof buf, "%a %b %d %X %Y", ts);
  94.                         break;
  95.           case 'd':
  96.                         sprintf(buf, "%02d", ts->tm_mday);
  97.                         break;
  98.                   case 'H':
  99.                         sprintf(buf, "%02d", ts->tm_hour);
  100.                         break;
  101.                   case 'I':
  102.                         n = ts->tm_hour;
  103.                         if (n == 0) n = 12;
  104.             else if (n > 12) n -= 12;
  105.                         sprintf(buf, "%02d", n);
  106.                         break;
  107.                   case 'j':
  108.                         sprintf(buf, "%03d", ts->tm_yday + 1);
  109.                         break;
  110.                   case 'm':
  111.                         sprintf(buf, "%02d", ts->tm_mon + 1);
  112.                         break;
  113.                   case 'M':
  114.                         sprintf(buf, "%02d", ts->tm_min);
  115.                         break;
  116.                   case 'p':
  117.             /*
  118.              * this is wrong - strings "AM', "PM" are
  119.              * locale dependent
  120.              */
  121.                         putstr = (ts->tm_hour < 12) ? "AM" : "PM";
  122.                         break;
  123.                   case 'S':
  124.                         sprintf(buf, "%02d", ts->tm_sec);
  125.                         break;
  126.                   case 'U':  /* week of year - starting Sunday */
  127.             sprintf(buf, "%02d", weeknumber(ts, 0));
  128.                         break;
  129.                   case 'W': /* week of year - starting Monday */
  130.             sprintf(buf, "%02d", weeknumber(ts, 1));
  131.                         break;
  132.                   case 'w':
  133.                         sprintf(buf, "%d", ts->tm_wday);
  134.                         break;
  135.                   case 'x':
  136.                 /* once again - format may be locale dependent */ 
  137.                         strftime(buf, sizeof buf, "%b %d %Y", ts);
  138.                         break;
  139.                   case 'X':
  140.             /* same applies to this format as well */
  141.                         sprintf(buf, "%02d:%02d:%02d", ts->tm_hour,
  142.                                 ts->tm_min, ts->tm_sec);
  143.                         break;
  144.                   case 'y':
  145.                         sprintf(buf, "%02d", ts->tm_year % 100);
  146.                         break;
  147.           case 'Y':
  148.                         sprintf(buf, "%d", ts->tm_year + 1900);
  149.                         break;
  150.                   case 'Z':
  151.                         if (NULL != (s = getenv("TZ"))) {
  152.                 strcpy(buf, s);
  153.                 s = buf;
  154.                 if (ts->tm_isdst) {
  155.                     while (*s && isalpha(*s)) s++;
  156.                         while (*s && (isdigit(*s)||
  157.                               *s == '+'  ||
  158.                               *s == '-'  ||
  159.                               *s == ':')) {
  160.                             s++;
  161.                         };
  162.                         if (*s)
  163.                             putstr = s;
  164.                 }
  165.                 s = putstr;
  166.                 while (*s && isalpha(*s))
  167.                         s++;
  168.                 *s++ = 0;
  169.             }
  170.             else
  171.                     buf[0] = '\0'; /* empty string */
  172.                         break;
  173.                    case '%':
  174.                         putstr = "%";
  175.                         break;
  176. #ifdef SYSV_EXT
  177.            case 'n':    /* same as \n */
  178.             putstr = "\n";
  179.             break;
  180.            case 't':    /* same as \t */
  181.             putstr = "\n";
  182.             break;
  183.             break;
  184.            case 'D':    /* date as %m/%d/%y */
  185.             strftime(buf, sizeof buf, "%m/%d/%y", ts);
  186.             break;
  187.            case 'e':    /* day of month, blank padded */
  188.             sprintf(buf, "%2d", ts->tm_mday);
  189.             break;
  190.            case 'r':    /* time as %I:%M:%S %p */
  191.             strftime(buf, sizeof buf, "%I:%M:%S %p", ts);
  192.             break;
  193.            case 'R':    /* time as %H:%M */
  194.             strftime(buf, sizeof buf, "%H:%M", ts);
  195.             break;
  196.            case 'T':    /* time as %H:%M:%S */
  197.             strftime(buf, sizeof buf, "%H:%M:%S", ts);
  198.             break;
  199. #endif
  200.                 }
  201.  
  202.                 if (num + (len = strlen(putstr)) >= maxsize)
  203.                         return 0;
  204.  
  205.                 num += len;
  206.                 while (--len >= 0)
  207.                         *str++ = *putstr++;
  208.         }
  209.         *str = 0;
  210.         return (size_t) num;
  211. }
  212.  
  213. /* 
  214.  * What follows grabbed, with a small change, from PD source of strftime
  215.  * by Arnold Robins - arnold@audiofax.com
  216.  */
  217. /* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */
  218.  
  219. static int
  220. weeknumber(timeptr, firstweekday)
  221. const struct tm *timeptr;
  222. int firstweekday;
  223. /*
  224.  * firstweekday is 0 if starting in Sunday, non-zero if in Monday
  225.  */
  226. {
  227.     return (timeptr->tm_yday - timeptr->tm_wday +
  228.         (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
  229. }
  230.