Fri May 1 20:15:05 2009 UTC ()
Extend %z to support all RFC-2822 timezone formats.


(ginsbach)
diff -r1.23 -r1.24 src/lib/libc/time/strptime.3
diff -r1.31 -r1.32 src/lib/libc/time/strptime.c

cvs diff -r1.23 -r1.24 src/lib/libc/time/strptime.3 (expand / switch to unified diff)

--- src/lib/libc/time/strptime.3 2009/03/09 19:24:27 1.23
+++ src/lib/libc/time/strptime.3 2009/05/01 20:15:05 1.24
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1.\" $NetBSD: strptime.3,v 1.23 2009/03/09 19:24:27 joerg Exp $ 1.\" $NetBSD: strptime.3,v 1.24 2009/05/01 20:15:05 ginsbach Exp $
2.\" 2.\"
3.\" Copyright (c) 1997, 1998, 2008 The NetBSD Foundation, Inc. 3.\" Copyright (c) 1997, 1998, 2008 The NetBSD Foundation, Inc.
4.\" All rights reserved. 4.\" All rights reserved.
5.\" 5.\"
6.\" This file was contributed to The NetBSD Foundation by Klaus Klein. 6.\" This file was contributed to The NetBSD Foundation by Klaus Klein.
7.\" 7.\"
8.\" Redistribution and use in source and binary forms, with or without 8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions 9.\" modification, are permitted provided that the following conditions
10.\" are met: 10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright 11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer. 12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
@@ -16,27 +16,27 @@ @@ -16,27 +16,27 @@
16.\" 16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27.\" POSSIBILITY OF SUCH DAMAGE. 27.\" POSSIBILITY OF SUCH DAMAGE.
28.\" 28.\"
29.Dd November 4, 2008 29.Dd April 30, 2009
30.Dt STRPTIME 3 30.Dt STRPTIME 3
31.Os 31.Os
32.Sh NAME 32.Sh NAME
33.Nm strptime 33.Nm strptime
34.Nd converts a character string to a time value 34.Nd converts a character string to a time value
35.Sh LIBRARY 35.Sh LIBRARY
36.Lb libc 36.Lb libc
37.Sh SYNOPSIS 37.Sh SYNOPSIS
38.In time.h 38.In time.h
39.Ft char * 39.Ft char *
40.Fn strptime "const char * restrict buf" "const char * restrict format" "struct tm * restrict tm" 40.Fn strptime "const char * restrict buf" "const char * restrict format" "struct tm * restrict tm"
41.Sh DESCRIPTION 41.Sh DESCRIPTION
42The 42The
@@ -178,60 +178,109 @@ extension. @@ -178,60 +178,109 @@ extension.
178.It Cm \&%U 178.It Cm \&%U
179the week number of the year (Sunday as the first day of the week) 179the week number of the year (Sunday as the first day of the week)
180as a decimal number [0,53]; 180as a decimal number [0,53];
181leading zeros are permitted but not required. 181leading zeros are permitted but not required.
182All days in a year preceding the first Sunday are considered to be in week 0. 182All days in a year preceding the first Sunday are considered to be in week 0.
183.It Cm \&%V 183.It Cm \&%V
184the ISO 8601:1988 week number as a decimal number. 184the ISO 8601:1988 week number as a decimal number.
185If the week (starting on Monday) that contains January 1 has more than 185If the week (starting on Monday) that contains January 1 has more than
186three days in the new year, then it is considered the first week of the 186three days in the new year, then it is considered the first week of the
187year. 187year.
188If it has fewer than four days in the new year, then it is considered 188If it has fewer than four days in the new year, then it is considered
189the last week of the previous year. 189the last week of the previous year.
190Weeks are numbered from 1 to 53. 190Weeks are numbered from 1 to 53.
 191.Po
191A 192A
192.Nx 193.Nx
193extension. 194extension.
 195.Pc
