home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / Programming / Source / WAIS / ir / ptime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-02  |  13.0 KB  |  595 lines

  1. #include "cutil.h"
  2.  
  3. #include <ctype.h>
  4.  
  5. /* 
  6.      strptime() converts the character string pointed to  by  buf
  7.      to a time value, which is stored in the tm structure pointed
  8.      to by tm, using the format specified by fmt.  A  pointer  to
  9.      the  character  following  the  last character in the string
  10.      pointed to by buf is returned.  fmt is  a  character  string
  11.      that consists of field descriptors and text characters, rem-
  12.      iniscent of scanf(3v).  Each field descriptor consists of  a
  13.      %  character followd by another character that specifies the
  14.      replacement for the field descriptor.  All other  characters
  15.      are  copied  from  fmt into the result.  The following field
  16.      descriptors are supported:
  17.  
  18.           %%   same as %
  19.  
  20.           %a
  21.           %A   day of week, using locale's weekday names;  either
  22.                the abbreviated or full name may be specified
  23.  
  24.           %b
  25.           %B
  26.           %h   month, using  locale's  month  names;  either  the
  27.                abbreviated or full name may be specified
  28.  
  29.           %c   date and time as %x %X
  30.  
  31.           %C   date and time, in locale's  long-format  date  and
  32.                time representation
  33.  
  34.           %d
  35.           %e   day of month (1-31; leading zeroes  are  permitted
  36.                but not required)
  37.  
  38.           %D   date as %m/%d/%y
  39.  
  40.           %H
  41.           %k   hour (0-23; leading zeroes are permitted  but  not
  42.  
  43.                required)
  44.  
  45.           %I
  46.           %l   hour (0-12; leading zeroes are permitted  but  not
  47.                required)
  48.  
  49.           %j   day number of year (001-366)
  50.  
  51.           %m   month number (1-12; leading zeroes  are  permitted
  52.                but not required)
  53.  
  54.           %M   minute (0-59; leading zeroes are permitted but not
  55.                required)
  56.  
  57.           %p   locale's equivalent of AM or PM
  58.  
  59.           %r   time as %I:%M:%S %p
  60.  
  61.           %R   time as %H:%M
  62.  
  63.           %S   seconds (0-59; leading zeroes  are  permitted  but
  64.                not required)
  65.  
  66.           %T   time as %H:%M:%S
  67.  
  68.           %x   date, using locale's date format
  69.  
  70.           %X   time, using locale's time format
  71.  
  72.           %y   year within century (0-99; leading zeroes are per-
  73.                mitted but not required)
  74.  
  75.           %Y   year, including century (for example, 1988)
  76.  
  77.      Case is ignored when matching items such as month or weekday
  78.      names.   The %M, %S, %y, and %Y fields are optional; if they
  79.      would be matched by white space, the match is suppressed and
  80.      the  appropriate  field of the tm structure pointed to by tm
  81.      is left unchanged.  If any of the format items %d,  %e,  %H,
  82.      %k,  %I,  %l,  %m,  %M,  %S,  %y, or %Y are matched, but the
  83.      string that matches them is followed  by  white  space,  all
  84.      subsequent  items  in  the  format  string are skipped up to
  85.      white space or the end of the format.   The  net  result  is
  86.      that, for example, the format %m/%d/%y can be matched by the
  87.      string 12/31; the tm_mon and tm_mday fields of the tm struc-
  88.      ture  pointed  to  by  tm  will be set to 11 and 31, respec-
  89.      tively, while the tm_year field will be unchanged.
  90.  
  91.  */
  92.  
  93. /*
  94. struct    tm {
  95.     int    tm_sec;
  96.     int    tm_min;
  97.     int    tm_hour;
  98.     int    tm_mday;
  99.     int    tm_mon;
  100.     int    tm_year;
  101.     int    tm_wday;
  102.     int    tm_yday;
  103.     int    tm_isdst;
  104.     char    *tm_zone;
  105.     long    tm_gmtoff;
  106. };
  107. */
  108.  
  109. #define CHECK_FOR_SPACES(buf, fmt)             \
  110.     if ((buf == NULL) || isspace(*buf) || (*buf == '\0')) { \
  111.     while ((! isspace(**fmt)) && (**fmt != '\0')) { \
  112.         (*fmt)++;                    \
  113.     }                        \
  114.     (*fmt)--;                    \
  115.     }                            \
  116.   return(buf)
  117.  
  118. static int substrmatch(char *, char *);
  119. static int substrmatch (str, match)
  120.      char *str;
  121.      char *match;
  122. {
  123.     int match_len = 0;
  124.  
  125.     while ((*str != '\0') && (*match != '\0')) {
  126.     if (tolower(*str) != tolower(*match)) {
  127.         return(match_len);
  128.     }
  129.     str++;
  130.     match++;
  131.     match_len++;
  132.     }
  133.     return(match_len);
  134. }  /* substrmatch() */
  135.  
  136.  
  137. static char *weekday_names[] = {
  138.     "Sunday",
  139.     "Monday",
  140.     "Tuesday",
  141.     "Wednesday",
  142.     "Thursday",
  143.     "Friday",
  144.     "Saturday"
  145. };  /* weekday_names[] */
  146.  
  147. static char *month_names[] = {
  148.     "January",
  149.     "February",
  150.     "March",
  151.     "April",
  152.     "May",
  153.     "June",
  154.     "July",
  155.     "August",
  156.     "September",
  157.     "October",
  158.     "November",
  159.     "December"
  160. };  /* month_names[] */
  161.  
  162. static char *get_weekday_name(char *, char **, struct tm *);
  163. static char *get_weekday_name (buf, fmt, tm)
  164.      char *buf;
  165.      char **fmt;
  166.      struct tm *tm;
  167. {
  168.     int i;
  169.     int len;
  170.     int num = sizeof(weekday_names) / sizeof(weekday_names[0]);
  171.  
  172.     for (i = 0; i < num; i++) {
  173.     len = substrmatch(buf, weekday_names[i]);
  174.     if (len > 2) {
  175.         tm->tm_wday = i;
  176.         return(& buf[len]);
  177.     }
  178.     }
  179.     return(NULL);
  180. }  /* get_weekday_name() */
  181.  
  182. static char *get_month_name(char *, char **, struct tm *);
  183. static char *get_month_name (buf, fmt, tm)
  184.      char *buf;
  185.      char **fmt;
  186.      struct tm *tm;
  187. {
  188.     int i;
  189.     int len;
  190.     int num = sizeof(month_names) / sizeof(month_names[0]);
  191.  
  192.     for (i = 0; i < num; i++) {
  193.     len = substrmatch(buf, month_names[i]);
  194.     if (len > 2) {
  195.         tm->tm_mon = i;
  196.         return(& buf[len]);
  197.     }
  198.     }
  199.     return(NULL);
  200. }  /* get_month_name() */
  201.  
  202.  
  203. static char *match_number(char *, int *, int, int);
  204. static char *match_number (buf, valp, min, max)
  205.      char *buf;
  206.      int *valp;
  207.      int min;
  208.      int max;
  209. {
  210.     int num = 0;
  211.     int newnum;
  212.  
  213.     while (isdigit(*buf)) {
  214.     newnum = num * 10 + (*buf - '0');
  215.     if (newnum > max) {
  216.         *valp = num;
  217.         return(buf);
  218.     }
  219.     num = newnum;
  220.     buf++;
  221.     }
  222.     *valp = num;
  223.     return(num >= min ? buf : NULL);
  224. }
  225.  
  226. static char *get_month_num(char *, char **, struct tm *);
  227. static char *get_month_num (buf, fmt, tm)
  228.      char *buf;
  229.      char **fmt;
  230.      struct tm *tm;
  231. {
  232.     int val = 0;
  233.     
  234.     buf = match_number(buf, &val, 1, 12);
  235.     tm->tm_mon = val - 1;
  236.     CHECK_FOR_SPACES(buf, fmt);
  237. }  /* get_month_num() */
  238.  
  239. static char *get_year_num(char *, char **, struct tm *);
  240. static char *get_year_num (buf, fmt, tm)
  241.      char *buf;
  242.      char **fmt;
  243.      struct tm *tm;
  244. {
  245.     int val = 0;
  246.  
  247.     buf = match_number(buf, &val, 0, 2000);
  248.     tm->tm_year = val % 100;
  249.     CHECK_FOR_SPACES(buf, fmt);
  250. }  /* get_year_num() */
  251.  
  252. static char *get_hour_num(char *, char **, struct tm *);
  253. static char *get_hour_num (buf, fmt, tm)
  254.      char *buf;
  255.      char **fmt;
  256.      struct tm *tm;
  257. {
  258.     int val = 0;
  259.  
  260.     buf = match_number(buf, &val, 0, 23);
  261.     tm->tm_hour = val;
  262.     CHECK_FOR_SPACES(buf, fmt);
  263. }  /* get_hour_num() */
  264.  
  265. static char *get_minute_num(char *, char **, struct tm *);
  266. static char *get_minute_num (buf, fmt, tm)
  267.      char *buf;
  268.      char **fmt;
  269.      struct tm *tm;
  270. {
  271.     int val = 0;
  272.  
  273.     buf = match_number(buf, &val, 0, 59);
  274.     tm->tm_min = val;
  275.     CHECK_FOR_SPACES(buf, fmt);
  276. }  /* get_minute_num() */
  277.  
  278. static char *get_second_num(char *, char **, struct tm *);
  279. static char *get_second_num (buf, fmt, tm)
  280.      char *buf;
  281.      char **fmt;
  282.      struct tm *tm;
  283. {
  284.     int val = 0;
  285.  
  286.     buf = match_number(buf, &val, 0, 59);
  287.     tm->tm_sec = val;
  288.     CHECK_FOR_SPACES(buf, fmt);
  289. }  /* get_second_num() */
  290.  
  291. static char *get_day_of_year_num(char *, char **, struct tm *);
  292. static char *get_day_of_year_num (buf, fmt, tm)
  293.      char *buf;
  294.      char **fmt;
  295.      struct tm *tm;
  296. {
  297.     int val = 0;
  298.  
  299.     buf = match_number(buf, &val, 1, 366);
  300.     tm->tm_yday = val - 1;
  301.     return(buf);
  302. }  /* get_day_of_year_num() */
  303.  
  304. static char *get_day_of_month_num(char *, char **, struct tm *);
  305. static char *get_day_of_month_num (buf, fmt, tm)
  306.      char *buf;
  307.      char **fmt;
  308.      struct tm *tm;
  309. {
  310.     int val = 0;
  311.  
  312.     buf = match_number(buf, &val, 1, 31);
  313.     tm->tm_mday = val;
  314.     CHECK_FOR_SPACES(buf, fmt);
  315. }  /* get_day_of_month_num() */
  316.  
  317. static char *get_am_or_pm(char *, char **, struct tm *);
  318. static char *get_am_or_pm (buf, fmt, tm)
  319.      char *buf;
  320.      char **fmt;
  321.      struct tm *tm;
  322. {
  323.     if (strncasecmp(buf, "am", 2) == 0) {
  324.     return(& buf[2]);
  325.     }
  326.     else if (strncasecmp(buf, "a.m.", 4) == 0) {
  327.     return(& buf[4]);
  328.     }
  329.     if (strncasecmp(buf, "pm", 2) == 0) {
  330.     buf += 2;
  331.     }
  332.     else if (strncasecmp(buf, "p.m.", 4) == 0) {
  333.     buf += 4;
  334.     }
  335.     else return(NULL);
  336.     if (tm->tm_hour < 12) {
  337.     tm->tm_hour += 12;
  338.     }
  339.     return(buf);
  340. }  /* get_am_or_pm() */
  341.  
  342. char *string_to_time (buf, fmt, tm)
  343.      char *buf;
  344.      char *fmt;
  345.      struct tm *tm;
  346. {
  347.     for (; *fmt != '\0'; fmt++) {
  348.     if (*fmt == '%') {
  349.         fmt++;
  350.         switch (*fmt) {
  351.           case 'a' :    /* weekday (abbrev or full) */
  352.           case 'A' :
  353.         buf = get_weekday_name(buf, &fmt, tm);
  354.         if (buf == NULL) {
  355.             return(NULL);
  356.         }
  357.         break;
  358.  
  359.           case 'b' :    /* month (abbrev or full) */
  360.           case 'B' :
  361.           case 'h' :
  362.         buf = get_month_name(buf, &fmt, tm);
  363.         break;
  364.  
  365.           case 'c' :    /* same as %x %X */
  366.         break;
  367.  
  368.           case 'C' :     /* locale's long-format date and time */
  369.         break;
  370.  
  371.           case 'd' :    /* day of month 1-31, leading 0's allowed */
  372.           case 'e' :
  373.         buf = get_day_of_month_num(buf, &fmt, tm);
  374.         break;
  375.  
  376.           case 'D' :    /* date as %m/%d/%y */
  377.         buf = get_month_num(buf, &fmt, tm);
  378.         if (buf == NULL) {
  379.             return(NULL);
  380.         }
  381.         if (*buf != '/') {
  382.             if (isspace(*buf)) {
  383.             break;
  384.             }
  385.             return(NULL);
  386.         }
  387.         buf++;
  388.         buf = get_day_of_month_num(buf, &fmt, tm);
  389.         if (buf == NULL) {
  390.             return(NULL);
  391.         }
  392.         if (*buf++ != '/') {
  393.             if (isspace(*buf)) {
  394.             break;
  395.             }
  396.             return(NULL);
  397.         }
  398.         buf = get_year_num(buf, &fmt, tm);
  399.         if (buf == NULL) {
  400.             return(NULL);
  401.         }
  402.         break;
  403.  
  404.           case 'H' :    /* hour 0-23, leading 0's allowed */
  405.           case 'k' :
  406.         buf = get_hour_num(buf, &fmt, tm);
  407.         break;
  408.  
  409.           case 'l' :    /* hour 0-12, leading 0's allowed */
  410.           case 'L' :
  411.         buf = get_hour_num(buf, &fmt, tm);
  412.         break;
  413.  
  414.           case 'j' :    /* day number of year 001-366 */
  415.         buf = get_day_of_year_num(buf, &fmt, tm);
  416.         break;
  417.  
  418.           case 'm' :    /* month number 1-12, leading 0's allowed */
  419.         buf = get_month_num(buf, &fmt, tm);
  420.         break;
  421.  
  422.           case 'M' :    /* minute, 0-59, leading 0's allowed */
  423.         buf = get_minute_num(buf, &fmt, tm);
  424.         break;
  425.  
  426.           case 'p' :    /* AM or PM */
  427.         buf = get_am_or_pm(buf, &fmt, tm);
  428.         break;
  429.  
  430.           case 'r' :    /* %l:%M:%S %p */
  431.         buf = get_hour_num(buf, &fmt, tm);
  432.         if (buf == NULL) {
  433.             return(NULL);
  434.         }
  435.         if (*buf++ != ':') {
  436.             if (isspace(*buf)) {
  437.             break;
  438.             }
  439.             return(NULL);
  440.         }
  441.         buf = get_minute_num(buf, &fmt, tm);
  442.         if (buf == NULL) {
  443.             return(NULL);
  444.         }
  445.         if (*buf++ != ':') {
  446.             if (isspace(*buf)) {
  447.             break;
  448.             }
  449.             return(NULL);
  450.         }
  451.         buf = get_second_num(buf, &fmt, tm);
  452.         if (buf == NULL) {
  453.             return(NULL);
  454.         }
  455.         while (isspace(*buf)) {
  456.             buf++;
  457.         }
  458.         buf = get_am_or_pm(buf, &fmt, tm);
  459.         if (buf == NULL) {
  460.             return(NULL);
  461.         }
  462.         break;
  463.  
  464.           case 'R' :    /* %H:%M */
  465.         buf = get_hour_num(buf, &fmt, tm);
  466.         if (buf == NULL) {
  467.             return(NULL);
  468.         }
  469.         if (*buf++ != ':') {
  470.             if (isspace(*buf)) {
  471.             break;
  472.             }
  473.             return(NULL);
  474.         }
  475.         buf = get_minute_num(buf, &fmt, tm);
  476.         if (buf == NULL) {
  477.             return(NULL);
  478.         }
  479.         break;
  480.  
  481.           case 'S' :    /* seconds 0-59, leading 0's allowed */
  482.         buf = get_second_num(buf, &fmt, tm);
  483.         break;
  484.  
  485.           case 'T' :    /* time as %H:%M:%S */
  486.         buf = get_hour_num(buf, &fmt, tm);
  487.         if (buf == NULL) {
  488.             return(NULL);
  489.         }
  490.         if (*buf++ != ':') {
  491.             if (isspace(*buf)) {
  492.             break;
  493.             }
  494.             return(NULL);
  495.         }
  496.         buf = get_minute_num(buf, &fmt, tm);
  497.         if (buf == NULL) {
  498.             return(NULL);
  499.         }
  500.         if (*buf++ != ':') {
  501.             if (isspace(*buf)) {
  502.             break;
  503.             }
  504.             return(NULL);
  505.         }
  506.         buf = get_second_num(buf, &fmt, tm);
  507.         if (buf == NULL) {
  508.             return(NULL);
  509.         }
  510.         break;
  511.  
  512.           case 'x' :    /* date, using locale's date format */
  513.         break;
  514.  
  515.           case 'X' :    /* time, using locale's time format */
  516.         break;
  517.  
  518.           case 'y' :    /* year 0-99, leading 0's allowed */
  519.         buf = get_year_num(buf, &fmt, tm);
  520.         break;
  521.  
  522.           case 'Y' :    /* year with century ie. 1988 */
  523.         buf = get_year_num(buf, &fmt, tm);
  524.         break;
  525.  
  526.           case '%' :  /* matches '%' */
  527.           default :
  528.         if (*buf != *fmt) {
  529.             return(NULL);
  530.         }
  531.         buf++;
  532.         break;
  533.         }  /* switch */
  534.         if (buf == NULL) {
  535.         return(NULL);
  536.         }
  537.     }  /* *fmt == '%' */
  538.     else if (isspace(*fmt)) {
  539.         /* match any number of spaces, even 0 */
  540.         while (isspace(*buf)) {  /* advance buf */
  541.         buf++;
  542.         }
  543.         while (isspace(*fmt)) {  /* advance fmt */
  544.         fmt++;
  545.         }
  546.         fmt--;
  547.     }
  548.     else {  /* anything else */
  549.         if (*buf != *fmt) {
  550.         return(NULL);
  551.         }
  552.         buf++;
  553.     }
  554.     }
  555.     return(buf);
  556. }  /* string_to_time() */
  557.  
  558.  
  559. main (argc, argv)
  560.      int argc;
  561.      char *argv[];
  562. {
  563.     char input[101];
  564.     struct tm tm;
  565.     char *ptr;
  566.     if(argc != 2){
  567.       printf("usage: format\n");
  568.       exit(-1);
  569.     }
  570.     while (TRUE) {
  571.     bzero((char *) &tm, sizeof(tm));
  572.     printf("\nEnter date --> ");
  573.     gets(input);
  574.     if (input[0] == 'q') exit(0);
  575.     ptr = string_to_time(input, argv[1], &tm);
  576.     if (ptr == NULL) {
  577.         printf("Returned NULL\n");
  578.     }
  579.     else {
  580.         printf("Read %d chars, '%s'\n",
  581.            ptr - input, ptr);
  582.     }
  583.     printf("\tm_sec\t%d\n", tm.tm_sec);
  584.     printf("\tm_min\t%d\n", tm.tm_min);
  585.     printf("\tm_hour\t%d\n", tm.tm_hour);
  586.     printf("\tm_mday\t%d\n", tm.tm_mday);
  587.     printf("\tm_mon\t%d\n", tm.tm_mon);
  588.     printf("\tm_year\t%d\n", tm.tm_year);
  589.     printf("\tm_wday\t%d\n", tm.tm_wday);
  590.     printf("\tm_yday\t%d\n", tm.tm_yday);
  591.     }  /* while () */
  592. }
  593.  
  594.  
  595.