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;