194.It Cm \&%w 196.It Cm \&%w
195the weekday as a decimal number [0,6], with 0 representing Sunday; 197the weekday as a decimal number [0,6], with 0 representing Sunday;
196leading zeros are permitted but not required. 198leading zeros are permitted but not required.
197.It Cm \&%W 199.It Cm \&%W
198the week number of the year (Monday as the first day of the week) 200the week number of the year (Monday as the first day of the week)
199as a decimal number [0,53]; 201as a decimal number [0,53];
200leading zeros are permitted but not required. 202leading zeros are permitted but not required.
201All days in a year preceding the first Monday are considered to be in week 0. 203All days in a year preceding the first Monday are considered to be in week 0.
202.It Cm \&%x 204.It Cm \&%x
203the date, using the locale's date format. 205the date, using the locale's date format.
204.It Cm \&%X 206.It Cm \&%X
205the time, using the locale's time format. 207the time, using the locale's time format.
206.It Cm \&%y 208.It Cm \&%y
207the year within the 20th century [69,99] or the 21st century [0,68]; 209the year within the 20th century [69,99] or the 21st century [0,68];
208leading zeros are permitted but not required. 210leading zeros are permitted but not required.
209If specified in conjunction 211If specified in conjunction
210with \&%C, specifies the year [0,99] within that century. 212with \&%C, specifies the year [0,99] within that century.
211.It Cm \&%Y 213.It Cm \&%Y
212the year, including the century (i.e., 1996). 214the year, including the century (i.e., 1996).
213.It Cm \&%z 215.It Cm \&%z
214an ISO 8601 timezone specification. 216an ISO 8601 or RFC-2822 timezone specification.
215This is either, 217This is one of the following:
 218the offset from
 219Coordinated Universal Time
 220.Pq Ql UTC
 221specified as:
 222.Dq [+-]hhmm ,
 223.Dq [+-]hh:mm ,
 224or
 225.Dq [+-]hh ;
 226.Ql UTC
 227specified as:
 228.Dq GMT
 229.Pq Ql Greenwich Mean Time ,
 230.Dq UT
 231.Pq Ql Universal Time ,
 232or
216.Dq Z 233.Dq Z
217for 234.Pq Ql Zulu Time ;
218.Ql UTC , 235a three character US timezone specified as:
219or the offset specified as: 236.Dq EDT ,
220.Dq [+-]hhmm 237.Dq EST ,
 238.Dq CDT ,
 239.Dq CST ,
 240.Dq MDT ,
 241.Dq MST ,
 242.Dq PDT ,
221or 243or
222.Dq [+-]hh:mm 244.Dq PST ,
 245with the first letter standing for
 246.Ql Eastern
 247.Pq Dq E ,
 248.Ql Central
 249.Pq Dq C ,
 250.Ql Mountain
 251.Pq Dq M
 252or
 253.Ql Pacific
 254.Pq Dq P ,
 255and the second letter standing for
 256.Ql Daylight
 257.Po
 258.Dq D
 259or summer
 260.Pc
 261time
223or 262or
224.Dq [+-]hh . 263.Ql Standard
 264.Pq Dq S
 265time;
 266a single letter military timezone specified as:
 267.Dq A
 268through
 269.Dq I
 270and
 271.Dq K
 272through
 273.Dq Y .
225.Po 274.Po
226A 275A
227.Nx 276.Nx
228extension. 277extension.
229.Pc 278.Pc
230.It Cm \&%Z 279.It Cm \&%Z
231timezone name or no characters when time zone information is unavailable. 280timezone name or no characters when time zone information is unavailable.
232.Po 281.Po
233A 282A
234.Nx 283.Nx
235extension. 284extension.
236.Pc 285.Pc
237.It Cm \&%% 286.It Cm \&%%

cvs diff -r1.31 -r1.32 src/lib/libc/time/strptime.c (expand / switch to unified diff)

--- src/lib/libc/time/strptime.c 2008/11/04 21:08:33 1.31
+++ src/lib/libc/time/strptime.c 2009/05/01 20:15:05 1.32
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: strptime.c,v 1.31 2008/11/04 21:08:33 christos Exp $ */ 1/* $NetBSD: strptime.c,v 1.32 2009/05/01 20:15:05 ginsbach Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code was contributed to The NetBSD Foundation by Klaus Klein. 7 * This code was contributed to The NetBSD Foundation by Klaus Klein.
8 * Heavily optimised by David Laight 8 * Heavily optimised by David Laight
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -21,27 +21,27 @@ @@ -21,27 +21,27 @@
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#if defined(LIBC_SCCS) && !defined(lint) 33#if defined(LIBC_SCCS) && !defined(lint)
34__RCSID("$NetBSD: strptime.c,v 1.31 2008/11/04 21:08:33 christos Exp $"); 34__RCSID("$NetBSD: strptime.c,v 1.32 2009/05/01 20:15:05 ginsbach Exp $");
35#endif 35#endif
36 36
37#include "namespace.h" 37#include "namespace.h"
38#include <sys/localedef.h> 38#include <sys/localedef.h>
39#include <ctype.h> 39#include <ctype.h>
40#include <locale.h> 40#include <locale.h>
41#include <string.h> 41#include <string.h>
42#include <time.h> 42#include <time.h>
43#include <tzfile.h> 43#include <tzfile.h>
44#include "private.h" 44#include "private.h"
45 45
46#ifdef __weak_alias 46#ifdef __weak_alias
47__weak_alias(strptime,_strptime) 47__weak_alias(strptime,_strptime)
@@ -49,38 +49,45 @@ __weak_alias(strptime,_strptime) @@ -49,38 +49,45 @@ __weak_alias(strptime,_strptime)
49 49
50#define _ctloc(x) (_CurrentTimeLocale->x) 50#define _ctloc(x) (_CurrentTimeLocale->x)
51 51
52/* 52/*
53 * We do not implement alternate representations. However, we always 53 * We do not implement alternate representations. However, we always
54 * check whether a given modifier is allowed for a certain conversion. 54 * check whether a given modifier is allowed for a certain conversion.
55 */ 55 */
56#define ALT_E 0x01 56#define ALT_E 0x01
57#define ALT_O 0x02 57#define ALT_O 0x02
58#define LEGAL_ALT(x) { if (alt_format & ~(x)) return NULL; } 58#define LEGAL_ALT(x) { if (alt_format & ~(x)) return NULL; }
59 59
60static char gmt[] = { "GMT" }; 60static char gmt[] = { "GMT" };
61static char utc[] = { "UTC" }; 61static char utc[] = { "UTC" };
 62/* RFC-822/RFC-2822 */
 63static const char * const nast[5] = {
 64 "EST", "CST", "MST", "PST", "\0\0\0"
 65};
 66static const char * const nadt[5] = {
 67 "EDT", "CDT", "MDT", "PDT", "\0\0\0"
 68};
