From b4be570207b23269a87e97d50cfa6b9ea88e4749 Mon Sep 17 00:00:00 2001 From: christos Date: Tue, 4 Nov 2008 18:37:28 +0000 Subject: [PATCH] Our new syslogd seems to want to depend on %z which is a gnu extension. - While here, add all the rest of gnu extensions: %g, %G, %u. - Fix long standing bug where %Z would not work because "private.h" was not included. (Hi Brian!) --- lib/libc/time/strptime.3 | 53 ++++++++++++++++++++- lib/libc/time/strptime.c | 100 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 6 deletions(-) diff --git a/lib/libc/time/strptime.3 b/lib/libc/time/strptime.3 index 9c687c11c1fa..4ab046d50237 100644 --- a/lib/libc/time/strptime.3 +++ b/lib/libc/time/strptime.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: strptime.3,v 1.21 2008/04/30 13:10:51 martin Exp $ +.\" $NetBSD: strptime.3,v 1.22 2008/11/04 18:37:28 christos 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 April 25, 2008 +.Dd November 4, 2008 .Os .Dt STRPTIME 3 .Sh NAME @@ -115,6 +115,20 @@ the same as .It Cm \&%F the date as %Y-%m-%d (the ISO 8601 date format). +.It Cm \&%g +the year corresponding to the ISO week number, without the century. +.Po +A +.Nx +extension. +.Pc +.It Cm \&%G +the year corresponding to the ISO week number, with the century. +.Po +A +.Nx +extension. +.Pc .It Cm \&%h the same as .Cm \&%b . @@ -154,11 +168,29 @@ leading zeros are permitted but not required. any white-space, including none. .It Cm \&%T the time as %H:%M:%S. +.It Cm \&%u +the day of the week as a decimal number, where Monday = 1. +.Po +A +.Nx +extension. +.Pc .It Cm \&%U the week number of the year (Sunday as the first day of the week) as a decimal number [0,53]; leading zeros are permitted but not required. All days in a year preceding the first Sunday are considered to be in week 0. +.It Cm \&%V +the ISO 8601:1988 week number as a decimal number. +If the week (starting on Monday) that contains January 1 has more than +three days in the new year, then it is considered the first week of the +year. +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. +A +.Nx +extension. .It Cm \&%w the weekday as a decimal number [0,6], with 0 representing Sunday; leading zeros are permitted but not required. @@ -178,6 +210,23 @@ If specified in conjunction with \&%C, specifies the year [0,99] within that century. .It Cm \&%Y the year, including the century (i.e., 1996). +.It Cm \&%z +an ISO 8601 timezone specification. +This is either, +.Dq Z +for +.Ql UTC , +or the offset specified as: +.Dq [+-]hhmm +or +.Dq [+-]hh:mm +or +.Dq [+-]hh . +.Po +A +.Nx +extension. +.Pc .It Cm \&%Z timezone name or no characters when time zone information is unavailable. .Po diff --git a/lib/libc/time/strptime.c b/lib/libc/time/strptime.c index 6dff8b8d8cd8..00edceebfc65 100644 --- a/lib/libc/time/strptime.c +++ b/lib/libc/time/strptime.c @@ -1,4 +1,4 @@ -/* $NetBSD: strptime.c,v 1.28 2008/04/28 20:23:01 martin Exp $ */ +/* $NetBSD: strptime.c,v 1.29 2008/11/04 18:37:28 christos Exp $ */ /*- * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: strptime.c,v 1.28 2008/04/28 20:23:01 martin Exp $"); +__RCSID("$NetBSD: strptime.c,v 1.29 2008/11/04 18:37:28 christos Exp $"); #endif #include "namespace.h" @@ -41,6 +41,7 @@ __RCSID("$NetBSD: strptime.c,v 1.28 2008/04/28 20:23:01 martin Exp $"); #include #include #include +#include "private.h" #ifdef __weak_alias __weak_alias(strptime,_strptime) @@ -56,7 +57,8 @@ __weak_alias(strptime,_strptime) #define ALT_O 0x02 #define LEGAL_ALT(x) { if (alt_format & ~(x)) return NULL; } -static const char gmt[4] = { "GMT" }; +static char gmt[] = { "GMT" }; +static char utc[] = { "UTC" }; 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 *, @@ -68,7 +70,7 @@ strptime(const char *buf, const char *fmt, struct tm *tm) { unsigned char c; const unsigned char *bp; - int alt_format, i, split_year = 0; + int alt_format, i, split_year = 0, neg, offs; const char *new_fmt; bp = (const u_char *)buf; @@ -258,6 +260,30 @@ literal: LEGAL_ALT(ALT_O); continue; + case 'u': /* The day of week, monday = 1. */ + bp = conv_num(bp, &i, 1, 7); + tm->tm_wday = i % 7; + LEGAL_ALT(ALT_O); + continue; + + case 'g': /* The year corresponding to the ISO week + * number but without the century. + */ + bp = conv_num(bp, &i, 0, 99); + continue; + + case 'G': /* The year corresponding to the ISO week + * number with century. + */ + do + *bp++; + while (isdigit(*bp)); + continue; + + case 'V': /* The ISO 8601:1988 week number as decimal */ + bp = conv_num(bp, &i, 0, 53); + continue; + case 'Y': /* The year. */ i = TM_YEAR_BASE; /* just for data sanity... */ bp = conv_num(bp, &i, 0, 9999); @@ -312,6 +338,72 @@ literal: } continue; + case 'z': + /* + * We recognize all ISO 8601 formats: + * Z = Zulu time/UTC + * [+-]hhmm + * [+-]hh:mm + * [+-]hh + */ + while (isspace(*bp)) + bp++; + + switch (*bp++) { + case 'Z': + tm->tm_isdst = 0; +#ifdef TM_GMTOFF + tm->TM_GMTOFF = 0; +#endif +#ifdef TM_ZONE + tm->TM_ZONE = utc; +#endif + continue; + case '+': + neg = 0; + break; + case '-': + neg = 1; + break; + default: + return NULL; + } + offs = 0; + for (i = 0; i < 4; ) { + if (isdigit(*bp)) { + offs = offs * 10 + (*bp++ - '0'); + i++; + continue; + } + if (i == 2 && *bp == ':') { + bp++; + continue; + } + break; + } + switch (i) { + case 2: + offs *= 100; + break; + case 4: + i = offs % 100; + if (i >= 60) + return NULL; + /* Convert minutes into decimal */ + offs = (offs / 100) * 100 + (i * 50) / 30; + break; + default: + return NULL; + } + tm->tm_isdst = 0; /* XXX */ +#ifdef TM_GMTOFF + tm->TM_GMTOFF = offs; +#endif +#ifdef TM_ZONE + tm->TM_ZONE = NULL; /* XXX */ +#endif + continue; + /* * Miscellaneous conversions. */