default_century

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:

Listing: Date Class Example Use
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.

Listing: The output method
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).

Listing: Example of dates in English and French
#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.