home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / time / strptime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-25  |  9.1 KB  |  343 lines

  1. /* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
  2.    This file is part of the GNU C Library.
  3.  
  4.    The GNU C Library is free software; you can redistribute it and/or
  5.    modify it under the terms of the GNU Library General Public License as
  6.    published by the Free Software Foundation; either version 2 of the
  7.    License, or (at your option) any later version.
  8.  
  9.    The GNU C Library is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.    Library General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU Library General Public
  15.    License along with the GNU C Library; see the file COPYING.LIB.  If
  16.    not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17.    Cambridge, MA 02139, USA.  */
  18.  
  19. /* Mitch DSouza - m.dsouza@mrc-apu.cam.ac.uk - Tue Sep 13 22:16:56  1994.
  20.  
  21.    This conforms to XOpen as checked by Patrick D'Cruze. Some extra comments:
  22.  
  23.     XPG4 say that %a = %A = the locale's full or abbreviated weekday name.
  24.     However GNU defines it so that:
  25.         a = the locale's abbreviated weekday name
  26.         A = the locale's full weekday name
  27.     This matches the equivalent functions in strftime.c.
  28.  
  29.     Also XPG4 simply states that %b = %h = %B = the locale's full or
  30.     abbreviated month name. In strftime.c these options are defined as:
  31.         b = h = the locale's abbreviated month name
  32.         B = the locale's full month name
  33.  
  34.    The coding below caters for both standards.
  35.  
  36.    Please test the following with (for example)
  37.     gcc -DDEBUG strptime.c
  38.     ./a.out "%x %X %A %b" "%x %X %a %B"
  39.  */
  40.  
  41. #include <ansidecl.h>
  42. #include <localeinfo.h>
  43. #include <ctype.h>
  44. #include <limits.h>
  45. #include <stddef.h>
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <time.h>
  50.  
  51. #if !defined(HAVE_GNU_LD) && !defined (__ELF__)
  52. #define    __tzname    tzname
  53. #define    __daylight    daylight
  54. #define    __timezone    timezone
  55. #endif
  56.  
  57. #define PERCENT            case '%'
  58. #define DAY_OF_WEEK_NAME    case 'a':\
  59.                 case 'A'    /* locale week name */
  60. #define MONTH_NAME        case 'b':\
  61.                 case 'B':\
  62.                 case 'h'    /* locale month name */
  63. #define DATE_AND_TIME        case 'c'    /* as in %x %X */
  64. #define DATE_AND_TIME_LOCALE    case 'C'    /* locale format */
  65. #define DAY_OF_MONTH        case 'd':\
  66.                 case 'e'    /* 01-31 */
  67. #define DATE_IN_SLASHES        case 'D'    /* e.g. %m/%d/%y */
  68. #define HOUR_IN_24        case 'H':\
  69.                 case 'k'    /* 00-23 */
  70. #define HOUR_IN_12        case 'I':\
  71.                 case 'i'    /* 01-12 */
  72. #define DAY_IN_YEAR        case 'j'    /* 001-366 */
  73. #define MONTH_NUMBER        case 'm'    /* 01-12 */
  74. #define MINUTE            case 'M'    /* 00-59 */
  75. #define AM_PM            case 'p'    /* locale format for AM/PM */
  76. #define TIME_WITH_COLONS    case 'r'    /* e.g. %I:%M:%S %p */
  77. #define HR_MIN_WITH_COLONS    case 'R'    /* %H:%M */
  78. #define SECONDS            case 'S'    /* 00-61 - leap sec */
  79. #define TIME_WITH_COLONS_24HR    case 'T'    /* %H:%M:%S */
  80. #define WEEK_NUM        case 'U'    /* week number of the year */
  81. #define WEEK_DAY_NUM        case 'w'    /* weekday number [0, 6] with
  82.                            Sunday as the first day of
  83.                            the week */
  84. #define WEEK_DAY_NUM_2        case 'W'    /* as %w except Monday is the
  85.                            first day of the week */
  86. #define DATE_LOCALE_FORMAT    case 'x'    /* locale format for date */
  87. #define TIME_LOCALE_FORMAT    case 'X'    /* locale format for time */
  88. #define YEAR_IN_CENTURY        case 'y'    /* 00-99 - unfortunately
  89.                            assumes that we are stuck
  90.                            in the 20th century */
  91. #define YEAR_WITH_CENTURY    case 'Y'    /* e.g. 1994 - expects 1900 */
  92.  
  93. static char *
  94. next_non_digit (char *p)
  95. {
  96.   while (p && isdigit (*p))
  97.     p++;
  98.   return p;
  99. }
  100.  
  101. char *
  102. DEFUN (strptime, (buf, format, tm),
  103.        char *buf AND CONST char *format AND register struct tm *tm)
  104. {
  105.   const char *pf = format;    /* pointer to the format pointer */
  106.   char *pb = buf;        /* pointer to the buffer pointer */
  107.   char *p;
  108.   int len,
  109.     found,
  110.     i;
  111.  
  112.   if (!pf || !pb)
  113.     return NULL;
  114.  
  115.   for (; *pf && *pb; pf++) {
  116.  
  117.     if (*pf == *pb) {
  118.       pb++;
  119.       continue;
  120.     }
  121.     if (*pf != '%')
  122.       continue;
  123.  
  124.     switch (*++pf) {
  125.  
  126.     PERCENT:
  127.       break;
  128.  
  129.     DAY_OF_WEEK_NAME:
  130.       for (i = 0; i < 7; i++)
  131.     if (found = !strncasecmp (pb,
  132.                   _time_info->full_wkday[i],
  133.                   len = strlen (_time_info->full_wkday[i])))
  134.       break;
  135.       if (!found)
  136.     for (i = 0; i < 7; i++)
  137.       if (found = !strncasecmp (pb,
  138.                 _time_info->abbrev_wkday[i],
  139.                 len = strlen (_time_info->abbrev_wkday[i])))
  140.         break;
  141.       if (found) {
  142.     pb += len;
  143.     tm->tm_wday = i;
  144.       }
  145.       break;
  146.  
  147.     MONTH_NAME:
  148.       for (i = 0; i < 12; i++)
  149.     if (found = !strncasecmp (pb,
  150.                   _time_info->full_month[i],
  151.                   len = strlen (_time_info->full_month[i])))
  152.       break;
  153.       if (!found)
  154.     for (i = 0; i < 12; i++)
  155.       if (found = !strncasecmp (pb,
  156.                 _time_info->abbrev_month[i],
  157.                 len = strlen (_time_info->abbrev_month[i])))
  158.         break;
  159.       if (found) {
  160.     pb += len;
  161.     tm->tm_mon = i;
  162.       }
  163.       break;
  164.  
  165.     DATE_AND_TIME:
  166.       p = strptime (pb, _time_info->date_time, tm);
  167.       pb += p - pb;
  168.       break;
  169.  
  170.     DATE_AND_TIME_LOCALE:
  171.       p = strptime (pb, _time_info->date_time, tm);
  172.       pb += p - pb;
  173.       break;
  174.  
  175.     DAY_OF_MONTH:
  176.       p = next_non_digit (pb);
  177.       sscanf (pb, "%.2d", &tm->tm_mday);
  178.       pb += p - pb;
  179.       break;
  180.  
  181.     DATE_IN_SLASHES:
  182.       p = strptime (pb, "%m/%d/%y", tm);
  183.       pb += p - pb;
  184.       break;
  185.  
  186.     HOUR_IN_24:
  187.       p = next_non_digit (pb);
  188.       sscanf (pb, "%.2d", &tm->tm_hour);
  189.       pb += p - pb;
  190.       break;
  191.  
  192.     HOUR_IN_12:
  193.       p = next_non_digit (pb);
  194.       sscanf (pb, "%.2d", &tm->tm_hour);
  195.       tm->tm_hour += 12;
  196.       pb += p - pb;
  197.       break;
  198.  
  199.     DAY_IN_YEAR:
  200.       p = next_non_digit (pb);
  201.       sscanf (pb, "%.3d", &tm->tm_yday);
  202.       if (tm->tm_yday)
  203.     tm->tm_yday--;
  204.       pb += p - pb;
  205.       break;
  206.  
  207.     MONTH_NUMBER:
  208.       p = next_non_digit (pb);
  209.       sscanf (pb, "%.2d", &tm->tm_mon);
  210.       if (tm->tm_mon)
  211.     tm->tm_mon--;
  212.       pb += p - pb;
  213.       break;
  214.  
  215.     MINUTE:
  216.       p = next_non_digit (pb);
  217.       sscanf (pb, "%.2d", &tm->tm_min);
  218.       pb += p - pb;
  219.       break;
  220.  
  221.     AM_PM:
  222.       if (!strncmp (pb, _time_info->ampm[0],
  223.             len = strlen (_time_info->ampm[0])))
  224.     pb += len;
  225.       else if (!strncmp (pb, _time_info->ampm[1],
  226.              len = strlen (_time_info->ampm[1])))
  227.     pb += len;
  228.       break;
  229.  
  230.     TIME_WITH_COLONS:
  231.       p = strptime (pb, "%I:%M:%S %p", tm);
  232.       pb += p - pb;
  233.       break;
  234.  
  235.     HR_MIN_WITH_COLONS:
  236.       p = strptime (pb, "%H:%M", tm);
  237.       pb += p - pb;
  238.       break;
  239.  
  240.     SECONDS:
  241.       p = next_non_digit (pb);
  242.       sscanf (pb, "%.2d", &tm->tm_sec);
  243.       pb += p - pb;
  244.       break;
  245.  
  246.     TIME_WITH_COLONS_24HR:
  247.       p = strptime (pb, "%H:%M:%S", tm);
  248.       pb += p - pb;
  249.       break;
  250.  
  251.     DATE_LOCALE_FORMAT:
  252.       p = strptime (pb, _time_info->date, tm);
  253.       pb += p - pb;
  254.       break;
  255.  
  256.     TIME_LOCALE_FORMAT:
  257.       p = strptime (pb, _time_info->time, tm);
  258.       pb += p - pb;
  259.       break;
  260.  
  261.     WEEK_DAY_NUM:
  262.       p = next_non_digit (pb);
  263.       sscanf (pb, "%.2d", &tm->tm_wday);
  264.       pb += p - pb;
  265.       break;
  266.  
  267.     YEAR_IN_CENTURY:
  268.       p = next_non_digit (pb);
  269.       sscanf (pb, "%.2d", &tm->tm_year);
  270.       pb += p - pb;
  271.       break;
  272.  
  273.     YEAR_WITH_CENTURY:
  274.       p = next_non_digit (pb);
  275.       sscanf (pb, "%.4d", &tm->tm_year);
  276.       tm->tm_year -= 1900;
  277.       pb += p - pb;
  278.       break;
  279.  
  280.     default: /* silent failure */
  281. #ifdef DEBUG
  282.       fprintf (stderr, "%s: unknown format specifier `%%%c'\n", __FILE__, *pf);
  283. #endif
  284.     }
  285.  
  286.   }
  287.   return pb;
  288. }
  289.  
  290. #ifdef DEBUG
  291. main (int argc, char **argv)
  292. {
  293.   struct tm *tm1,
  294.     tm2;
  295.   char buf[1024];
  296.   char format[1024];
  297.   int len = 1023,
  298.     err = 0;
  299.   time_t now;
  300.  
  301.   if (argv[1])
  302.     strcpy (format, argv[1]);
  303.   else
  304.     strcpy (format, "%I:%M:%S %p %m/%d/%y %a %b %y %j");
  305.  
  306.   time (&now);
  307.   tm1 = localtime (&now);
  308.   strftime (buf, len, format, tm1);
  309.   printf ("Start executing strftime(buf,\"%s\",tm)\n", format);
  310.   printf ("\treturned buf=\"%s\" \n",buf);
  311.  
  312.   if (argv[2])
  313.     strcpy (format, argv[2]);
  314.  
  315.   printf ("Now executing strptime(\"%s\",\"%s\",tm)\n",buf,format);
  316.   bzero (&tm2, sizeof (struct tm));
  317.   strptime (buf, format, &tm2);
  318.   if (tm1->tm_sec != tm2.tm_sec)
  319.     err++, printf ("\ttm_sec is different (%d - %d)\n", tm1->tm_sec, tm2.tm_sec);
  320.   if (tm1->tm_min != tm2.tm_min)
  321.     err++, printf ("\ttm_min is different (%d - %d)\n", tm1->tm_min, tm2.tm_min);
  322.   if (tm1->tm_hour != tm2.tm_hour)
  323.     err++, printf ("\ttm_hour is different (%d - %d)\n", tm1->tm_hour, tm2.tm_hour);
  324.   if (tm1->tm_mday != tm2.tm_mday)
  325.     err++, printf ("\ttm_mday is different (%d - %d)\n", tm1->tm_mday, tm2.tm_mday);
  326.   if (tm1->tm_mon != tm2.tm_mon)
  327.     err++, printf ("\ttm_mon is different (%d - %d)\n", tm1->tm_mon, tm2.tm_mon);
  328.   if (tm1->tm_year != tm2.tm_year)
  329.     err++, printf ("\ttm_year is different (%d - %d)\n", tm1->tm_year, tm2.tm_year);
  330.   if (tm1->tm_wday != tm2.tm_wday)
  331.     err++, printf ("\ttm_wday is different (%d - %d)\n", tm1->tm_wday, tm2.tm_wday);
  332.   if (tm1->tm_yday != tm2.tm_yday)
  333.     err++, printf ("\ttm_yday is different (%d - %d)\n", tm1->tm_yday, tm2.tm_yday);
  334.   if (tm1->tm_isdst != tm2.tm_isdst)
  335.     err++, printf ("\ttm_isdst is different (%d - %d)\n", tm1->tm_isdst, tm2.tm_isdst);
  336.  
  337.   if (!err)
  338.     printf ("Ok: time tm struct has been filled incorrectly\n");
  339.   else
  340.     printf ("%d out of %d fields filled correctly\n", 8 - err, 8);
  341. }
  342. #endif
  343.