about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2005-07-18 03:33:45 +0000
committerRoland McGrath <roland@gnu.org>2005-07-18 03:33:45 +0000
commitb5bb1655ab7cc2991d4389c3180ece3e4de47cea (patch)
tree7dbef27cd6ab978e4ecc697b166cb5d59b544952
parent0973e844870b17f8231c3c0f5a2dae042ce6bfc0 (diff)
downloadglibc-b5bb1655ab7cc2991d4389c3180ece3e4de47cea.tar.gz
glibc-b5bb1655ab7cc2991d4389c3180ece3e4de47cea.tar.xz
glibc-b5bb1655ab7cc2991d4389c3180ece3e4de47cea.zip
2005-04-26 Ulrich Drepper <drepper@redhat.com>
	[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.
-rw-r--r--time/Makefile2
-rw-r--r--time/strptime_l.c36
-rw-r--r--time/tst-strptime2.c59
3 files changed, 96 insertions, 1 deletions
diff --git a/time/Makefile b/time/Makefile
index 7acc964fdc..799a8b70fa 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -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
 
diff --git a/time/strptime_l.c b/time/strptime_l.c
index cf0ab7153d..ccb838a229 100644
--- a/time/strptime_l.c
+++ b/time/strptime_l.c
@@ -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
index 0000000000..73552bb8f8
--- /dev/null
+++ b/time/tst-strptime2.c
@@ -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;
+}