Module Name:    src
Committed By:   ginsbach
Date:           Fri May  1 20:15:05 UTC 2009

Modified Files:
        src/lib/libc/time: strptime.3 strptime.c

Log Message:
Extend %z to support all RFC-2822 timezone formats.


To generate a diff of this commit:
cvs rdiff -u -r1.23 -r1.24 src/lib/libc/time/strptime.3
cvs rdiff -u -r1.31 -r1.32 src/lib/libc/time/strptime.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/time/strptime.3
diff -u src/lib/libc/time/strptime.3:1.23 src/lib/libc/time/strptime.3:1.24
--- src/lib/libc/time/strptime.3:1.23	Mon Mar  9 19:24:27 2009
+++ src/lib/libc/time/strptime.3	Fri May  1 20:15:05 2009
@@ -1,4 +1,4 @@
-.\"	$NetBSD: strptime.3,v 1.23 2009/03/09 19:24:27 joerg Exp $
+.\"	$NetBSD: strptime.3,v 1.24 2009/05/01 20:15:05 ginsbach Exp $
 .\"
 .\" Copyright (c) 1997, 1998, 2008 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -26,7 +26,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 4, 2008
+.Dd April 30, 2009
 .Dt STRPTIME 3
 .Os
 .Sh NAME
@@ -188,9 +188,11 @@
 If it has fewer than four days in the new year, then it is considered
 the last week of the previous year.
 Weeks are numbered from 1 to 53.
+.Po
 A
 .Nx
 extension.
+.Pc
 .It Cm \&%w
 the weekday as a decimal number [0,6], with 0 representing Sunday;
 leading zeros are permitted but not required.
@@ -211,17 +213,64 @@
 .It Cm \&%Y
 the year, including the century (i.e., 1996).
 .It Cm \&%z
-an ISO 8601 timezone specification.
-This is either,
+an ISO 8601 or RFC-2822 timezone specification.
+This is one of the following:
+the offset from
+Coordinated Universal Time
+.Pq Ql UTC
+specified as:
+.Dq [+-]hhmm ,
+.Dq [+-]hh:mm ,
+or
+.Dq [+-]hh ;
+.Ql UTC
+specified as:
+.Dq GMT
+.Pq Ql Greenwich Mean Time ,
+.Dq UT
+.Pq Ql Universal Time ,
+or
 .Dq Z
-for
-.Ql UTC ,
-or the offset specified as:
-.Dq [+-]hhmm
+.Pq Ql Zulu Time ;
+a three character US timezone specified as:
+.Dq EDT ,
+.Dq EST ,
+.Dq CDT ,
+.Dq CST ,
+.Dq MDT ,
+.Dq MST ,
+.Dq PDT ,
 or
-.Dq [+-]hh:mm
+.Dq PST ,
+with the first letter standing for
+.Ql Eastern
+.Pq Dq E ,
+.Ql Central
+.Pq Dq C ,
+.Ql Mountain
+.Pq Dq M
+or
+.Ql Pacific
+.Pq Dq P ,
+and the second letter standing for
+.Ql Daylight
+.Po
+.Dq D
+or summer
+.Pc
+time
 or
-.Dq [+-]hh .
+.Ql Standard
+.Pq Dq S
+time;
+a single letter military timezone specified as:
+.Dq A
+through
+.Dq I
+and 
+.Dq K
+through
+.Dq Y .
 .Po
 A
 .Nx