62 69
63static const u_char *conv_num(const unsigned char *, int *, uint, uint); 70static const u_char *conv_num(const unsigned char *, int *, uint, uint);
64static const u_char *find_string(const u_char *, int *, const char * const *, 71static const u_char *find_string(const u_char *, int *, const char * const *,
65 const char * const *, int); 72 const char * const *, int);
66 73
67 74
68char * 75char *
69strptime(const char *buf, const char *fmt, struct tm *tm) 76strptime(const char *buf, const char *fmt, struct tm *tm)
70{ 77{
71 unsigned char c; 78 unsigned char c;
72 const unsigned char *bp; 79 const unsigned char *bp, *ep;
73 int alt_format, i, split_year = 0, neg, offs; 80 int alt_format, i, split_year = 0, neg = 0, offs;
74 const char *new_fmt; 81 const char *new_fmt;
75 82
76 bp = (const u_char *)buf; 83 bp = (const u_char *)buf;
77 84
78 while (bp != NULL && (c = *fmt++) != '\0') { 85 while (bp != NULL && (c = *fmt++) != '\0') {
79 /* Clear `alternate' modifier prior to new conversion. */ 86 /* Clear `alternate' modifier prior to new conversion. */
80 alt_format = 0; 87 alt_format = 0;
81 i = 0; 88 i = 0;
82 89
83 /* Eat up white-space. */ 90 /* Eat up white-space. */
84 if (isspace(c)) { 91 if (isspace(c)) {
85 while (isspace(*bp)) 92 while (isspace(*bp))
86 bp++; 93 bp++;
@@ -310,72 +317,131 @@ literal: @@ -310,72 +317,131 @@ literal:
310 317
311 case 'Z': 318 case 'Z':
312 tzset(); 319 tzset();
313 if (strncmp((const char *)bp, gmt, 3) == 0) { 320 if (strncmp((const char *)bp, gmt, 3) == 0) {
314 tm->tm_isdst = 0; 321 tm->tm_isdst = 0;
315#ifdef TM_GMTOFF 322#ifdef TM_GMTOFF
316 tm->TM_GMTOFF = 0; 323 tm->TM_GMTOFF = 0;
317#endif 324#endif
318#ifdef TM_ZONE 325#ifdef TM_ZONE
319 tm->TM_ZONE = gmt; 326 tm->TM_ZONE = gmt;
320#endif 327#endif
321 bp += 3; 328 bp += 3;
322 } else { 329 } else {
323 const unsigned char *ep; 
324 
325 ep = find_string(bp, &i, 330 ep = find_string(bp, &i,
326 (const char * const *)tzname, 331 (const char * const *)tzname,
327 NULL, 2); 332 NULL, 2);
328 if (ep != NULL) { 333 if (ep != NULL) {
329 tm->tm_isdst = i; 334 tm->tm_isdst = i;
330#ifdef TM_GMTOFF 335#ifdef TM_GMTOFF
331 tm->TM_GMTOFF = -(timezone); 336 tm->TM_GMTOFF = -(timezone);
332#endif 337#endif
333#ifdef TM_ZONE 338#ifdef TM_ZONE
334 tm->TM_ZONE = tzname[i]; 339 tm->TM_ZONE = tzname[i];
335#endif 340#endif
336 } 341 }
337 bp = ep; 342 bp = ep;
338 } 343 }
339 continue; 344 continue;
340 345
341 case 'z': 346 case 'z':
342 /* 347 /*
343 * We recognize all ISO 8601 formats: 348 * We recognize all ISO 8601 formats:
344 * Z = Zulu time/UTC 349 * Z = Zulu time/UTC
345 * [+-]hhmm 350 * [+-]hhmm
346 * [+-]hh:mm 351 * [+-]hh:mm
347 * [+-]hh 352 * [+-]hh
 353 * We recognize all RFC-822/RFC-2822 formats:
 354 * UT|GMT
 355 * North American : UTC offsets
 356 * E[DS]T = Eastern : -4 | -5
 357 * C[DS]T = Central : -5 | -6
 358 * M[DS]T = Mountain: -6 | -7
 359 * P[DS]T = Pacific : -7 | -8
 360 * Military
 361 * [A-IL-M] = -1 ... -9 (J not used)
 362 * [N-Y] = +1 ... +12
348 */ 363 */
349 while (isspace(*bp)) 364 while (isspace(*bp))
350 bp++; 365 bp++;
351 366
352 switch (*bp++) { 367 switch (*bp++) {
 368 case 'G':
 369 if (*bp++ != 'M')
 370 return NULL;
 371 /*FALLTHROUGH*/
 372 case 'U':
 373 if (*bp++ != 'T')
 374 return NULL;
 375 /*FALLTHROUGH*/
353 case 'Z': 376 case 'Z':
354 tm->tm_isdst = 0; 377 tm->tm_isdst = 0;
355#ifdef TM_GMTOFF 378#ifdef TM_GMTOFF
356 tm->TM_GMTOFF = 0; 379 tm->TM_GMTOFF = 0;
357#endif 380#endif
358#ifdef TM_ZONE 381#ifdef TM_ZONE
359 tm->TM_ZONE = utc; 382 tm->TM_ZONE = utc;
360#endif 383#endif
361 continue; 384 continue;
362 case '+': 385 case '+':
363 neg = 0; 386 neg = 0;
364 break; 387 break;
365 case '-': 388 case '-':
366 neg = 1; 389 neg = 1;
367 break; 390 break;
368 default: 391 default:
 392 --bp;
 393 ep = find_string(bp, &i, nast, NULL, 4);
 394 if (ep != NULL) {
 395#ifdef TM_GMTOFF
 396 tm->TM_GMTOFF = -5 - i;
 397#endif
 398#ifdef TM_ZONE
 399 tm->TM_ZONE = __UNCONST(nast[i]);
 400#endif
 401 bp = ep;
 402 continue;
 403 }
 404 ep = find_string(bp, &i, nadt, NULL, 4);
 405 if (ep != NULL) {
 406 tm->tm_isdst = 1;
 407#ifdef TM_GMTOFF
 408 tm->TM_GMTOFF = -4 - i;
 409#endif
 410#ifdef TM_ZONE
 411 tm->TM_ZONE = __UNCONST(nadt[i]);
 412#endif
 413 bp = ep;
 414 continue;
 415 }
 416
 417 if ((*bp >= 'A' && *bp <= 'I') ||
 418 (*bp >= 'L' && *bp <= 'Y')) {
 419#ifdef TM_GMTOFF
 420 /* Argh! No 'J'! */
 421 if (*bp >= 'A' && *bp <= 'I')
 422 tm->TM_GMTOFF =
 423 ('A' - 1) - (int)*bp;
 424 else if (*bp >= 'L' && *bp <= 'M')
 425 tm->TM_GMTOFF = 'A' - (int)*bp;
 426 else if (*bp >= 'N' && *bp <= 'Y')
 427 tm->TM_GMTOFF = (int)*bp - 'M';
 428#endif
 429#ifdef TM_ZONE
 430 tm->TM_ZONE = NULL; /* XXX */
 431#endif
 432 bp++;
 433 continue;
 434 }
369 return NULL; 435 return NULL;
370 } 436 }
371 offs = 0; 437 offs = 0;
372 for (i = 0; i < 4; ) { 438 for (i = 0; i < 4; ) {
373 if (isdigit(*bp)) { 439 if (isdigit(*bp)) {
374 offs = offs * 10 + (*bp++ - '0'); 440 offs = offs * 10 + (*bp++ - '0');
375 i++; 441 i++;
376 continue; 442 continue;
377 } 443 }
378 if (i == 2 && *bp == ':') { 444 if (i == 2 && *bp == ':') {
379 bp++; 445 bp++;
380 continue; 446 continue;
381 } 447 }