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                       ]