about summary refs log tree commit diff
path: root/time
diff options
context:
space:
mode:
Diffstat (limited to 'time')
-rw-r--r--time/Makefile4
-rw-r--r--time/strptime_l.c36
-rw-r--r--time/tst-strptime2.c59
3 files changed, 97 insertions, 2 deletions
diff --git a/time/Makefile b/time/Makefile
index 7acc964fdc..14313563eb 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-2002,2003,2004 Free Software Foundation, Inc.
+# Copyright (C) 1991-2003, 2004, 2005 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -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 01c4f8282a..dc0cc686fd 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;
+}