This keyword allows you to enter the default century which is used to create the correct year when parsing the %y format. This format parses a number and then computes the year by adding it to 100*default_century. The "C" locale has:
default_century = 20
Assume a Date class. The I/O for the Date class can be written using time_get and time_put in a portable manner. The input operator might look like:
template<class charT, class traits> std::basic_istream<charT, traits>& operator >>(std::basic_istream<charT, traits>& is, Date& item) { typename std::basic_istream<charT, traits>::sentry ok(is); if (ok) { std::ios_base::iostate err = std::ios_base::goodbit; try { const std::time_get<charT>& tg = std::use_facet<std::time_get<charT> > (is.getloc()); std::tm t; tg.get_date(is, 0, is, err, &t); if (!(err & std::ios_base::failbit)) item = Date(t.tm_mon+1, t.tm_mday, t.tm_year+1900); } catch (...) { err |= std::ios_base::badbit | std::ios_base::failbit; } is.setstate(err); } return is; }
The code extracts the time_get facet from the istream's locale and uses its get_date method to fill a tm. If the extraction was successful, then the data is transferred from the tm into the Date class.
template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, const Date& item)
{
std::basic_ostream<charT, traits>::sentry ok(os);
if (ok)
{
bool failed;
try
{
const std::time_put<charT>& tp =
std::use_facet<std::time_put<charT> >
(os.getloc());
std::tm t;
t.tm_mday = item.day();
t.tm_mon = item.month() - 1;
t.tm_year = item.year() - 1900;
t.tm_wday = item.dayOfWeek();
charT pattern[2] = {'%', 'x'};
failed = tp.put(os, os, os.fill(), &t, pattern,
pattern+2).failed();
}
catch (...)
{
failed = true;
}
if (failed)
os.setstate(std::ios_base::failbit |
std::ios_base::badbit);
}
return os;
}
After extracting the time_put facet from the ostream's locale, you transfer data from your Date class into the tm (or the Date class could simply export a tm). Then the put method is called with the tm and using the pattern "%x". There are several good things about the Date's I/O methods:
With the Date's I/O done, the rest of the example is very easy. A French locale can be created with the following data in a file named "French":
$time_narrow
date = "%A, le %d %B %Y"
weekday =
dimanche lundi mardi mercredi jeudi vendredi samedi
abrev_weekday =
dim lun mar mer jeu ven sam
monthname = j
anvier février mars avril mai juin juillet août
abrev_monthname =
jan fév mar avr mai juin juil aoû sep oct nov déc
Now a program can read and write Date's in both English and French (and the Date class is completely ignorant of both languages).
#include <locale> #include <iostream> #include <sstream> #include "Date.h" int main() { std::istringstream in("Saturday February 24 2001"); Date today; in >> today; std::cout.imbue(std::locale("French")); std::cout << "En Paris, c'est " << today << '\n'; std::cout.imbue(std::locale("US")); std::cout << "But in New York it is " << today << '\n'; }
This program reads in a Date using the "C" locale from an istringstream. Then cout is imbued with "French" and the same Date is written out. And finally the same stream is imbued again with a "US" locale and the same Date is written out again. The output is:
En Paris, c'est samedi, le 24 février 2001 But in New York it is Saturday February 24 2001
For this example the "US" locale was implemented with an empty file. This was possible since the relevant parts of the "US" locale coincide with the "C" locale.