]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
2005-04-26 Ulrich Drepper <drepper@redhat.com>
authorRoland McGrath <roland@gnu.org>
Mon, 18 Jul 2005 03:33:45 +0000 (03:33 +0000)
committerRoland McGrath <roland@gnu.org>
Mon, 18 Jul 2005 03:33:45 +0000 (03:33 +0000)
[BZ #1105]
* time/strptime_l.c (__strptime_internal): Handle 'z' to set
tm_gmtoff.
* time/Makefile (tests): Add tst-strptime2.
* time/tst-strptime2.c: New file.

time/Makefile
time/strptime_l.c
time/tst-strptime2.c [new file with mode: 0644]

index 7acc964fdc24d0000e0ac7fe16b9c47d31216501..799a8b70fa0fbc1b49a2483c518fbb2b0f7be721 100644 (file)
@@ -35,7 +35,7 @@ distribute := datemsk
 
 tests  := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
           tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
-          tst-mktime3
+          tst-mktime3 tst-strptime2
 
 include ../Rules
 
index cf0ab7153d99c025c9f12c5299926fa309bafb33..ccb838a229f1d050e3008d15b3ad309ffe188dce 100644 (file)
@@ -687,6 +687,42 @@ __strptime_internal (rp, fmt, tm, decided, era_cnt LOCALE_PARAM)
        case 'Z':
          /* XXX How to handle this?  */
          break;
+       case 'z':
+         /* We recognize two formats: if two digits are given, these
+            specify hours.  If fours digits are used, minutes are
+            also specified.  */
+         {
+           val = 0;
+           while (*rp == ' ')
+             ++rp;
+           if (*rp != '+' && *rp != '-')
+             return NULL;
+           bool neg = *rp++ == '-';
+           int n = 0;
+           while (n < 4 && *rp >= '0' && *rp <= '9')
+             {
+               val = val * 10 + *rp++ - '0';
+               ++n;
+             }
+           if (n == 2)
+             val *= 100;
+           else if (n != 4)
+             /* Only two or four digits recognized.  */
+             return NULL;
+           else
+             {
+               /* We have to convert the minutes into decimal.  */
+               if (val % 100 >= 60)
+                 return NULL;
+               val = (val / 100) * 100 + ((val % 100) * 50) / 30;
+             }
+           if (val > 1200)
+             return NULL;
+           tm->tm_gmtoff = (val * 3600) / 100;
+           if (neg)
+             tm->tm_gmtoff = -tm->tm_gmtoff;
+         }
+         break;
        case 'E':
 #ifdef _NL_CURRENT
          switch (*fmt++)
diff --git a/time/tst-strptime2.c b/time/tst-strptime2.c
new file mode 100644 (file)
index 0000000..73552bb
--- /dev/null
@@ -0,0 +1,59 @@
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+
+
+static const struct
+{
+  const char *fmt;
+  long int gmtoff;
+} tests[] =
+  {
+    { "1113472456 +1000", 36000 },
+    { "1113472456 -1000", -36000 },
+    { "1113472456 +10", 36000 },
+    { "1113472456 -10", -36000 },
+    { "1113472456 +1030", 37800 },
+    { "1113472456 -1030", -37800 },
+    { "1113472456 +0030", 1800 },
+    { "1113472456 -0030", -1800 },
+    { "1113472456 -1330", LONG_MAX },
+    { "1113472456 +1330", LONG_MAX },
+    { "1113472456 -1060", LONG_MAX },
+    { "1113472456 +1060", LONG_MAX },
+    { "1113472456  1030", LONG_MAX },
+  };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+int
+main (void)
+{
+  int result = 0;
+
+  for (int i = 0; i < ntests; ++i)
+    {
+      struct tm tm;
+
+      if (strptime (tests[i].fmt, "%s %z", &tm) == NULL)
+       {
+         if (tests[i].gmtoff != LONG_MAX)
+           {
+             printf ("round %d: strptime unexpectedly failed\n", i);
+             result = 1;
+           }
+         continue;
+       }
+
+      if (tm.tm_gmtoff != tests[i].gmtoff)
+       {
+         printf ("round %d: tm_gmtoff is %ld\n", i, (long int) tm.tm_gmtoff);
+         result = 1;
+       }
+    }
+
+  if (result == 0)
+    puts ("all OK");
+
+  return 0;
+}