stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r424870 - /incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp
Date Mon, 24 Jul 2006 00:52:31 GMT
Author: sebor
Date: Sun Jul 23 17:52:31 2006
New Revision: 424870

URL: http://svn.apache.org/viewvc?rev=424870&view=rev
Log:
2006-07-23  Martin Sebor  <sebor@roguewave.com>

	STDCXX-4
	* 22.locale.time.get.cpp: New test exercising the std::time_get facet.

Added:
    incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp   (with props)

Added: incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp?rev=424870&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp (added)
+++ incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp Sun Jul 23 17:52:31 2006
@@ -0,0 +1,1696 @@
+/***************************************************************************
+ *
+ * 22.locale.time.get.cpp - tests exercising the std::time_get facet
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ *
+ * Copyright 2001-2006 Rogue Wave Software.
+ * 
+ **************************************************************************/
+
+#include <locale>
+#include <sstream>   // for stringstream
+
+#include <climits>   // for INT_{MIN,MAX}
+#include <clocale>   // for LC_ALL
+#include <cstdio>    // for fprintf()
+#include <cstdlib>   // for getenv()
+#include <cstring>   // for memcmp(), strlen()
+#include <ctime>     // for struct tm
+
+#include <driver.h>      // for rw_test()
+#include <file.h>        // for rw_nextfd()
+#include <rw_locale.h>   // for rw_locales()
+
+/**************************************************************************/
+
+template <class charT>
+void do_test (int lineno, charT, const char *cname,
+              std::tm val, const char *pat, int consumed,
+              const char *fmt, int flags, int err_expect = -1)
+{
+    std::basic_ostringstream<charT> ostrm;
+
+    typedef std::istreambuf_iterator<charT> InIter;
+    typedef std::ostreambuf_iterator<charT> OutIter;
+
+    const std::time_get<charT, InIter> &tg =
+        std::use_facet<std::time_get<charT, InIter> >(ostrm.getloc ());
+
+    const std::time_put<charT, OutIter> &tp =
+        std::use_facet<std::time_put<charT, OutIter> >(ostrm.getloc ());
+
+    ostrm.flags (std::ios_base::fmtflags (flags));
+
+    charT wpatbuf [256];
+    for (std::size_t j = 0; !!(wpatbuf [j] = pat [j]); ++j);
+
+    const charT *wpat    = wpatbuf;
+    const charT *wpatend = wpat + std::char_traits<charT>::length (wpat);
+
+    // format string
+    OutIter it (ostrm);
+    tp.put (it, ostrm, charT (' '), &val, wpat, wpatend);
+
+    // working around dumb compilers such as MSVC 6.0 that
+    // do not zero initialize POD structs when using tm()
+    static std::tm zero_tm;
+    std::tm x = zero_tm;
+
+    std::basic_istringstream<charT> istrm (ostrm.str ());
+
+    istrm.flags (std::ios_base::fmtflags (flags));
+
+    std::ios_base::iostate err = std::ios_base::goodbit;
+
+    const char *fname = 0;
+
+    InIter ibeg = InIter (istrm);
+    InIter iend;
+
+    _TRY {
+        if (   '\0' == fmt [1]
+            || ('E' ==  fmt [0] || 'O' == fmt [0] && '\0' == fmt [2])) {
+
+            // single-character format strings "a", "b", "x", "X", and "Y"
+            // exercise the standard time_get interface, i.e., get_weekday(),
+            // get_monthname(), and get_year()
+
+            // other single or two character format strings, e.g., "Ec" or "Ex"
+            // exercise the single character extension (format specifier and
+            // an optional modifier)
+
+            switch (*fmt) {
+            case 'a':
+                fname = "get_weekday";
+                iend  = tg.get_weekday (ibeg, iend, istrm, err, &x);
+                break;
+
+            case 'b':
+                fname = "get_monthname";
+                iend  = tg.get_monthname (ibeg, iend, istrm, err, &x);
+                break;
+
+            case 'x':
+                fname = "get_date";
+                iend  = tg.get_date (ibeg, iend, istrm, err, &x);
+                break;
+
+            case 'X':
+                fname = "get_time";
+                iend  = tg.get_time (ibeg, iend, istrm, err, &x);
+                break;
+
+            case 'Y':
+                fname = "get_year";
+                iend  = tg.get_year (ibeg, iend, istrm, err, &x);
+                break;
+
+            default:
+                fname = "get";
+                if ('E' == fmt [0] || 'O' == fmt [0])
+                    iend = tg.get (ibeg, iend, istrm, err, &x,
+                                   fmt [1], fmt [0]);
+                else
+                    iend = tg.get (ibeg, iend, istrm, err, &x, *fmt);
+                break;
+            }
+        }
+        else {
+            // multi-character format strings exercise the pattern
+            // extensions to time_get, ala strptime()
+
+            charT fmtstr [256];
+            charT *end;
+
+            const char *pfmt = fmt;
+            for (end = fmtstr; *pfmt; *end++ = *pfmt++);
+
+            fname = "get";
+            iend  = tg.get (ibeg, iend, istrm, err, &x, fmtstr, end);
+        }
+    }
+    _CATCH (...) {
+        rw_error (0, 0, lineno,
+                  "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") "
+                  "unexpectedly threw an exception",
+                  __LINE__, cname, fname,
+                  int (sizeof (charT)), ostrm.str ().data (), fmt);
+
+        return;
+    }
+
+    int extracted = -1 == consumed ? -1
+        : int (istrm.rdbuf ()->pubseekoff (0, std::ios::cur, std::ios::in));
+
+    if (extracted == -1)
+        consumed = -1;
+
+    int success =
+        extracted == consumed && (-1 == err_expect || err == err_expect);
+
+    rw_assert (success, __FILE__, lineno,
+               "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") "
+               "ate %d, expected %d, rdstate() == %{Is}, got %{Is}",
+               __LINE__, cname, fname,
+               int (sizeof (charT)), ostrm.str ().data (), fmt,
+               extracted, consumed, err_expect, err);
+
+    success = 0 == std::memcmp (&x, &val, sizeof x);
+
+    rw_assert (success, __FILE__, lineno,
+               "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") got %{t}, "
+               "expected %{t}, flags = %{If}, locale (%s)",
+               __LINE__, cname, fname,
+               int (sizeof (charT)), ostrm.str ().data (), fmt, &x,
+               &val, flags, std::locale ().name ().data ());
+}
+
+
+/**************************************************************************/
+
+std::tm mktm (int sec = 0, int min = 0, int hour = 0,
+              int mday = 0, int mon = 0, int year = 0,
+              int wday = 0, int yday = 0, int isdst = 0)
+{
+    std::tm tmp = std::tm ();
+
+    if (sec < 0) {
+        // get the current local time
+        std::time_t t = std::time (0);
+        std::tm *ptm = std::localtime (&t);
+        return ptm ? *ptm : tmp;
+    }
+
+    // use arguments to initialize struct
+    tmp.tm_sec   = sec;     // seconds after the minute [0, 60]
+    tmp.tm_min   = min;     // minutes after the hour   [0, 59]
+    tmp.tm_hour  = hour;    // hours since midnight     [0, 23]
+    tmp.tm_mday  = mday;    // day of the month         [1, 31]
+    tmp.tm_mon   = mon;     // months since January     [0, 11]
+    tmp.tm_year  = year;    // years since 1900
+    tmp.tm_wday  = wday;    // days since Sunday        [0, 6]
+    tmp.tm_yday  = yday;    // days since January 1     [0, 365]
+    tmp.tm_isdst = isdst;   // Daylight Saving Time flag
+
+    return tmp;
+}
+
+
+// for convenience
+#define Boolalpha   std::ios_base::boolalpha
+#define Dec         std::ios_base::dec
+#define Fixed       std::ios_base::fixed
+#define Hex         std::ios_base::hex
+#define Internal    std::ios_base::internal
+#define Left        std::ios_base::left
+#define Oct         std::ios_base::oct
+#define Right       std::ios_base::right
+#define Scientific  std::ios_base::scientific
+#define Showbase    std::ios_base::showbase
+#define Showpoint   std::ios_base::showpoint
+#define Showpos     std::ios_base::showpos
+#define Skipws      std::ios_base::skipws
+#define Unitbuf     std::ios_base::unitbuf
+#define Uppercase   std::ios_base::uppercase
+#define Bin         std::ios_base::bin
+#define Adjustfield std::ios_base::adjustfield
+#define Basefield   std::ios_base::basefield
+#define Floatfield  std::ios_base::floatfield
+#define Nolock      std::ios_base::nolock
+#define Nolockbuf   std::ios_base::nolockbuf
+
+// capitalize to prevent EDG eccp from expanding the macros
+// in .cc files when implicit inclusion is used (causes errors
+// in constructs such as traits_type::eof ())
+#define Bad         std::ios_base::badbit
+#define Eof         std::ios_base::eofbit
+#define Fail        std::ios_base::failbit
+#define Good        std::ios_base::goodbit
+
+
+#define T __LINE__, charT (), cname, mktm
+#define TEST do_test
+
+#define FUNCTION(fun)                                           \
+    rw_info (0, 0, __LINE__,                                    \
+             "std::time_get<%s>::%s() in locale (\"%s\")",      \
+             cname, fun, std::locale ().name ().c_str ())
+
+#define STEP(desc)   rw_info (0, 0, __LINE__, "%s", desc)
+
+
+template <class charT>
+void test_posix (charT, const char *cname)
+{
+    // set the global locale object
+    std::locale::global (std::locale ("C"));
+
+    // exercise abbreviated weekday names (time_get::get_weekday())
+    FUNCTION ("get_weekday");
+
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", -1, "a", 0, Eof);
+
+    // comparison is case insensitive
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "SUN", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "sun", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "a", 0, Eof);
+
+    // abbreviation followed by a letter other than the one
+    // that follows in a full name is acepted
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "suna", 3, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "monb", 3, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "tuec", 3, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "wedd", 3, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "thue", 3, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "frif", 3, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "satg", 3, "a", 0, Good);
+
+    // exercise failure on invalid input including incomplete
+    // full names (other than valid cases exercised above)
+    TEST (T (0, 0, 0, 0, 0, 0, 0), " Sun",      0, "a", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Mond",      4, "a", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Tuesd",     5, "a", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Wednesd",   7, "a", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Thursda.",  7, "a", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Fridax",    5, "a", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "6Saturday", 0, "a", 0, Fail);
+
+    // exercise full weekday names
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "%A", -1, "a", 0, -1);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "%A", -1, "a", 0, -1);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "%A", -1, "a", 0, -1);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "%A", -1, "a", 0, -1);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "%A", -1, "a", 0, -1);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "%A", -1, "a", 0, -1);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "%A", -1, "a", 0, -1);
+
+    // comparison is case insensitive
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "SUNDAY",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "sunday",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday",   7, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday",  8, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday",  8, "a", 0, Good);
+
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday ",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday 0",   6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesdayy",   7, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday.", 9, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday,",  8, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday/",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday:",  8, "a", 0, Good);
+
+    // exercise abbreviated month names (time_get::get_monthname())
+    FUNCTION ("get_monthname");
+    TEST (T (0, 0, 0, 0,  0), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  1), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  2), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  3), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  4), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  5), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  6), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  7), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  8), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  9), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 10), "%b", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 11), "%b", -1, "b", 0, -1);
+
+    TEST (T (0, 0, 0, 0,  0), "Jan", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  1), "Feb", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  2), "Mar", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  3), "Apr", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  4), "May", 3, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  5), "Jun", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  6), "Jul", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  7), "Aug", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  8), "Sep", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0,  9), "Oct", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0, 10), "Nov", 3, "b", 0, Eof);
+    TEST (T (0, 0, 0, 0, 11), "Dec", 3, "b", 0, Eof);
+
+    // exercise invalid abbreviated month names
+    TEST (T (0, 0, 0, 0,  0), "J",   1, "b", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0,  0), "J ",  1, "b", 0, Fail);
+    TEST (T (0, 0, 0, 0,  0), "Ja",  2, "b", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0,  0), "Ju",  2, "b", 0, Eof | Fail);
+
+    // exercise full month names
+    TEST (T (0, 0, 0, 0,  0), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  1), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  2), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  3), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  4), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  5), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  6), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  7), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  8), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  9), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
+
+    TEST (T (0, 0, 0, 0,  0), "January",   7, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  0), "January ",  7, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  1), "February",  8, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  2), "March",     5, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  2), "Marchh",    5, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  3), "April",     5, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  4), "May",       3, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  5), "June",      4, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  6), "July",      4, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  6), "Jull",      3, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  7), "August",    6, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  8), "September", 9, "b", 0, Good);
+    TEST (T (0, 0, 0, 0,  9), "October",   7, "b", 0, Good);
+    TEST (T (0, 0, 0, 0, 10), "November",  8, "b", 0, Good);
+    TEST (T (0, 0, 0, 0, 11), "December",  8, "b", 0, Good);
+
+    // exercise invalid full month names
+    TEST (T (0, 0, 0, 0, 0), "Januar",    6, "b", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0, 0), "Februar",   7, "b", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0, 0), " March",    0, "b", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0), "apri/",     4, "b", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0), "/MAY",      0, "b", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0), ":Jun",      0, "b", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0), "Ju ",       2, "b", 0, Fail);
+
+    // exercise date (time_get::get_date())
+    FUNCTION ("get_date");
+    TEST (T (0, 0, 0,  1, 0, 100), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  2, 1, 111), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  3, 2, 122), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  4, 3, 133), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  5, 4, 144), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  6, 5, 155), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  7, 6, 166), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  8, 7, 168), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0,  9, 8,  69), "%x", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0, 10, 9,  99), "%x", 8, "x", 0, Eof);
+
+    TEST (T (0, 0, 0, 11,  5, 155), "06/11/55", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0, 12,  6, 167), "07/12/67", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0, 23,  7,  78), "08/23/78", 8, "x", 0, Eof);
+    TEST (T (0, 0, 0, 31, 11,  89), "12/31/89", 8, "x", 0, Eof);
+
+    // exercise time (time_get::get_time())
+    FUNCTION ("get_time");
+    TEST (T ( 0,  0,  0), "%X", 8, "X", 0, Eof);
+    TEST (T ( 1, 59, 11), "%X", 8, "X", 0, Eof);
+    TEST (T (12, 48, 10), "%X", 8, "X", 0, Eof);
+    TEST (T (23, 37,  9), "%X", 8, "X", 0, Eof);
+    TEST (T (34, 26,  8), "%X", 8, "X", 0, Eof);
+    TEST (T (45, 15,  7), "%X", 8, "X", 0, Eof);
+    TEST (T (56,  4,  6), "%X", 8, "X", 0, Eof);
+
+    TEST (T ( 0,  0,  0), "00:00:00", 8, "X", 0, Eof);
+    TEST (T (60,  9, 23), "23:09:60", 8, "X", 0, Eof);
+    TEST (T (59, 18, 22), "22:18:59", 8, "X", 0, Eof);
+    TEST (T (58, 27, 21), "21:27:58", 8, "X", 0, Eof);
+    TEST (T (57, 36, 20), "20:36:57", 8, "X", 0, Eof);
+    TEST (T (56, 45, 19), "19:45:56", 8, "X", 0, Eof);
+    TEST (T (55, 54, 18), "18:54:55", 8, "X", 0, Eof);
+
+    // exercise year (time_get::get_year())
+    FUNCTION ("get_year");
+    TEST (T (0, 0, 0, 0, 0, -1900),     "0", 1, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1900),    "00", 2, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1899),   "001", 3, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,  -124),  "1776", 4, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,     0),  "1900", 4, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,     1),  "1901", 4, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,    99),  "1999", 4, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   102),  "2002", 4, "Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 98099), "99999", 5, "Y", 0, Eof);
+
+    FUNCTION ("get");
+
+    // exercise extensions implementing complete IEEE Std 1003.1-2001 support
+    // http://www.opengroup.org/onlinepubs/007904975/functions/strptime.html
+
+    // capital format specifier (other than "X") implies the
+    // testing of std::time_get<>::get (..., char, char)
+
+    // %a The day of the week, using the locale's weekday names;
+    //    either the abbreviated or full name may be specified.
+    // %A Equivalent to %a.
+    STEP ("%a, %A: the day of the week");
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "A", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "A", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "A", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "A", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "A", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "A", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "A", 0, Eof);
+
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday",    6, "A", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday",    6, "A", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday",   7, "A", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "A", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday",  8, "A", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday",    6, "A", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday",  8, "A", 0, Good);
+
+    // %b The month, using the locale's month names;
+    //    either the abbreviated or full name may be specified.
+    // %B Equivalent to %b.
+    STEP ("%b, %B: the month");
+    TEST (T (0, 0, 0, 0,  0), "January",   7, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  1), "February",  8, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  2), "March",     5, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  3), "April",     5, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  4), "May",       3, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  5), "June",      4, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  6), "July",      4, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  7), "August",    6, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  8), "September", 9, "B", 0, Good);
+    TEST (T (0, 0, 0, 0,  9), "October",   7, "B", 0, Good);
+    TEST (T (0, 0, 0, 0, 10), "November",  8, "B", 0, Good);
+    TEST (T (0, 0, 0, 0, 11), "December",  8, "B", 0, Good);
+
+    // %c Replaced by the locale's appropriate date and time representation.
+    STEP ("%c: date and time representation");
+    rw_warn (0, 0, __LINE__, "%%c not being exercised");
+
+
+    // %C: The century number [00,99]; leading zeros are permitted
+    //     but not required.
+    STEP ("%C: the century number");
+    TEST (T (0, 0, 0, 0, 0, -1900),   "0", 1, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1800),   "1", 1, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1700),   "2", 1, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1600),   "3", 1, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1500),  "04", 2, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,     0),  "19", 2, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   100),  "20", 2, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   200),  "21", 2, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,  1300),  "32", 2, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,  8000),  "99", 2, "C", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,     0), "100", 3, "C", 0, Eof | Fail);
+
+    // %d The day of the month [01,31]; leading zeros are permitted but not
+    //    required.
+    STEP ("%d: day of the month");
+    TEST (T (0, 0, 0,  1),    "1", 1, "d", 0, Eof);
+    TEST (T (0, 0, 0,  2),   "02", 2, "d", 0, Eof);
+    TEST (T (0, 0, 0, 28),   "28", 2, "d", 0, Eof);
+    TEST (T (0, 0, 0, 29),   "29", 2, "d", 0, Eof);
+    TEST (T (0, 0, 0, 30),  "030", 3, "d", 0, Eof);
+    TEST (T (0, 0, 0, 31), "0031", 4, "d", 0, Eof);
+    TEST (T (0, 0, 0,  0),    "0", 1, "d", 0, Eof | Fail);
+    // leading whitespace not allowed
+    TEST (T (0, 0, 0,  0),   " 3", 0, "d", 0, Fail);
+    TEST (T (0, 0, 0,  0),   "32", 2, "d", 0, Eof | Fail);
+
+    // %D The date as %m/%d/%y.
+    STEP ("%D: the date as %m/%d/%y");
+    TEST (T (0, 0, 0, 14, 3, 102),      "4/14/2",  6, "D", 0, Eof);
+    TEST (T (0, 0, 0, 14, 3, 102),    "04/14/02",  8, "D", 0, Eof);
+    TEST (T (0, 0, 0, 14, 3, 102),   "04/14/002",  9, "D", 0, Eof);
+    TEST (T (0, 0, 0,  0, 0,   0),    "0/1/2002",  1, "D", 0, Fail);
+    TEST (T (0, 0, 0,  0, 0,   0),    "4/0/2002",  3, "D", 0, Fail);
+    TEST (T (0, 0, 0,  0, 0,   0),   "4/32/2002",  4, "D", 0, Fail);
+
+    // %e Equivalent to %d; leading zeros are permitted but not required.
+    STEP ("%e: equivalent to %d");
+    TEST (T (0, 0, 0,  1),  "01", 2, "e", 0, Eof);
+    TEST (T (0, 0, 0,  9),   "9", 1, "e", 0, Eof);
+    TEST (T (0, 0, 0, 31),  "31", 2, "e", 0, Eof);
+    TEST (T (0, 0, 0,  0),   "0", 1, "e", 0, Eof | Fail);
+    // leading whitespace not allowed
+    TEST (T (0, 0, 0,  0),  " 2", 0, "e", 0, Fail);
+    TEST (T (0, 0, 0,  0),  "99", 2, "e", 0, Eof | Fail);
+
+    // %h Equivalent to %b.
+    STEP ("%h: equivalent to %b");
+    TEST (T (0, 0, 0, 0,  0), "Jan",      3, "h", 0, Eof);
+    TEST (T (0, 0, 0, 0,  1), "February", 8, "h", 0, Good);
+    TEST (T (0, 0, 0, 0,  2), "Mar",      3, "h", 0, Eof);
+    TEST (T (0, 0, 0, 0,  3), "April",    5, "h", 0, Good);
+    TEST (T (0, 0, 0, 0,  4), "May",      3, "h", 0, Good);
+    TEST (T (0, 0, 0, 0,  5), "June",     4, "h", 0, Good);
+    TEST (T (0, 0, 0, 0,  6), "Jul",      3, "h", 0, Eof);
+    TEST (T (0, 0, 0, 0,  7), "August",   6, "h", 0, Good);
+    TEST (T (0, 0, 0, 0,  8), "Sep",      3, "h", 0, Eof);
+    TEST (T (0, 0, 0, 0,  9), "October",  7, "h", 0, Good);
+    TEST (T (0, 0, 0, 0, 10), "Nov",      3, "h", 0, Eof);
+    TEST (T (0, 0, 0, 0, 11), "December", 8, "h", 0, Good);
+
+    // %H The hour (24-hour clock) [00,23]; leading zeros are permitted
+    //    but not required.
+    STEP ("%H: the hour (24-hour clock)");
+    TEST (T (0, 0,  0),   "0", 1, "H", 0, Eof);
+    TEST (T (0, 0,  0),  "00", 2, "H", 0, Eof);
+    TEST (T (0, 0,  0), "000", 3, "H", 0, Eof);
+    TEST (T (0, 0,  1),   "1", 1, "H", 0, Eof);
+    TEST (T (0, 0,  2),   "2", 1, "H", 0, Eof);
+    TEST (T (0, 0,  3),   "3", 1, "H", 0, Eof);
+    TEST (T (0, 0, 11),  "11", 2, "H", 0, Eof);
+    TEST (T (0, 0, 12),  "12", 2, "H", 0, Eof);
+    TEST (T (0, 0, 13),  "13", 2, "H", 0, Eof);
+    TEST (T (0, 0, 23),  "23", 2, "H", 0, Eof);
+    TEST (T (0, 0, 23), "023", 3, "H", 0, Eof);
+    TEST (T (0, 0,  0), "024", 3, "H", 0, Eof | Fail);
+    TEST (T (0, 0,  0), "987", 3, "H", 0, Eof | Fail);
+
+    // %I The hour (12-hour clock) [01,12]; leading zeros are permitted
+    //    but not required.
+    STEP ("%I: the hour (12-hour clock)");
+    TEST (T (0, 0,  0),   "1", 1, "I", 0, Eof);
+    TEST (T (0, 0,  1),   "2", 1, "I", 0, Eof);
+    TEST (T (0, 0,  2),   "3", 1, "I", 0, Eof);
+    TEST (T (0, 0,  3),   "4", 1, "I", 0, Eof);
+    TEST (T (0, 0,  4),   "5", 1, "I", 0, Eof);
+    TEST (T (0, 0,  5),   "6", 1, "I", 0, Eof);
+    TEST (T (0, 0,  6),   "7", 1, "I", 0, Eof);
+    TEST (T (0, 0,  7),   "8", 1, "I", 0, Eof);
+    TEST (T (0, 0,  8),   "9", 1, "I", 0, Eof);
+    TEST (T (0, 0,  9),  "10", 2, "I", 0, Eof);
+    TEST (T (0, 0, 10),  "11", 2, "I", 0, Eof);
+    TEST (T (0, 0, 11),  "12", 2, "I", 0, Eof);
+    TEST (T (0, 0,  0),  "13", 2, "I", 0, Eof | Fail);
+    TEST (T (0, 0,  0), "013", 3, "I", 0, Eof | Fail);
+    TEST (T (0, 0,  0), "123", 3, "I", 0, Eof | Fail);
+    TEST (T (0, 0,  0),   "0", 1, "I", 0, Eof | Fail);
+
+    // %j The day number of the year [001,366]; leading zeros are permitted
+    //    but not required.
+    TEST (T (0, 0, 0, 0, 0, 0, 0,   0),   "1", 1, "j", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0,   1),   "2", 1, "j", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0,   2),  "03", 2, "j", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0,   9),  "10", 2, "j", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0, 364), "365", 3, "j", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0, 365), "366", 3, "j", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0,   0),   "0", 1, "j", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0,   0), "367", 3, "j", 0, Eof | Fail);
+
+#ifdef __GLIBC__
+
+    STEP ("%k: equivalent to %H (GNU glibc extension)");
+    
+    TEST (T (0, 0,  0),   "0", 1, "k", 0, Eof);
+    TEST (T (0, 0,  1),   "1", 1, "k", 0, Eof);
+    TEST (T (0, 0,  9),   "9", 1, "k", 0, Eof);
+    TEST (T (0, 0, 10),  "10", 2, "k", 0, Eof);
+    TEST (T (0, 0, 11),  "11", 2, "k", 0, Eof);
+    TEST (T (0, 0, 12),  "12", 2, "k", 0, Eof);
+    TEST (T (0, 0, 13),  "13", 2, "k", 0, Eof);
+    TEST (T (0, 0, 23),  "23", 2, "k", 0, Eof);
+    TEST (T (0, 0, 23), "023", 3, "k", 0, Eof);
+    TEST (T (0, 0,  0), "024", 3, "k", 0, Eof | Fail);
+    TEST (T (0, 0,  0), "987", 3, "k", 0, Eof | Fail);
+
+#endif   // __GLIBC__
+
+    // %m The month number [01,12]; leading zeros are permitted
+    //    but not required.
+    STEP ("%m: the month number");
+    TEST (T (0, 0, 0, 0,  0, 0),  "1", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  1, 0),  "2", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  2, 0),  "3", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  3, 0),  "4", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  4, 0),  "5", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  5, 0),  "6", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  6, 0),  "7", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  7, 0),  "8", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  8, 0),  "9", 1, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  9, 0), "10", 2, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0, 10, 0), "11", 2, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0, 11, 0), "12", 2, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  0, 0), "01", 2, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  1, 0), "02", 2, "m", 0, Eof);
+    TEST (T (0, 0, 0, 0,  0, 0),  "0", 1, "m", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0,  0, 0), "13", 2, "m", 0, Eof | Fail);
+
+    // %M The minute [00,59]; leading zeros are permitted but not required.
+    STEP ("%M: the minute");
+    TEST (T (0,  0),   "0", 1, "M", 0, Eof);
+    TEST (T (0,  0),  "00", 2, "M", 0, Eof);
+    TEST (T (0,  0), "000", 3, "M", 0, Eof);
+    TEST (T (0,  1),   "1", 1, "M", 0, Eof);
+    TEST (T (0,  2),   "2", 1, "M", 0, Eof);
+    TEST (T (0, 19),  "19", 2, "M", 0, Eof);
+    TEST (T (0, 29),  "29", 2, "M", 0, Eof);
+    TEST (T (0, 59),  "59", 2, "M", 0, Eof);
+    TEST (T (0,  0),  "60", 2, "M", 0, Eof | Fail);
+
+    // %n Any white space.
+    STEP ("%n: any whitespace");
+    TEST (T (),     "", 0, "n", 0, Eof);
+    TEST (T (),    " ", 1, "n", 0, Eof);
+    TEST (T (),   "  ", 2, "n", 0, Eof);
+    TEST (T (),  "   ", 3, "n", 0, Eof);
+    TEST (T (),  "\n ", 2, "n", 0, Eof);
+    TEST (T (),  " \t", 2, "n", 0, Eof);
+    TEST (T (), "\n\t", 2, "n", 0, Eof);
+    TEST (T (),    ".", 0, "n", 0, Good);
+    TEST (T (),   " 1", 1, "n", 0, Good);
+    TEST (T (), "\t 2", 2, "n", 0, Good);
+
+    // %p The locale's equivalent of a.m or p.m.
+    STEP ("%p: the equivalent of AM/PM");
+    TEST (T (0, 0,  1), "AM", 2, "p", 0, Good);
+    TEST (T (0, 0, 13), "PM", 2, "p", 0, Good);
+    TEST (T (0, 0,  0),  "",  0, "p", 0, Eof | Fail);
+    TEST (T (0, 0,  0),  "A", 1, "p", 0, Eof | Fail);
+    TEST (T (0, 0,  0),  "P", 1, "p", 0, Eof | Fail);
+    TEST (T (0, 0,  0),  "M", 0, "p", 0, Fail);
+    TEST (T (0, 0,  0), "A ", 1, "p", 0, Fail);
+    TEST (T (0, 0,  0), "P ", 1, "p", 0, Fail);
+
+    // %r 12-hour clock time using the AM/PM notation if t_fmt_ampm is
+    //    not an empty string in the LC_TIME portion of the current locale;
+    //    in the POSIX locale, this shall be equivalent to %I:%M:%S %p.
+    STEP ("%r: 12-hour clock time using the AM/PM notation");
+    rw_warn (0, 0, __LINE__, "%%r not being exercised");
+
+
+    // %R The time as %H:%M.
+    STEP ("%R: the time as %H:%M");
+    TEST (T (0,  0,  0),      "0:0", 3, "R", 0, Eof);
+    TEST (T (0,  1,  0),      "0:1", 3, "R", 0, Eof);
+    TEST (T (0,  2,  0),     "0:02", 4, "R", 0, Eof);
+    TEST (T (0, 59,  0),     "0:59", 4, "R", 0, Eof);
+    TEST (T (0, 48,  1),     "1:48", 4, "R", 0, Eof);
+    TEST (T (0, 37, 11),    "11:37", 5, "R", 0, Eof);
+    TEST (T (0, 26, 19),    "19:26", 5, "R", 0, Eof);
+    TEST (T (0, 15, 22),    "22:15", 5, "R", 0, Eof);
+    TEST (T (0,  4, 23),    "23:04", 5, "R", 0, Eof);
+    TEST (T (0,  3, 23), "23:03:00", 5, "R", 0, Good);
+    TEST (T (0,  2, 23),  "23:2:01", 4, "R", 0, Good);
+    TEST (T (0,  0,  0),    "23:60", 5, "R", 0, Eof | Fail);
+    TEST (T (0,  0,  0),    "24:00", 2, "R", 0, Fail);
+
+    // %S The seconds [00,60]; leading zeros are permitted but not required.
+    STEP ("%S: the seconds");
+    TEST (T ( 0),   "0", 1, "S", 0, Eof);
+    TEST (T ( 1),  "01", 2, "S", 0, Eof);
+    TEST (T ( 2), "002", 3, "S", 0, Eof);
+    TEST (T (13),  "13", 2, "S", 0, Eof);
+    TEST (T (24),  "24", 2, "S", 0, Eof);
+    TEST (T (34),  "34", 2, "S", 0, Eof);
+    TEST (T (45),  "45", 2, "S", 0, Eof);
+    TEST (T (56),  "56", 2, "S", 0, Eof);
+    TEST (T (60),  "60", 2, "S", 0, Eof);
+    TEST (T ( 0),  "61", 2, "S", 0, Eof | Fail);
+
+    // %t Any white space.
+    STEP ("%t: any whitespace");
+    TEST (T (),   "\t", 1, "t", 0, Eof);
+    TEST (T (),    " ", 1, "t", 0, Eof);
+    TEST (T (),   "  ", 2, "t", 0, Eof);
+    TEST (T (),  "\n ", 2, "t", 0, Eof);
+    
+    // %T The time as %H:%M:%S.
+    STEP ("%T: the time as %H:%M:%S");
+    TEST (T ( 0,  0,  0),    "0:0:00", 6, "T", 0, Eof);
+    TEST (T ( 1,  1,  0),     "0:1:1", 5, "T", 0, Eof);
+    TEST (T ( 2,  2,  0),    "0:02:2", 6, "T", 0, Eof);
+    TEST (T ( 3, 59,  0),    "0:59:3", 6, "T", 0, Eof);
+    TEST (T ( 4, 48,  1),   "1:48:04", 7, "T", 0, Eof);
+    TEST (T ( 5, 37, 11),   "11:37:5", 7, "T", 0, Eof);
+    TEST (T ( 6, 26, 19), "19:26:006", 9, "T", 0, Eof);
+    TEST (T ( 7, 15, 22),  "22:015:7", 8, "T", 0, Eof);
+    TEST (T ( 8,  4, 23), "023:004:8", 9, "T", 0, Eof);
+    TEST (T (60, 59, 23), "023:59:60", 9, "T", 0, Eof);
+    TEST (T ( 0,  0,  0),  "23:59:61", 8, "T", 0, Eof | Fail);
+    TEST (T ( 0,  0,  0),    "0:0:62", 6, "T", 0, Eof | Fail);
+    TEST (T ( 0,  0,  0),       "0:0", 3, "T", 0, Eof | Fail);
+    TEST (T ( 0,  0,  0),       "999", 3, "T", 0, Eof | Fail);
+
+    // %U The week number of the year (Sunday as the first day of the week)
+    //    as a decimal number [00,53]; leading zeros are permitted but not
+    //    required.
+    STEP ("%U: the Sunday-based week of the year");
+    TEST (T (0, 0, 0, 0, 0, 320, 2, 60), "9", 1, "U", 0, Eof);
+
+    // %w The weekday as a decimal number [0,6], with 0 representing
+    //    Sunday; leading zeros are permitted but not required.
+    STEP ("%w: the Sunday-based weekday as a decimal number");
+    TEST (T (0, 0, 0, 0, 0, 0, 0),  "0", 1, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "00", 2, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1),  "1", 1, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "01", 2, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2),  "2", 1, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3),  "3", 1, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4),  "4", 1, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5),  "5", 1, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 6),  "6", 1, "w", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 0),  "7", 1, "w", 0, Eof | Fail);
+
+    // %W The week number of the year (Monday as the first day of the
+    //    week) as a decimal number [00,53]; leading zeros are permitted
+    //    but not required.
+    STEP ("%W: the Monday-based week of the year");
+    TEST (T (0, 0, 0, 0, 0, 0, 0),  "0", 1, "W", 0, Eof);
+
+    // rw_warn (0, 0, __LINE__, "%%W specifier not being exercised");
+
+    // %x The date, using the locale's date format.
+    STEP ("%x: the date");
+    TEST (T (0, 0, 0, 25, 6, 67), "7/25/1967", 9, "%x", 0, Eof);
+
+    // %X The time, using the locale's time format.
+    STEP ("%X: the time");
+    TEST (T (12, 34, 5),  "5:34:12", 7,  "%X", 0, Eof);
+    TEST (T (23, 45, 6), " 6:45:23", 8, " %X", 0, Eof);
+
+    // %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.)
+    STEP ("%y: the year within century");
+    TEST (T (0, 0, 0, 0, 0,   100),    "0", 1, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   100),   "00", 2, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   101),    "1", 1, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   102),    "2", 1, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   103),   "03", 2, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   168),   "68", 2, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,    69),   "69", 2, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,    99),   "99", 2, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1800),  "100", 3, "%y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,   102), "2002", 4, "%y", 0, Eof);
+
+    // %Y The year, including the century (for example, 1988).
+    STEP ("%Y: the year, including the century");
+    TEST (T (0, 0, 0, 0, 0, -1900),      "0", 1, "%Y",  0, Eof);
+    TEST (T (0, 0, 0, 0, 0, -1900),     " 0", 2, " %Y", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0,    99), "\t1999", 5, " %Y", 0, Eof);
+
+    STEP ("invalid pattern");
+    TEST (T (0), "0", 0, "E", 0, Fail);
+    TEST (T (0), "0", 0, "i", 0, Fail);
+    TEST (T (0), "0", 0, "J", 0, Fail);
+    TEST (T (0), "0", 0, "N", 0, Fail);
+    TEST (T (0), "0", 0, "P", 0, Fail);
+    TEST (T (0), "0", 0, "s", 0, Fail);
+    TEST (T (0), "0", 0, "u", 0, Fail);
+    TEST (T (0), "0", 0, "z", 0, Fail);
+    TEST (T (0), "0", 0, "Z", 0, Fail);
+
+
+    // %Ec The locale's alternative date and time representation. 
+    // %EC The name of the base year (period) in the locale's alternative
+    //     representation.
+    // %Ex The locale's alternative date representation.
+    // %EX The locale's alternative time representation.
+    // %Ey The offset from %EC (year only) in the locale's alternative
+    // representation.
+    // %EY The full alternative year representation.
+    // %Od The day of the month using the locale's alternative numeric
+    //     symbols; leading zeros are permitted but not required.
+    // %Oe Equivalent to %Od.
+    // %OH The hour (24-hour clock) using the locale's alternative numeric
+    //     symbols.
+    // %OI The hour (12-hour clock) using the locale's alternative numeric
+    //     symbols.
+    // %Om The month using the locale's alternative numeric symbols.
+    // %OM The minutes using the locale's alternative numeric symbols.
+    // %OS The seconds using the locale's alternative numeric symbols.
+    // %OU The week number of the year (Sunday as the first day of the week)
+    //     using the locale's alternative numeric symbols.
+    // %Ow The number of the weekday (Sunday=0) using the locale's
+    //     alternative numeric symbols.
+    // %OW The week number of the year (Monday as the first day of the
+    //     week) using the locale's alternative numeric symbols.
+    // %Oy The year (offset from %C ) using the locale's alternative numeric
+    // symbols.
+    rw_warn (0, 0, __LINE__, "E modifier not being exercised");
+    rw_warn (0, 0, __LINE__, "O modifier not being exercised");
+
+    // exercise pattern strings containing multiple format specifiers
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun Jan",       7, "%a %b", 0, Eof);
+    TEST (T (0, 0, 0, 0, 1, 0, 1), "Mon  Feb",      8, "%a %b", 0, Eof);
+    TEST (T (0, 0, 0, 0, 2, 0, 2), "Tue%nMar",      7, "%a %b", 0, Eof);
+    TEST (T (0, 0, 0, 0, 3, 0, 3), "Wed%t Apr",     8, "%a %b", 0, Eof);
+    TEST (T (0, 0, 0, 0, 2, 0, 5), "Friday March", 12, "%a %b", 0, Good);
+}
+
+/**************************************************************************/
+
+
+template <class charT>
+void test_english (charT, const char *cname, const char *locname)
+{
+    _TRY {
+        // set the global locale object to the german locale
+        std::locale::global (std::locale (locname));
+    }
+    _CATCH (...) {
+        rw_error (0, 0, __LINE__,
+                  "locale(%#s) unexpectedly threw an exception", locname);
+
+        return;
+    }
+
+    // exercise abbreviated weekday names
+    FUNCTION ("get_weekday");
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "a", 0, Eof);
+
+    // exercise full weekday names
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday",   7, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday",  8, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday",    6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday",  8, "a", 0, Good);
+
+    // exercise full month names
+    FUNCTION ("get_monthname");
+    TEST (T (0, 0, 0, 0,  0), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  1), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  2), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  3), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  4), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  5), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  6), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  7), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  8), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  9), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
+
+    // exercise date (time_get::get_date())
+    FUNCTION ("get_date");
+    TEST (T (0, 0, 0, 1, 0, 100), "%x", 8, "x", 0, Eof);
+
+    // exercise time (time_get::get_time())
+    FUNCTION ("get_time");
+
+    int len;
+
+    {
+        // determine whether "%X" is equivalent to "%I:%M:%S %p"
+        // (e.g., HP-UX or Linux) or to "%I:%M:%S" (e.g., Compaq
+        // Tru64 UNIX)
+        char buf [32];
+        const std::tm tmb = mktm (0, 0, 1);
+        len = std::strftime (buf, sizeof buf, "%X", &tmb);
+    }
+
+    const int hour = 11 == len ? 12 : 0;
+
+    TEST (T ( 0, 0,  0), "%X", len, "X", 0, 11 == len ? Good : Eof);
+    TEST (T ( 0, 0,  1), "%X", len, "X", 0, 11 == len ? Good : Eof);
+    TEST (T ( 0, 0, 11), "%X", len, "X", 0, 11 == len ? Good : Eof);
+    TEST (T ( 0, 0, 12), "%X", len, "X", 0, 11 == len ? Good : Eof);
+    TEST (T ( 0, 0, 13), "%X", len, "X", 0, 11 == len ? Good : Eof);
+    TEST (T ( 0, 0, 23), "%X", len, "X", 0, 11 == len ? Good : Eof);
+
+    TEST (T ( 0, 0, 12 - hour), "12:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         1), "01:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         2), "02:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         3), "03:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         4), "04:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         5), "05:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         6), "06:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         7), "07:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         8), "08:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,         9), "09:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,        10), "10:00:00 AM", len, "X", 0, Good);
+    TEST (T ( 0, 0,        11), "11:00:00 AM", len, "X", 0, Good);
+
+    TEST (T ( 0, 0,        12), "12:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  1), "01:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  2), "02:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  3), "03:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  4), "04:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  5), "05:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  6), "06:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  7), "07:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  8), "08:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour +  9), "09:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour + 10), "10:00:00 PM", len, "X", 0, Good);
+    TEST (T ( 0, 0, hour + 11), "11:00:00 PM", len, "X", 0, Good);
+
+    TEST (T (60, 9, hour + 11), "11:09:60 PM", len, "X", 0, Good);
+}
+
+/**************************************************************************/
+
+
+template <class charT>
+void test_german (charT, const char *cname, const char *locname)
+{
+    _TRY {
+        // set the global locale object to the german locale
+        std::locale::global (std::locale (locname));
+    }
+    _CATCH (...) {
+        rw_error (0, 0, __LINE__,
+                  "locale(%#s) unexpectedly threw an exception", locname);
+
+        return;
+    }
+
+    // exercise abbreviated weekday names
+    // these may be { So, Mo, Di, Mi, Do, Sa } (e.g., Compaq Tru64 UNIX)
+    // or { Son, Mon, Die, Mit, Don, Sam } (e.g., Linux, SunOS, or Win32)
+    FUNCTION ("get_weekday");
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", -1, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", -1, "a", 0, Eof);
+
+    // exercise full weekday names
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "Sonntag",     7, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "Montag",      6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "Dienstag",    8, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "Mittwoch",    8, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "Donnerstag", 10, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "Freitag",     7, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "Samstag",     7, "a", 0, Good);
+
+    // exercise full month names
+    FUNCTION ("get_monthname");
+    TEST (T (0, 0, 0, 0,  0), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  1), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  2), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  3), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  4), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  5), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  6), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  7), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  8), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  9), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
+}
+
+/**************************************************************************/
+
+
+template <class charT>
+void test_danish (charT, const char *cname, const char *locname)
+{
+    _TRY {
+        // set the global locale object to the german locale
+        std::locale::global (std::locale (locname));
+    }
+    _CATCH (...) {
+        rw_error (0, 0, __LINE__,
+                  "locale(%#s) unexpectedly threw an exception", locname);
+
+        return;
+    }
+
+    // exercise abbreviated weekday names
+    FUNCTION ("get_weekday");
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", 3, "a", 0, Eof);
+
+    // avoid using <s><o/><n> or <s><o/><n><d><a><g> since it
+    // contains the non-ASCII character <o/> (o with a slash)
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "man", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "tir", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "ons", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "tor", 3, "a", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "fre", 3, "a", 0, Eof);
+
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "mandag",   6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "tirsdag",  7, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 3), "onsdag",   6, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 4), "torsdag",  7, "a", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 5), "fredag",   6, "a", 0, Good);
+
+    // exercise full month names
+    FUNCTION ("get_monthname");
+    TEST (T (0, 0, 0, 0,  0), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  1), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  2), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  3), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  4), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  5), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  6), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  7), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  8), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0,  9), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1);
+    TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1);
+}
+
+/**************************************************************************/
+
+
+struct time_data
+{
+    const char*        abday [7];     // %a   abbreviated day name
+    const char*        day [7];       // %A   full day name
+    const char*        abmon [12];    // %b   abbreviated month name
+    const char*        mon [12];      // %B   full month name
+    const char*        am_pm [2];     // %p   AM/PM designator
+    const char*        d_t_fmt;       // %c   date and time
+    const char*        d_fmt;         // %x   date
+    const char*        t_fmt;         // %X   time
+    const char*        t_fmt_ampm;    // %r   time with the AM/PM designaror
+    const char*        era_d_t_fmt;   // %Ec  alternative date and time
+    const char*        era_d_fmt;     // %EX  alternative date
+    const char*        era_t_fmt;     // %Ex  alternative time
+    const char* const* alt_digits;    //      alternative numeric symbols
+
+    struct era_data {
+        int         offset;
+        int         start_day;   // [1..31]
+        int         start_mon;   // [0..11]
+        int         start_year;
+        int         end_day;     // [1..31]
+        int         end_mon;     // [0..11]
+        int         end_year;    // INT_MIN, [0..9999], INT_MAX
+        const char *name;
+        const char *format;
+    };
+
+    const era_data* era;
+};
+
+
+// the root of the locale directory (RWSTD_LOCALE_ROOT)
+// set in main() instead of here to avoid Solaris 7 putenv() bug (PR #30017)
+static const char*
+locale_root;
+
+
+static const char*
+make_LC_TIME (const time_data *td)
+{
+    static char locnamebuf [L_tmpnam + 32];
+
+    if (*locnamebuf)
+        return locnamebuf;
+
+    // create a temporary locale definition file
+    char srcfname [L_tmpnam + 32];
+    std::sprintf (srcfname, "%s" SLASH "LC_TIME.src", locale_root);
+
+    std::FILE *fout = std::fopen (srcfname, "w");
+
+    std::fprintf (fout, "LC_TIME\n");
+
+    unsigned i;
+
+    std::fprintf (fout, "abday ");
+
+    for (i = 0; i != sizeof td->abday / sizeof *td->abday; ++i) {
+        std::fprintf (fout, "\"");
+        pcs_write (fout, td->abday [i]);
+        std::fprintf (fout, "\"%c", i < 6 ? ';' : '\n');
+    }            
+
+    std::fprintf (fout, "day ");
+
+    for (i = 0; i != sizeof td->day / sizeof *td->day; ++i) {
+        std::fprintf (fout, "\"");
+        pcs_write (fout, td->day [i]);
+        std::fprintf (fout, "\"%c", i < 6 ? ';' : '\n');
+    }            
+
+    std::fprintf (fout, "abmon ");
+
+    for (i = 0; i != sizeof td->abmon / sizeof *td->abmon; ++i) {
+        std::fprintf (fout, "\"");
+        pcs_write (fout, td->abmon [i]);
+        std::fprintf (fout, "\"%c", i < 11 ? ';' : '\n');
+    }            
+
+    std::fprintf (fout, "mon ");
+
+    for (i = 0; i != sizeof td->mon / sizeof *td->mon; ++i) {
+        std::fprintf (fout, "\"");
+        pcs_write (fout, td->mon [i]);
+        std::fprintf (fout, "\"%c", i < 11 ? ';' : '\n');
+    }            
+
+    std::fprintf (fout, "am_pm ");
+
+    for (i = 0; i != sizeof td->am_pm / sizeof *td->am_pm; ++i) {
+        std::fprintf (fout, "\"");
+        pcs_write (fout, td->am_pm [i]);
+        std::fprintf (fout, "\"%c", i < 1 ? ';' : '\n');
+    }
+
+    // write out d_t_fmt, d_fmt, t_fmt, etc.
+    // preface each line with a comment giving
+    // the specification in a human-readable format
+    std::fprintf (fout, "\n# d_t_fmt \"%s\"\nd_t_fmt \"",
+                  td->d_t_fmt);
+    pcs_write (fout, td->d_t_fmt);
+
+    std::fprintf (fout, "\"\n\n# d_fmt \"%s\"\nd_fmt \"",
+                  td->d_fmt);
+    pcs_write (fout, td->d_fmt);
+
+    std::fprintf (fout, "\"\n\n# t_fmt \"%s\"\nt_fmt \"",
+                  td->t_fmt);
+    pcs_write (fout, td->t_fmt);
+
+    std::fprintf (fout, "\"\n\n# t_fmt_ampm \"%s\"\nt_fmt_ampm \"",
+                  td->t_fmt_ampm);
+    pcs_write (fout, td->t_fmt_ampm);
+
+    std::fprintf (fout, "\"\n\n# era_d_t_fmt \"%s\"\nera_d_t_fmt \"",
+                  td->era_d_t_fmt);
+    pcs_write (fout, td->era_d_t_fmt);
+
+    std::fprintf (fout, "\"\n\n# era_d_fmt \"%s\"\nera_d_fmt \"",
+                  td->era_d_fmt);
+    pcs_write (fout, td->era_d_fmt);
+
+    std::fprintf (fout, "\"\n\n# era_t_fmt \"%s\"\nera_t_fmt \"",
+                  td->era_t_fmt);
+    pcs_write (fout, td->era_t_fmt);
+
+    std::fprintf (fout, "\"\nalt_digits ");
+
+    for (i = 0; td->alt_digits [i]; ++i) {
+        std::fprintf (fout, "\"");
+        pcs_write (fout, td->alt_digits [i]);
+        std::fprintf (fout, "\"%c", td->alt_digits [i + 1] ? ';' : '\n');
+    }
+
+    std::fprintf (fout, "\n\nera ");
+
+    for (i = 0; INT_MIN != td->era [i].offset; ++i) {
+
+        char segment [256];
+
+        std::sprintf (segment, "%c:%u:%04d/%02d/%02d:",
+                      td->era [i].offset < 0 ? '-' : '+',
+                      td->era [i].offset < 0 ? -td->era [i].offset
+                                             : td->era [i].offset,
+                      td->era [i].start_year + 1900,
+                      td->era [i].start_mon + 1,
+                      td->era [i].start_day);
+
+        const char *end_date = 0;
+
+        if (INT_MIN == td->era [i].end_year)
+            end_date = "-*";   // beginning of time
+        else if (INT_MAX == td->era [i].end_year)
+            end_date = "+*";   // end of time
+
+        if (end_date) {
+            std::sprintf (segment + std::strlen (segment), "%s:%s:%s",
+                          end_date, td->era [i].name, td->era [i].format);
+        }
+        else {
+            std::sprintf (segment + std::strlen (segment),
+                          "%04d/%02d/%02d:%s:%s",
+                          td->era [i].end_year + 1900,
+                          td->era [i].end_mon + 1,
+                          td->era [i].end_day,
+                          td->era [i].name,
+                          td->era [i].format);
+        }
+
+        std::fprintf (fout, "\"");
+        pcs_write (fout, segment);
+        std::fprintf (fout, "\"%c",
+                      INT_MIN == td->era [i + 1].offset ? '\n' : ';');
+    }
+
+    std::fprintf (fout, "\nEND LC_TIME\n");
+
+    std::fclose (fout);
+
+    // create a temporary character map file
+    char cmfname [L_tmpnam + 32];
+    std::sprintf (cmfname, "%s" SLASH "pcs.cm", locale_root);
+
+    fout = std::fopen (cmfname, "w");
+    pcs_write (fout, 0);
+
+    std::fclose (fout);
+
+    // process the locale definition file and the character map
+    const char* const locname =
+        rw_localedef ("-w ", srcfname, cmfname, "test-locale");
+
+    return locname;
+}
+
+
+static const char*
+make_LC_TIME ()
+{
+    const char* const alt_digits[] = {
+        "",      "1st",  "2nd",  "3rd",  "4th",
+         "5th",  "6th",  "7th",  "8th",  "9th",
+        "10th", "11th", "12th", "13th", "14th",
+        "15th", "16th", "17th", "18th", "19th",
+        "20th", "21st", "22nd", "23rd", "24th",
+        "25th", "26th", "27th", "28th", "29th",
+        "30th", "31st", 0   // sentinel
+    };
+
+    const time_data::era_data era[] = {
+        // some entries copied and modified from HP-UX 11.11 ja_JP.utf8
+        //
+        // # 1990-01-02 and onward:    "Heisei%EyNen" (1990 is Heisei 2 Nen.)
+        // # 1990-01-01 to 1990-01-02: "%C"           (no era specified)
+        // # 1989-01-08 to 1989-12-31: "HeiseiGannen"
+        // # 1927-01-01 to 1989-01-07: "Showa%EyNen"  (1927 is Showa 2 Nen.)
+        // # 1927-01-01 and prior:     "foo"
+        // era "+:2:1990/01/02:+*:<U????><U????>:%EC%Ey<U????>";
+        //     "+:1:1989/01/08:1989/12/31:<U????>:%EC<U????><U????>";
+        //     "+:2:1927/01/01:1989/01/07:<U????><U????>:%EC%Ey<U????>";
+        //     "-:7:1926/12/31:-*:foo:bar%EC%Ey"
+
+        //   7|2        |1        | |2   starting year in an era
+        // <<<|>>>>>>>>>|>>>>>>>>>|.|>>> direction in which years increase
+        //    ^         ^         ^ ^
+        //    |         |         | |
+        //    |         |         | +-> Jan 2, 1990 (Heisei %Ey Nen)
+        //    |         |         +-> Dec 31, 1989 (%C)
+        //    |         +-> Jan 7, 1989 (Heisei Gannen)
+        //    +-> Jan 1, 1927 (Showa %Ey Nen)
+        //    +-< Dec 31, 1926 (foobar %Ey)
+
+        {  2,  2,  0, 90,  0,  0, INT_MAX, "Heisei", "%EC %Ey Nen" },
+        {  1,  8,  0, 89, 31, 11,      89, "Heisei", "%EC Gannen" },
+        {  2,  1,  0, 27,  7,  0,      89, "Showa",  "%EC %Ey Nen" },
+        { -7, 31, 11, 26,  0,  0, INT_MIN, "bar",    "foo%EC %Ey" },
+        { INT_MIN /* sentinel entry */, 0, 0, 0, 0, 0, 0, 0, 0 }
+    };
+
+    const time_data td = {
+        // %a
+        { "[Sun]", "[Mon]", "[Tue]", "[Wed]", "[Thu]", "[Fri]", "[Sat]" },
+
+        // %A
+        {
+            "[Sunday]", "[Monday]", "[Tuesday]", "[Wednesday]", "[Thursday]",
+            "[Friday]", "[Saturday]"
+        },
+
+        // %b
+        {
+            "[Jan]", "[Feb]", "[Mar]", "[Apr]", "[May]", "[Jun]",
+            "[Jul]", "[Aug]", "[Sep]", "[Oct]", "[Nov]", "[Dec]",
+        },
+
+        // %B
+        {
+            "[January]", "[February]", "[March]", "[April]", "[May]", "[June]",
+            "[July]", "[August]", "[September]", "[October]", "[November]",
+            "[December]",
+        },
+
+        { "[A.M.]", "[P.M.]" },                 // %p
+
+        "[[%a][%b][%d][%H][%M][%S][%y]]",       // %c
+        "[[%3m][%.4d][%4.3y]]",                 // %x
+        "[[%3H][%.4M][%4.3S]]",                 // %X
+        "[[%I][%M][%S][%p]]",                   // %r
+        "[[%A][%B][%Od][%H][%M][%S][%Y]]",      // %Ec
+        "%Ow weekday, %OU week, %Oy year",      // %Ex
+        "%OH hour, %OM minute, %OS second",     // %EX
+
+        alt_digits, era
+    };
+
+    const char* const locname = make_LC_TIME (&td);
+
+    return locname;
+}
+
+/**************************************************************************/
+
+
+template <class charT>
+void test_user (charT, const char *cname, const char *locname)
+{
+    const char* const envar = std::getenv (LOCALE_ROOT_ENVAR);
+
+    rw_info (0, 0, __LINE__,
+             "std::time_get<%s>, in locale(\"%s\") "
+             "created from a generated LC_TIME file; "
+             LOCALE_ROOT_ENVAR "=%s",
+             cname, locname, envar);
+
+    // construct a locale object from the binary database
+    std::locale loc;
+
+    _TRY {
+        loc = std::locale (loc, locname, std::locale::time);
+    }
+    _CATCH (...) {
+        rw_error (0, 0, __LINE__,
+                  "locale (locale (), \"%s\", locale::time) "
+                  "unexpectedly threw an exception", locname);
+        return;
+    }
+
+    // set the global locale (used by the test function)
+    std::locale::global (loc);
+
+    
+    // %Ec: The locale's alternative date and time representation.
+    STEP ("%Ec: alternative date and time representation");
+    TEST (T (0, 0, 0, 1, 0, 0, 0),
+          // "[[%A][%B][%Od][%H][%M][%S][%Y]]"
+          "[[[Sunday]][[January]][1st][00][00][00][1900]]", 46,
+          "%Ec", 0, Good);
+
+    TEST (T (5, 4, 3, 2, 1, 1, 1),
+          "[[[monday]][[february]][2nd][03][04][05][1901]]", 47,
+          "%Ec", 0, Good);
+
+    TEST (T (60, 59, 23, 31, 2, -1898, 2),
+          // %Y requires a four digit year, 02 is not treated as 2002
+          "[[[TUE]][[MAR]][31st][23][59][60][02]]", 38,
+          "%Ec", 0, Good);
+
+    // %EC: The name of the base year (period) in the locale's
+    //      alternative representation.
+
+    // %Ex: The locale's alternative date representation.
+    STEP ("%Ex: alternative date representation");
+
+    // verify that facet computes the remaining tm members from
+    // the supplied data
+    TEST (T (0, 0, 0, 21, 4, 2002, 2, 141),
+          // "%Ow weekday, %OU week, %Oy year"
+          "2nd weekday, 21st week, 2nd year", 32,
+          // i.e., May 21, 2002
+          "%Ex", 0, Good);
+
+    // %EX: The locale's alternative time representation.
+    STEP ("%EX: alternative time representation");
+    // verify that 0 is correctly parsed if alternative numeric
+    // symbols are expected and the symbol for zero is empty
+    TEST (T (0, 1, 2),
+          // "%OH hour, %OM minute, %OS second"
+          "2nd hour, 1st minute, 0 second", 30,
+          "%EX", 0, Good);
+
+    TEST (T (21, 22, 23),
+          // "%OH hour, %OM minute, %OS second"
+          "23rd hour, 22nd minute, 21st second", 35,
+          "%EX", 0, Good);
+
+    // %Ey: The offset from %EC (year only) in the locale's
+    //      alternative representation.
+    STEP ("%Ey: offset from %EC in alternative representation.");
+    rw_warn (0, 0, __LINE__, "%%Ey not being exercised");
+
+    // %EY: The full alternative year representation.
+    STEP ("%EY: the full alternative year representation");
+    rw_warn (0, 0, __LINE__, "%%EY not being exercised");
+
+    // %Od: The day of the month using the locale's alternative
+    //      numeric symbols; leading zeros are permitted but not required.
+    STEP ("%Od: the day of the month using alternative numeric symbols");
+    TEST (T (0, 0, 0,  1),  "1st", 3, "%Od", 0, Good);
+    TEST (T (0, 0, 0,  2),  "2nd", 3, "%Od", 0, Good);
+    TEST (T (0, 0, 0, 11), "11th", 4, "%Od", 0, Good);
+    TEST (T (0, 0, 0, 21), "21st", 4, "%Od", 0, Good);
+    TEST (T (0, 0, 0, 30), "30th", 4, "%Od", 0, Good);
+    TEST (T (0, 0, 0, 31), "31st", 4, "%Od", 0, Good);
+    TEST (T (0, 0, 0,  0),   "32", 2, "%Od", 0, Eof | Fail);
+
+    // %Oe: Equivalent to %Od.
+    STEP ("%Oe: equivalent to %Od");
+    TEST (T (0, 0, 0,  3),  "3rd", 3, "%Oe", 0, Good);
+    TEST (T (0, 0, 0,  4),  "4th", 3, "%Oe", 0, Good);
+    TEST (T (0, 0, 0,  9),  "9th", 3, "%Oe", 0, Good);
+    TEST (T (0, 0, 0, 10), "10th", 4, "%Oe", 0, Good);
+    TEST (T (0, 0, 0,  0), "32nd", 2, "%Oe", 0, Fail);
+    TEST (T (0, 0, 0,  0),   "33", 2, "%Oe", 0, Eof | Fail);
+
+    // %OH: The hour (24-hour clock) using the locale's alternative
+    //      numeric symbols.
+    STEP ("%OH: the hour (24-hour clock) using alternative numeric symbols");
+    TEST (T (0, 0,  0),    "0", 1, "%OH", 0, Eof);
+    TEST (T (0, 0,  0),   "00", 2, "%OH", 0, Eof);
+    TEST (T (0, 0,  1),  "1st", 3, "%OH", 0, Good);
+    TEST (T (0, 0,  2),  "2nd", 3, "%OH", 0, Good);
+    TEST (T (0, 0, 11), "11th", 4, "%OH", 0, Good);
+    TEST (T (0, 0, 12), "12th", 4, "%OH", 0, Good);
+    TEST (T (0, 0, 13), "13th", 4, "%OH", 0, Good);
+    TEST (T (0, 0, 23), "23rd", 4, "%OH", 0, Good);
+
+    // %OI: The hour (12-hour clock) using the locale's alternative
+    //      numeric symbols.
+    STEP ("%OI: the hour (12-hour clock) using alternative numeric symbols");
+    TEST (T (0, 0,  0),    "0", 1, "%OI", 0, Eof);
+    TEST (T (0, 0,  0),  "000", 3, "%OI", 0, Eof);
+    TEST (T (0, 0,  3),  "3rd", 3, "%OI", 0, Good);
+    TEST (T (0, 0, 11), "11th", 4, "%OI", 0, Good);
+    TEST (T (0, 0, 12), "12th", 4, "%OI", 0, Good);
+    TEST (T (0, 0,  0), "13th", 4, "%OI", 0, Fail);
+    TEST (T (0, 0,  0),   "14", 2, "%OI", 0, Eof | Fail);
+
+    // %Om: The month using the locale's alternative numeric symbols.
+    STEP ("%Om: the month using alternative numeric symbols");
+    TEST (T (0, 0, 0, 0,  0),  "1st", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  1),  "2nd", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  2),  "3rd", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  3),  "4th", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  4),  "5th", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  5),  "6th", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  6),  "7th", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  7),  "8th", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  8),  "9th", 3, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  9), "10th", 4, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0, 10), "11th", 4, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0, 11), "12th", 4, "%Om", 0, Good);
+    TEST (T (0, 0, 0, 0,  0), "13th", 4, "%Om", 0, Fail);
+    TEST (T (0, 0, 0, 0,  0),    "0", 1, "%Om", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0,  0),   "00", 2, "%Om", 0, Eof | Fail);
+    TEST (T (0, 0, 0, 0,  0),   "01", 2, "%Om", 0, Eof | Fail);
+
+    // %OM: The minutes using the locale's alternative numeric symbols.
+    STEP ("%OM: the minutes using alternative numeric symbols");
+    TEST (T (0,  0),    "0", 1, "%OM", 0, Eof);
+    TEST (T (0,  1),  "1st", 3, "%OM", 0, Good);
+    TEST (T (0,  2),  "2nd", 3, "%OM", 0, Good);
+    TEST (T (0,  3),  "3rd", 3, "%OM", 0, Good);
+    TEST (T (0,  4),  "4th", 3, "%OM", 0, Good);
+    TEST (T (0, 29), "29th", 4, "%OM", 0, Good);
+    TEST (T (0, 30), "30th", 4, "%OM", 0, Good);
+    TEST (T (0, 31), "31st", 4, "%OM", 0, Good);
+    TEST (T (0, 32),   "32", 2, "%OM", 0, Eof);
+    TEST (T (0,  0),   "60", 2, "%OM", 0, Eof | Fail);
+    TEST (T (0,  0),    "2", 1, "%OM", 0, Eof | Fail);
+
+    // %OS: The seconds using the locale's alternative numeric symbols.
+    STEP ("%OS: the seconds using alternative numeric symbols");
+    TEST (T ( 0),    "0", 1, "%OS", 0, Eof);
+    TEST (T ( 1),  "1st", 3, "%OS", 0, Good);
+    TEST (T ( 2),  "2nd", 3, "%OS", 0, Good);
+    TEST (T ( 3),  "3rd", 3, "%OS", 0, Good);
+    TEST (T ( 4),  "4th", 3, "%OS", 0, Good);
+    TEST (T (29), "29th", 4, "%OS", 0, Good);
+    TEST (T (30), "30th", 4, "%OS", 0, Good);
+    TEST (T (31), "31st", 4, "%OS", 0, Good);
+    TEST (T (32),   "32", 2, "%OS", 0, Eof);
+    TEST (T (59),  "059", 3, "%OS", 0, Eof);
+    TEST (T (60), "0060", 4, "%OS", 0, Eof);
+    TEST (T ( 0),   "61", 2, "%OS", 0, Eof | Fail);
+    TEST (T ( 0),   "21", 2, "%OS", 0, Eof | Fail);
+
+    // %OU: The week number of the year (Sunday as the first day of the week)
+    //      using the locale's alternative numeric symbols.
+    STEP ("%OU: the Sunday-based week using alternative numeric symbols");
+    rw_warn (0, 0, __LINE__, "%%OU not being exercised");
+
+    // %Ow: The number of the weekday (Sunday=0) using the locale's
+    //      alternative numeric symbols.
+    STEP ("%Ow: Sunday-based weekday using alternative numeric symbols");
+    TEST (T (0, 0, 0, 0, 0, 0, 0),   "0", 1, "%Ow", 0, Eof);
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "1st", 3, "%Ow", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 2), "2nd", 3, "%Ow", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 6), "6th", 3, "%Ow", 0, Good);
+    TEST (T (0, 0, 0, 0, 0, 0, 0), "7th", 3, "%Ow", 0, Fail);
+    TEST (T (0, 0, 0, 0, 0, 0, 0),   "8", 1, "%Ow", 0, Eof | Fail);
+
+    // %OW: The week number of the year (Monday as the first day of the week)
+    //      using the locale's alternative numeric symbols.
+    STEP ("%OW: the Monday-based week using alternative numeric symbols");
+    
+    TEST (T (0, 0, 0, 0, 0, 0, 1), "1st", 3, "%OW", 0, Good);
+    // rw_warn (0, 0, __LINE__, "%%OW not being exercised");
+
+    // %Oy: The year (offset from %C ) using the locale's alternative
+    //      numeric symbols.
+    STEP ("%Oy: year offset from %C using alternative numeric symbols");
+    rw_warn (0, 0, __LINE__, "%%Oy not being exercised");
+}
+
+/**************************************************************************/
+
+
+// try to find a named locale (use a grep expression if available)
+static const char*
+find_locale (const char *name)
+{
+#if !defined (_WIN32) && !defined (_WIN64)
+
+    rw_locales (_UNUSED_CAT, name);
+    return rw_locales (LC_ALL, name);
+
+#else   // _WIN{32,64}
+
+    // FIXME: handle non-UNIX systems
+    for (const char *loc = rw_locales (); *loc; loc += std::strlen (loc) + 1) {
+        if (!std::strcmp (loc, name))
+            return loc;
+    }
+
+    return 0;
+
+#endif   // _WIN{32,64}
+}
+
+/**************************************************************************/
+
+static int
+run_test (int, char**)
+{
+    // set up RWSTD_LOCALE_ROOT and other environment variables
+    // here as opposed to at program startup to work around a
+    // SunOS 5.7 bug in putenv() (PR ##30017)
+    locale_root = rw_set_locale_root ();
+
+    // store the next available file descriptor
+    // in order to detect file descriptor leaks
+    const int fd0 = rw_nextfd (0);
+
+    test_posix (char (), "char");
+
+    const char *locname;
+
+#if !defined (_WIN32) && !defined (_WIN64)
+
+    const char en_US[] = "en_US";
+    const char de[]    = "^de[^a-z1-9]*";
+    const char da[]    = "^da[^a-z1-9]*";
+
+#else   // dumbass Windows
+
+    const char en_US[] = "ENU";
+    const char de[]    = "DEU";
+    const char da[]    = "DAN";
+
+#endif
+
+    int nnamed = 0;
+
+    // try to find and exercise the english locale
+    if ((locname = find_locale (en_US)) && *locname) {
+        test_english (char (), "char", locname);
+        ++nnamed;
+    }
+
+    // try to find and exercise the german locale
+    if ((locname = find_locale (de)) && *locname) {
+        test_german (char (), "char", locname);
+        ++nnamed;
+    }
+
+    // try to find and exercise the danish locale
+    if ((locname = find_locale (da)) && *locname) {
+        test_danish (char (), "char", locname);
+        ++nnamed;
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise the time_get facets with a user-defined locale
+    std::locale::global (std::locale ("C"));
+
+    // create a LC_TIME database based on user-defined data
+    locname = make_LC_TIME ();
+
+    if (!locname) {
+        rw_error (0, 0, __LINE__, "failed to generate LC_TIME locale data");
+        return 0;
+    }
+
+    test_user (char (), "char", locname);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    test_posix (wchar_t (), "wchar_t");
+
+    test_user (wchar_t (), "wchar_t", locname);
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    // reset the gloab locale to free up resources (such as file
+    // descriptors used by time_get_byname to map locale databases)
+    std::locale::global (std::locale ("C"));
+
+    const int fd1 = rw_nextfd (0);
+
+    rw_assert (0 == fd1 - fd0, 0, __LINE__,
+               "%d file descriptor leaks detected", fd1 - fd0);
+
+    rw_assert (0 != nnamed, 0, __LINE__,
+               "time_get not exercised in named locales");
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.locale.time.get",
+                    0 /* no comment */,
+                    run_test,
+                    "",
+                    0);
+}

Propchange: incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/localization/22.locale.time.get.cpp
------------------------------------------------------------------------------
    svn:keywords = Id



Mime
View raw message