summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1998-03-15 06:49:02 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1998-03-15 06:49:02 +0000
commitda01281deeb457fb1c76ea91a5e32e0f89b768e1 (patch)
tree17c6f5c30bac3e4c3c9c1d8d14a03e2ae2773a96
parente42d3d5a02080909c4be95e281bcf76ae2987fae (diff)
Fix %m, %I, %S, %y, %C, and %j conversions. Fixes by nakayosh@kcn.or.jp
and myself. Some bugs noted by woods@most.weird.com.
-rw-r--r--lib/libc/time/strptime.353
-rw-r--r--lib/libc/time/strptime.c31
2 files changed, 48 insertions, 36 deletions
diff --git a/lib/libc/time/strptime.3 b/lib/libc/time/strptime.3
index e8b0a0989f4..4e4e80c20f7 100644
--- a/lib/libc/time/strptime.3
+++ b/lib/libc/time/strptime.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: strptime.3,v 1.4 1998/01/20 21:10:08 mycroft Exp $
+.\" $OpenBSD: strptime.3,v 1.2 1998/03/15 06:49:00 millert Exp $
.\"
.\" Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -33,7 +33,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd January 20, 1998
+.Dd March 14, 1998
.Os
.Dt STRPTIME 3
.Sh NAME
@@ -55,15 +55,15 @@ using the format specified by
.Pp
The
.Fa format
-string consists of zero or more conversion specifications and
-ordinary characters. All ordinary characters are copied directly into
-the buffer. A conversion specification consists of a percent sign `%'
-followed by one or two conversion characters which specify the replacement
-required. There must be white-space or other non-alphanumeric characters
-between any two conversion specifications.
+string consists of zero or more conversion specifications and ordinary
+characters. All ordinary characters are copied directly into the
+buffer. A conversion specification consists of a percent sign `%'
+followed by one or two conversion characters which specify the
+replacement required. There must be white-space or other
+non-alphanumeric characters between any two conversion specifications.
.Pp
The LC_TIME category defines the locale values for the conversion
-specifications. The following conversion specifications are supported:
+specifications. The following conversion specifications are supported:
.Bl -tag -width "xxxx"
.It Cm \&%a
the day of week, using the locale's weekday names;
@@ -80,11 +80,12 @@ the same as
.It Cm \&%c
the date and time, using the locale's date and time format.
.It Cm \&%C
-the century number [0,99];
-leading zeros are permitted but not required.
+the century number [0,99]; leading zeros are permitted but not required.
+Note that the converted value is added to the current value of the
+``tm_year'' field (in order that the "\&%y" conversion be useful).
.It Cm \&%d
the day of month [1,31];
-leading zeros are permitted but required.
+leading zeros are permitted but not required.
.It Cm \&%D
the date as %m/%d/%y.
.It Cm \&%e
@@ -119,7 +120,7 @@ any white-space
.It Cm \&%p
the locale's equivalent of a.m. or p.m..
.It Cm \&%r
-the time (12-hour clock) with %p, using the locale's time format.
+the time as %I:%M:%S %p.
.It Cm \&%R
the time as %H:%M.
.It Cm \&%S
@@ -147,12 +148,15 @@ the date, using the locale's date format.
.It Cm \&%X
the time, using the locale's time format.
.It Cm \&%y
-the year within the 20th century [69,99] or the 21st century [0,68];
-leading zeros are permitted but not required.
+the year within the current century. When a century is not otherwise
+specified, values in the range 69-99 refer to years in the twentieth
+century (1969 to 1999 inclusive); values in the range 00-68 refer
+to years in the twenty-first century (2000 to 2068 inclusive).
+Leading zeros are permitted but not required.
.It Cm \&%Y
-the year, including the century (i.e., 1996).
+the year, including the century (i.e., 1998).
.It Cm \&%%
-A `%' is written. No argument is converted.
+A `%' is written. No argument is converted.
.El
.Ss Modified conversion specifications
For compatibility, certain conversion specifications can be modified
@@ -160,20 +164,21 @@ by the
.Cm E
and
.Cm O
-modifier characters to indicate that an alternative format or specification
-should be used rather than the one normally used by the unmodified
-conversion specification. As there are currently neither alternative formats
-nor specifications supported by the system, the behavior will be as if the
-unmodified conversion specification were used.
+modifier characters to indicate that an alternative format or
+specification should be used rather than the one normally used by the
+unmodified conversion specification. As there are currently neither
+alternative formats nor specifications supported by the system, the
+behavior will be as if the unmodified conversion specification were
+used.
.Sh RETURN VALUES
If successful, the
.Nm
function returns a pointer to the character following the last character
-parsed. Otherwise, a null pointer is returned.
+parsed. Otherwise, a null pointer is returned.
.Sh SEE ALSO
.Xr strftime 3
.Sh STANDARDS
The
.Fn strptime
function conforms to
-.St -xpg4 .
+.St -xpg4.2 .
diff --git a/lib/libc/time/strptime.c b/lib/libc/time/strptime.c
index 82aa93c162a..c1f6cbbf5f5 100644
--- a/lib/libc/time/strptime.c
+++ b/lib/libc/time/strptime.c
@@ -36,7 +36,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: strptime.c,v 1.1 1998/02/04 22:22:43 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: strptime.c,v 1.2 1998/03/15 06:49:01 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/localedef.h>
@@ -68,6 +68,7 @@ strptime(buf, fmt, tm)
char c;
const char *bp;
int alt_format, i, len;
+ int century = TM_YEAR_BASE;
bp = buf;
@@ -131,9 +132,9 @@ literal:
return (0);
break;
- case 'r': /* The time in 12-hour clock representation. */
+ case 'r': /* The time as "%I:%M:%S %p". */
_LEGAL_ALT(0);
- if (!(bp = strptime(bp, _ctloc(t_fmt_ampm), tm)))
+ if (!(bp = strptime(bp, "%I:%M:%S %p", tm)))
return (0);
break;
@@ -210,7 +211,7 @@ literal:
if (!(_conv_num(&bp, &i, 0, 99)))
return (0);
- tm->tm_year = i * 100;
+ century = i * 100;
break;
case 'd': /* The day of month. */
@@ -234,7 +235,7 @@ literal:
/* FALLTHROUGH */
case 'I':
_LEGAL_ALT(_ALT_O);
- if (!(_conv_num(&bp, &tm->tm_hour, 0, 11)))
+ if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
return (0);
break;
@@ -242,6 +243,7 @@ literal:
_LEGAL_ALT(0);
if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
return (0);
+ tm->tm_yday--;
break;
case 'M': /* The minute. */
@@ -254,6 +256,7 @@ literal:
_LEGAL_ALT(_ALT_O);
if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
return (0);
+ tm->tm_mon--;
break;
case 'p': /* The locale's equivalent of AM/PM. */
@@ -284,7 +287,7 @@ literal:
case 'S': /* The seconds. */
_LEGAL_ALT(_ALT_O);
- if (!(_conv_num(&bp, &tm->tm_sec, 1, 61)))
+ if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
return (0);
break;
@@ -315,15 +318,19 @@ literal:
tm->tm_year = i - TM_YEAR_BASE;
break;
- case 'y': /* The year within 100 years of the epoch. */
+ case 'y': /* The year within the century (2 digits). */
_LEGAL_ALT(_ALT_E | _ALT_O);
if (!(_conv_num(&bp, &i, 0, 99)))
return (0);
- if (i <= 68)
- tm->tm_year = i + 2000 - TM_YEAR_BASE;
- else
- tm->tm_year = i + 1900 - TM_YEAR_BASE;
+ if (century == TM_YEAR_BASE) {
+ if (i <= 68)
+ tm->tm_year = i + 2000 - TM_YEAR_BASE;
+ else
+ tm->tm_year = i + 1900 - TM_YEAR_BASE;
+ } else {
+ tm->tm_year = i + century - TM_YEAR_BASE;
+ }
break;
/*
@@ -364,7 +371,7 @@ _conv_num(buf, dest, llim, ulim)
*dest += *(*buf)++ - '0';
} while ((*dest * 10 <= ulim) && **buf >= '0' && **buf <= '9');
- if (*dest < llim || *dest > ulim)
+ if (*dest < llim || *dest > ulim || isdigit(**buf))
return (0);
return (1);