Index: src/lib/libc/time/strptime.c
diff -u src/lib/libc/time/strptime.c:1.31 src/lib/libc/time/strptime.c:1.32
--- src/lib/libc/time/strptime.c:1.31	Tue Nov  4 21:08:33 2008
+++ src/lib/libc/time/strptime.c	Fri May  1 20:15:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: strptime.c,v 1.31 2008/11/04 21:08:33 christos Exp $	*/
+/*	$NetBSD: strptime.c,v 1.32 2009/05/01 20:15:05 ginsbach Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: strptime.c,v 1.31 2008/11/04 21:08:33 christos Exp $");
+__RCSID("$NetBSD: strptime.c,v 1.32 2009/05/01 20:15:05 ginsbach Exp $");
 #endif
 
 #include "namespace.h"
@@ -59,6 +59,13 @@
 
 static char gmt[] = { "GMT" };
 static char utc[] = { "UTC" };
+/* RFC-822/RFC-2822 */
+static const char * const nast[5] = {
+       "EST",    "CST",    "MST",    "PST",    "\0\0\0"
+};
+static const char * const nadt[5] = {
+       "EDT",    "CDT",    "MDT",    "PDT",    "\0\0\0"
+};
 
 static const u_char *conv_num(const unsigned char *, int *, uint, uint);
 static const u_char *find_string(const u_char *, int *, const char * const *,
@@ -69,8 +76,8 @@
 strptime(const char *buf, const char *fmt, struct tm *tm)
 {
 	unsigned char c;
-	const unsigned char *bp;
-	int alt_format, i, split_year = 0, neg, offs;
+	const unsigned char *bp, *ep;
+	int alt_format, i, split_year = 0, neg = 0, offs;
 	const char *new_fmt;
 
 	bp = (const u_char *)buf;
@@ -320,8 +327,6 @@
 #endif
 				bp += 3;
 			} else {
-				const unsigned char *ep;
-
 				ep = find_string(bp, &i,
 					       	 (const char * const *)tzname,
 					       	  NULL, 2);
@@ -345,11 +350,29 @@
 			 * [+-]hhmm
 			 * [+-]hh:mm
 			 * [+-]hh
+			 * We recognize all RFC-822/RFC-2822 formats:
+			 * UT|GMT
+			 *          North American : UTC offsets
+			 * E[DS]T = Eastern : -4 | -5
+			 * C[DS]T = Central : -5 | -6
+			 * M[DS]T = Mountain: -6 | -7
+			 * P[DS]T = Pacific : -7 | -8
+			 *          Military
+			 * [A-IL-M] = -1 ... -9 (J not used)
+			 * [N-Y]  = +1 ... +12
 			 */
 			while (isspace(*bp))
 				bp++;
 
 			switch (*bp++) {
+			case 'G':
+				if (*bp++ != 'M')
+					return NULL;
+				/*FALLTHROUGH*/
+			case 'U':
+				if (*bp++ != 'T')
+					return NULL;
+				/*FALLTHROUGH*/
 			case 'Z':
 				tm->tm_isdst = 0;
 #ifdef TM_GMTOFF
@@ -366,6 +389,49 @@
 				neg = 1;
 				break;
 			default:
+				--bp;
+				ep = find_string(bp, &i, nast, NULL, 4);
+				if (ep != NULL) {
+#ifdef TM_GMTOFF
+					tm->TM_GMTOFF = -5 - i;
+#endif
+#ifdef TM_ZONE
+					tm->TM_ZONE = __UNCONST(nast[i]);
+#endif
+					bp = ep;
+					continue;
+				}
+				ep = find_string(bp, &i, nadt, NULL, 4);
+				if (ep != NULL) {
+					tm->tm_isdst = 1;
+#ifdef TM_GMTOFF
+					tm->TM_GMTOFF = -4 - i;
+#endif
+#ifdef TM_ZONE
+					tm->TM_ZONE = __UNCONST(nadt[i]);
+#endif
+					bp = ep;
+					continue;
+				}
+
+				if ((*bp >= 'A' && *bp <= 'I') ||
+				    (*bp >= 'L' && *bp <= 'Y')) {
+#ifdef TM_GMTOFF
+					/* Argh! No 'J'! */
+					if (*bp >= 'A' && *bp <= 'I')
+						tm->TM_GMTOFF =
+						    ('A' - 1) - (int)*bp;
+					else if (*bp >= 'L' && *bp <= 'M')
+						tm->TM_GMTOFF = 'A' - (int)*bp;
+					else if (*bp >= 'N' && *bp <= 'Y')
+						tm->TM_GMTOFF = (int)*bp - 'M';
+#endif
+#ifdef TM_ZONE
+					tm->TM_ZONE = NULL; /* XXX */
+#endif
+					bp++;
+					continue;
+				}
 				return NULL;
 			}
 			offs = 0;

Reply via email to