Topic: time_get should refer to strptime
Author: brendan@zen.org (Brendan Kehoe)
Date: Tue, 27 May 2003 17:19:34 +0000 (UTC) Raw View
In IEEE Std 1003.1-2001, strptime was adjusted to have '%y' behave
slightly differently; strftime, however, does not include the same
adjusted rules.
Now, strptime is supposed to add 100 if the year being seen is
[00..69) to make it be the year 2000..2069. Otherwise, it must be
1970..1999.
The puzzle appears when you have a tm struct with tm_year set to
something like 155, and try to use time_get and time_put with it.
In the C++ standard, we say at 22.2.5.1.2.4/1 that
time_get<>::do_get_date()
Reads characters starting at s until it has extracted those struct
tm members, and remaining format characters, used by
time_put<>::put()
to produce the format specified by 'x', or until it encounters an
error.
For the classic C locale, this according to C99 7.23.3.5 will be
''%m/%d%y'':
%x equivalent to ''%m/%d/%y''.
In the C++ standard, 22.2.5.3.1.1/4 says
The first character of each sequence is equal to '%', followed by
an optional modifier character mod237) and a format specifier
character
spec as defined for the function strftime.
That would seem to suggest that time_get<>::do_get_date() should use
the interpretation of the specifiers as described for strftime. i.e.,
when '%x' for the locale gives us '%m/%d/%y', we should interpret each
of those things as defined by strftime.
However, IEEE Std 1003.1-2001 has '%y' in that '%m/%d/%y' set mean
something different with strftime than with strptime, pointing out
that strftime is used for printing, while strptime is used for
parsing.
strftime, as defined in IEEE Std 1003.1-2001, should see %y as
%y
Replaced by the last two digits of the year as a decimal
number
[00,99]. [ tm_year]
strptime, in the same standard, is different:
%y
The year within century. When a century is not otherwise
specified, values in the range [69,99] shall refer to years
1969 to 1999 inclusive, and values in the range [00,68]
shall
refer to years 2000 to 2068 inclusive; leading zeros shall
be
permitted but shall not be required.
Note:
It is expected that in a future version of
IEEE Std 1003.1-2001 the default century inferred from
a
2-digit year will change. (This would apply to all
commands accepting a 2-digit year as input.)
That makes sense for code that's calling strftime to print (put) a
date, and for code that's calling strptime to parse (get) a date.
It does not make sense that the standard is apparently directing
implementers to base their time_get<>::do_get_date() on the standard
for strftime. I believe it should instead state that strptime's
format specifiers, and the rules for them, are the appropriate match
for time_get<>::do_get_date().
Otherwise, if you to time_put<>::put() with a tm_year of 155, a call
then to time_get<>::do_get_date() with the string put() gave us would
yield a tm struct whose tm_year is the 2-digit number of 55, not the
155 we started with.
I believe one fix could be to rephrase the sentence at 22.2.5.1.2.4/1
to instead state that for time_get<>::do_get_date(), the effects are
that it should use strptime's rules for the format specified by '%x',
not stating that the definition of time_put<>::put() plays as much of
a role in it. Thus, a "C" locale value of '%m/%d/%y' would be what
you do for '%x', but each of '%m', '%d', and '%y' (most importantly)
are based on those in the definition of strptime, not the strftime
mentioned for time_put<>::put().
B
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]