N2058=06-0128 Proposed Text for Proposal to add Date-Time to the Standard Library 1.0

Jeff Garland (jeff-at-crystalclearsoftware.com)


Table of Contents

Detailed Table of Contents
Introduction
Proposed Text
Acknowledgments
References

Detailed Table of Contents

Introduction

Note: This draft is only partially complete and will need to be updated. However, it does show the scope and extent of the proposal.

This paper will focus on the details of the proposal to add a date-time library to the c++ standard. Please see N1900=05-0160 Proposal to Add Date-Time to the C++ Standard Library for an overview of the motivations, design, and major design decisions.

The author fully expects the Library Working Group to have many suggestions and refinements since this is a lengthy proposal and this is the authors first experience writing a standards proposal.

Proposed Text

Text in notes is meant as explanatory information about the proposal. It is not to be added to the TR.

Note

This is an example of a note that is NOT part of the TR text.

All dates and times in this proposal are supplied in ISO extended form unless otherwise specified. Specifically year-month-day hour:minute:second.fractional_seconds. So the 15th day of September 2006 is specified as 2006-09-15.

Chapter (tbs) - Datetime Library

This clause contains components that C++ programs may use to manipulate dates, times, and timezones.

Unless otherwise specified, all components described in this clause are declared in namespace std::tr2::datetime.

Requirements

Requirements on Programs

Requirements on Implemenations

FW.1 Normative References

ISO 8601:2004 Data elements and interchange formats -- Information interchange -- Representation of dates and times

FW.2 Definitions

Time Point: An instant in the time continuum (dimensionless).

Time Duration: A length of time unattached to a any time point. Time durations have an assigned maxiumum resolution (eg: 1 second).

Time Period: A length of time between two time points

Epoch: The start of a given time scale. For time_t the epoch is 1970-01-01 00:00:00. In this text the epoch will normally be called the 'minimum date' or 'minimum time'.

Maximum Date/Time: The maxiumum representable time in a time system implementation. For time_t the maximum representable time is January 19, 2038 03:14:08.

Valid Date/Time: A date or time that can be represented within the range of a time system with a defined epoch, resolution, and maximum date/time.

Header <datetime> Synopsis

The header <datetime> defines a basic date, basic duration, and basic period class templates.

The header <datetime> defines a basic gregorian calendar templates that implements core calendric calcuations.

The header <datetime> defines a series of typedefs to provide date and other time types.

The header <datetime> defines a timezone classes to provide for local time adjustment calculations input and output.

The header <datetime> defines a input output functions and facets for the date time types.

The header <datetime> defines a set of exception classes used to signal errors in construction of incorrect dates and times.

namespace std 
{
  namespace tr2 
  {
    namespace datetime 
    {

      enum special_values {negative_infinity, positive_infinity, not_a_date_time,
                           max_date_time, min_date_time, not_special };

      enum week_of_month {1st_week = 1, 2nd_week, 3rd_week, 4th_week, 
                          5th_week, last_week_of_month};

      //corresponds to iso 8601 day of the week numbering
      enum day_of_the_week {sunday=1, monday, tuesday, wednesday, thursday, friday, saturday }

      struct year_month_day;

      //basic class for time durations
      template<class duration_rep_traits> class basic_duration;

      //common calendar functions.
      template<typename ymd_type_, typename date_int_type_>
      class basic_calendar;

      //classes and functions for date
      template<class date_impl> 
      class basic_date;


      //Exception classes for construction of dates
      class bad_date_error;   // public std::runtime_error
      class bad_day_of_month; // public bad_date_error
      class bad_day_of_year;  // public bad_date_error
      class bad_week_of_year  // public bad_date_error
      class bad_year;         // public bad_date_error
      class bad_month;        // public bad_date_error
      class bad_weekday;      // public bad_date_error
      class bad_date_conversion; //public bad_date_error

      //high resolution durations
      template<class time_impl>
      class basic_time_duration;

      //Classes and functions for time representation
      template <class time_impl>
      class basic_date_time;

      template <class CharT, class TraitsT>
      std::basic_ostream<CharT, TraitsT>&
      operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_date_time&);

      template <class CharT, class Traits>
      std::basic_istream<CharT, Traits>&
      operator>>(std::basic_istream<CharT, Traits>& is, basic_date_time&);

      //Classes and functions for time periods
      template<class point_rep, class duration_rep>
      class basic_time_period;

      template<typename time_type, typename CharT = char>
      class time_zone_base;

      template<class CharT = char>
      class time_zone_names_base;

      //Timezone type used for user customization (TODO????)
      class time_zone : public time_zone_base<date_time>;

      //Exception class for conversions of local time values
      class invalid_time_label;  // public std::logic_error

      template<typename time_type, typename charT=char>
      class posix_time_zone : public time_zone<time_type, charT>;

      template<class date_type>
      class day_clock;

      template<class time_type>
      class second_clock;

      template<class time_type>
      class microsecond_clock;

      //...indicates implementation defined
      typedef basic_date<implementation-defined>                  date;
      typedef basic_duration<implementation-defined>              days;
      typedef basic_duration<implementation-defined>              weeks;
      typedef basic_duration<implementation-defined>              months;
      typedef basic_duration<implementation-defined>              years;
      typedef basic_time_period<date, days>    date_period;

      typedef basic_date_time<implementation-defined>             date_time;
      typedef basic_time_duration<implementation-defined>         hours;
      typedef basic_time_duration<implementation-defined>         minutes;
      typedef basic_time_duration<implementation-defined>         seconds;
      typedef basic_time_duration<implementation-defined>         milliseconds;
      typedef basic_time_duration<implementation-defined>         microseconds;
      typedef basic_time_duration<implementation-defined>         nanoseconds;

  
      //io stuff
      template <class CharT, class TraitsT>
      std::basic_ostream<CharT, TraitsT>&
      operator<<(std::basic_ostream<CharT, TraitsT>& os, basic_duration&);

      template <class CharT, class Traits>
      std::basic_istream<CharT, Traits>&
      operator>>(std::basic_istream<CharT, Traits>& is,  basic_duration&);

      template <class CharT, class TraitsT>
      std::basic_ostream<CharT, TraitsT>&
      operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_date&);

      template <class CharT, class Traits>
      std::basic_istream<CharT, Traits>&
      operator>>(std::basic_istream<CharT, Traits>& is, basic_date&);

      template <class CharT, class TraitsT>
      std::basic_ostream<CharT, TraitsT>&
      operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_time_duration&);

      template <class CharT, class Traits>
      std::basic_istream<CharT, Traits>&
      operator>>(std::basic_istream<CharT, Traits>& is, basic_time_duration&);


      template <class CharT, class TraitsT>
      std::basic_ostream<CharT, TraitsT>&
      operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_time_period&);

      template <class CharT, class Traits>
      std::basic_istream<CharT, Traits>&
      operator>>(std::basic_istream<CharT, Traits>& is, basic_time_period&);

      template <class CharT, class TraitsT>
      std::basic_ostream<CharT, TraitsT>&
      operator<<(std::basic_ostream<CharT, TraitsT>& os, posix_time_zone&);

      template <class CharT, class Traits>
      std::basic_istream<CharT, Traits>&
      operator>>(std::basic_istream<CharT, Traits>& is,  posix_time_zone&);

      template <class date_type,
                class CharT, 
                class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
      class date_facet; // : public std::locale::facet

      template <class date_type,
                class CharT, 
                class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
      class date_input_facet; // public std::locale::facet {


      template <class time_type,
                class CharT, 
                class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
      class time_facet;

      template <class time_type,
                class CharT, 
                class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
      class time_input_facet;


    }  // namespace datetime 
  }  //namespace tr2
}  //namespace std

Core Classes

Template Class basic_calendar

This is a parameterized implementation of a proleptic Gregorian, iso, and julian calendar functions. These functions allow for the calculation of various date-related values including the conversion of values such as the 'year-month-day' into an integer value that can be used to represent a date.

Note

All the methods of this class are static functions, so the intent is to never create instances of this class.

Note

This class is parameterized to allow for alternate date time implemenations to utilize these functions as part of an implementation.

template<typename ymd_type_, typename date_int_type_>
class basic_calendar {
public:
  typdef  typename ymd_type_::weekday_type weekday_type; //TODO change to traits?
  typedef ymd_type_                        ymd_type;
  typedef typename ymd_type::month_type    month_type;
  typedef typename ymd_type::day_type      day_type;
  typedef typename ymd_type::year_type     year_type;
  typedef date_int_type_                   date_int_type;


  //iso/gregorian related functions
  static unsigned short day_of_week    (const ymd_type& ymd);
  static int            week_number    (const ymd_type& ymd);
  static bool           is_leap_year(year_type y);
  static unsigned short last_day_of_month(year_type y, month_type m);

  //TODO document or remove
  static int            days_after_weekday(date_int_type day_number, weekday_type);
  static int            days_before_weekday(date_int_type day_number, weekday_type);
  

  static date_int_type  day_number     (const ymd_type& ymd);
  static ymd_type       from_day_number(date_int_type);

  //julian calendar functions
  static date_int_type  julian_day_number(const ymd_type& ymd);
  static long           modjulian_day_number(const ymd_type& ymd);
  static ymd_type       from_julian_day_number(long julian_day_number);
  static ymd_type       from_modjulian_day_number(long modjulian_day);

  //calendar traits functions
  static ymd_type       min_ymd();
  static ymd_type       max_ymd();
  static date_int_type  min_count();
  static date_int_type  max_count();
  static unsigned short days_in_week();
};

Remarks:

Returns:

basic_calendar ymd template parameter

The ymd_type parameter is a simple structure that has the following requirements.

ymd_type requirements

ExpressionNotes
ymd_type::year_typeA typedef that provides the integer type used for year field of the ymd_type.
ymd_type::month_typeA typedef that provides the integer type used for month field of the ymd_type.
ymd_type::day_typeA typedef that provides the integer type used for month field of the ymd_type.
ymd_type.yearAn integer type that represents the current year. TODO--ragne
ymd_type.monthAn integer type the represents a month. Values will be assigned with January == 1 thru December ==12
ymd_type.dayAn integer type that represents a day within a month. Values will range from 1 to 31.
ymd_type.day_of_yearAn integer type that represents the day of the year. Values will range from 1 to 366

basic_calendar typedefs

basic_calendar calculation functions

static unsigned short day_of_week    (const ymd_type& ymd);

Returns: Day of the week from the specified year-month-day where Sunday is 0, Monday is 1, thru Saturday == 6.

static int week_number    (const ymd_type& ymd);

Remarks: Calculate the iso week number for the year-month-day as defined in ISO 8601:2004 Data elements and interchange formats -- Information interchange -- Representation of dates and times

Returns: An integer value from 0 to 53 corresponding to the week number for the year,month,day.

static bool           is_leap_year(year_type y);

Returns: True if the specified year is a leap year, false otherwise.

static unsigned short last_day_of_month(year_type y, month_type m);

Remarks: Calculate the last day of the month taking into account leap years. This is a constant for all months except February which returns 28 for a non leap year and 29 for a leap year. For example, the value for January is always 31.

Returns: An integer value between 1 and 31 that represents the last day of the month.

static date_int_type  day_number     (const ymd_type& ymd);

Remarks: Calculate an integer day count based on the proleptic Gregorian/ISO calendar that corresponds to the date. The number must monotinically increase starting from min_count to max_count with one value for each day.

Note

This function provides the infrastructure to implement the days_between dates externally from the calendar class.

Returns: An integer cooresponding to the specified year-month-day. The return value from this function will map to the same passed year-month-day as calculated by from_day_number.

static ymd_type       from_day_number(date_int_type day_number);

Remarks: Converts an integer back to a year-month-day.

Returns: The year-month-day value cooresponding to the specified day_number.

basic_calendar date_int_type template parameter

The date_int_type provides an integer type that is used in all calculations of the date.

Note

The intent of the date_int_type is to allow implementations to use different integer sizes within the implementation. For example, some implementations my use 64 bit integer in representing a combined date time and will find it helpful to directly calculate into this specific integer type even though a 32 bit integer would be sufficient to represent the valid date range. In addition, this enables low level user access to these functions using user defined integer types.

basic_calendar julian calendar functions

The following functions provide conversions to and from julian an modified julian day numbers.

Note

A freely available resource with descriptions of the algorithms to be implemented here can be found at http://www.tondering.dk/claus/calendar.html

static date_int_type  julian_day_number(const ymd_type& ymd);

Remarks: Calculate the julian day number (TODO reference and outside).

Returns: An integer representing the julian day number for the specified year-month-day.

static long modjulian_day_number(const ymd_type& ymd);

Remarks: Calculate the modified julian day number (TODO reference and outside).

Returns: Day of the week from the specified year-month-day where Sunday=0, Monday1, thru Saturday=6.

static ymd_type       from_julian_day_number(long julian_day);

Remarks:

Returns: A year-month-day structure with day, month, year fields set.

static ymd_type       from_modjulian_day_number(long mod_julian_day);

Remarks: A year-month-day structure from the modified julian day.

Returns: Day of the week from the specified year-month-day where Sunday = 0, Monday = 1, thru Saturday == 6.

basic_calendar traits functions

The following functions provide basic information about the minimum and maximum dates handled by the implementation.

static ymd_type       min_ymd();

Remarks: Get the year-month-day of the minimum date provided by the calendar implementation.

Returns: An instance of the ymd_type with the year, month, and day fields set.

Note

For this proposal this will nominally be [1400-01-01

static ymd_type       max_ymd();

Remarks: Get the year-month-day of the maximum date provided by the calendar implementation.

Returns: An instance of the ymd_type with the year, month, and day fields set.

Note

For this proposal this will nominally be [10000-01-01

static date_int_type  min_count();

Returns: Returns the minimum day number value used by the calendar.

Note

This will typically be 0, but implementations may use 0 for special values internally.

static date_int_type  max_count();

Returns: Returns the maximum day number value used by the calendar.

static unsigned short days_in_week();

Remarks: Enables generic programming for non-iso calendar systems.

Returns: Returns 7.

Template Class basic_date

The basic_date template provide the core interface for the date typedef that will be the primary interface for date programming. Internally, the basic_date will hold an implementation defined integer type. This allows the basic_date interface to provide with with different calendar implementations that provide different valid date ranges the typedef date.

template<class date_impl> 
class basic_date {
 public:

  //typedefs
  typedef typename date_impl::calendar_type calendar_type;

  typedef typename date_impl::year_type  year_type;
  typedef typename date_impl::month_type month_type;
  typedef typename date_impl::day_type   day_type;
  typedef typename date_impl::ymd_type   ymd_type;

  typedef typename date_impl::day_of_week_type    day_of_week_type;  
  typedef typename date_impl::day_of_year_type    day_of_year_type;  
  typedef typename date_impl::week_of_year_type   week_of_year_type;

  typedef typename date_impl::weekday_type        weekday_type; 
  typedef typename date_impl::week_of_month_type  week_of_month_type; 

  typedef typename date_impl::special_values_type special_values_type;

  typedef typename date_impl::date_duration_type  date_duration_type;

  typedef typename date_impl::date_int_type date_int_type;


  //constructors
  basic_date(year_type y, month_type m, day_type d);
  basic_date(const ymd_type& ymd);
  basic_date(year_type y, day_of_year_type doy);
  basic_date(const basic_date& rhs);
  //constructs something like: Sunday in Week 50 of year 2004
  basic_date(year_type y, week_of_year_type week_number, weekday_type wd);
  //constructs something like: 3rd Monday in Feb of 2004
  basic_date(year_type y, month_type m, week_of_month_type week_number, weekday_type wd);
  basic_date(std::time_t t);
  basic_date(const std::tm& datetm);
  //construct positive/negative infinity max or min date
  basic_date(special_values_type sv);
  //default constuctor == not-a-date-time
  basic_date(); 

  //Basic accessors
  year_type        year()           const;
  month_type       month()          const;
  day_type         day()            const;
  day_of_week_type day_of_week()    const; //eg: Sun, Mon, ...


  //additional accessors
  day_of_year_type  day_of_year()  const; //1..365 or 1..366 (for leap year)
  week_of_year_type week_number()  const; //ISO 8601 week number 1..53
  date_int_type     day_number()   const; //Return the day number since start of the epoch
  basic_date        end_of_month() const; //Return the last day of the current month

  //special value accessors
  bool is_special()                 const;
  special_values_type as_special()  const;

  //conversion accessors
  time_t        to_time_t()      const;   
  ymd_type      year_month_day() const; //Get ymd structure

  // Conversion to julian calendar
  date_int_type julian_day()     const;
  long          modjulian_day()  const; 

  //calculation accessors 
  date_duration_type days_until  (weekday_type) const;
  date_duration_type days_before (weekday_type) const;
  basic_date         next        (weekday_type) const;
  basic_date         previous    (weekday_type) const;
      
  //comparison operators
  bool operator<  (const basic_date&) const;
  bool operator<= (const basic_date&) const;
  bool operator>  (const basic_date&) const;
  bool operator>= (const basic_date&) const;
  bool operator== (const basic_date&) const;
  bool operator!= (const basic_date&) const;

  //arithmetic operators
  date_duration_type operator-  (const basic_date&)     const;
  basic_date         operator-  (const date_duration_type&) const;
  basic_date         operator-= (const date_duration_type&);
  basic_date         operator+  (const date_duration_type&) const;
  basic_date         operator+= (const date_duration_type&);

};


template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& os, const date&);

template <class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is, date&);


//Exception classes for construction of dates
class bad_day_of_month : public std::out_of_range
{};
class bad_day_of_year : public std::out_of_range
{};
class bad_week_of_year : public std::out_of_range
{};
class bad_year : public std::out_of_range
{};
class bad_month : public std::out_of_range
{};
class bad_weekday : public std::out_of_range
{};
  //Exception class for conversions of local time values
class invalid_time_label : public std::logic_error
{};

Template Class basic_date - typedefs

Template Class basic_date - constructors

The date type provides may types of constructors for creating a date type.

basic_date(); 

Remarks: Construct date with the special value not-a-date-time.

Throws: none

basic_date(const basic_date& rhs);

Remarks: Copy constructor.

Throws: none

basic_date(year_type year, month_type month, day_type day);

Remarks: Construct a month from integer year, month, day values.

Throws:bad_year if year > calendar::max_ymd().year

Throws:bad_month if month < 0 or month > 12

Throws:bad_day if day is greater than calendar::last_day_of_month(year,month)

Note

This last case requires the exception be thrown in the case of a non leap-year and a Feb 29th specification.

basic_date(const ymd_type& ymd);

Remarks: Construct a month from integer year, month, day values in the ymd struct.

Throws:bad_year if ymd.year > calendar::max_ymd().year

Throws:bad_month if ymd.month < 0 or month > 12

Throws:bad_day if ymd.day is greater than calendar::last_day_of_month(year,month)

basic_date(year_type year, day_of_year_type day_of_year);

Remarks: Construct a date based on the year and the day of year value.

Throws:bad_year if ymd.year > calendar::max_ymd().year

Throws:bad_day_of_year day_of_year > 366 or (day_of_year = 366 and and year ! leap year)

Note

In the 8601 standard the day_of_year is called the 'ordinal number'. In leap years, dates after Feb 29 have a different day number than in common years. As a result the day_of_year for March 1 is 61 in a leap year and 60 in common years.

basic_date(year_type y, week_of_year_type week_number, weekday_type wd);

Remarks: Construct a date using a specification like: Sunday in Week 50 of year 2004.

Throws:bad_year if ymd.year > calendar::max_ymd().year

Throws:bad_weekday

Throws:bad_week_of_year

basic_date(year_type y, month_type m, week_of_month_type week_number, weekday_type wd);

Remarks: Constructs something like: 3rd Monday in Feb of 2004

Throws:bad_year if ymd.year > calendar::max_ymd().year

Throws:bad_weekday

Throws:bad_week_of_year

basic_date(std::time_t t);

Remarks: Constructs date base on offset from time_t epoch of 1970-01-01.

Throws: None.

basic_date(const std::tm& datetm);

Remarks: Constructs date from the fields specified in the tm structure. In particular uses the fields tm_mday, tm_mon, tm_year. Values of tm_year are treated as years since 1900. Negative values of tm_year are interpreted as a negative offset from the year 1900.

Note

Most implementations of date input/output in current standard libraries accept and correctly handle tm_year with negative values. For example, tm_year == -1 logically corresponds to 1899. Recently one implementation made a recent change by that prohibited negative tm_year values. The author has not been able to find anything in the standard or otherwise that specifies how negative values of tm_year should be handled. This may need to change to support portable implementations going forward.

Throws:bad_year if datetm.tm_year+1900 > calendar::max_ymd().year or datetm.tm_year+1900 < calendar::min_ymd().year

Throws:bad_month if datetm.tm_month < 0 or datetm.tm_month > 11

Throws:bad_day if datetm.tm_day is greater than calendar::last_day_of_month(year,month) or datetm.tm_day < 1

basic_date(special_values_type sv);

Remarks: Constructs date to one of the supported special values.

Throws: None.

Template Class basic_date - Basic accessors

year_type        year()           const;

Returns: Returns year part of the date. Undefined if date is a special_value.

Throws: None.

month_type       month()          const;

Returns: Returns month part of the date. Undefined if date is a special_value.

Throws: None.

day_type         day()            const;

Returns: Returns month part of the date. Undefined if date is a special_value.

Throws: None.

day_of_week_type day_of_week()    const; 

Returns: Returns the iso day of the week represented by the date. Undefined if date is a special value.

Throws: None.

day_of_year_type  day_of_year()  const; //1..365 or 1..366 (for leap year)

Returns: Returns the iso day of the year (1..366) respresented by the date. Undefined if date is a special value.

Throws: None.

week_of_year_type week_number()  const; 

Returns: Returns the iso week number (1..53) of the day respresented by the date. Undefined if date is a special value.

Throws: None.

date_int_type     day_number()   const; 

Returns: Returns the count of days from calendar::ymd_min() to date represented by date. Undefined if date is a special value.

Throws: None.

basic_date        end_of_month() const; 

Returns: Returns the last day in the month of the date as defined by calendar::last_day_of_month(year, month). Undefined if date is a special value.

Throws: None.

bool is_special() const;

Returns: True of the date is set to one of the special values, false otherwise.

Throws: None.

special_values_type as_special()  const;

Returns: Returns one of the special values

Throws: None.

time_t to_time_t() const;   

Returns: Conversion accessor that returns time_t value represented by the date.

Throws: bad_date_conversion if date value is outside the valid date range represented by time_t or date is a special value.

ymd_type      year_month_day() const; 

Returns: Returns the date broken into the year, month, and day structure.

date_int_type julian_day()     const;

Returns: Conversion accessor that returns julian day value represented by the date.

Throws: bad_date_conversion if date value is outside the valid date range represented by julian_day or date is a special value.

date_int_type modjulian_day()  const; 

Returns: Conversion accessor that returns time_t value represented by the date.

Throws: bad_date_conversion if date value is outside the valid date range represented by modjulian_day or date is a special value.

Template Class basic_date - comparison operators

The comparison operators will take into account the following rules for handling of special values. All representable dates between the minimum and maximum representable date are described as 'any valid date' below. In general, positive_infinity is considered to be greater than any valid date as well as not_a_date_time. negative_infinity is considered to be less than any valid date as well as not_a_date_time. Since max_date_time and min_date_time special values represent valid dates these special values utilize normal comparison rules.

Special Value Comparison Rules

descriptionresultNotes
negative_infinity < negative_infinityfalse
negative_infinity == negative_infinitytrue
negative_infinity < not_a_date_timetrueAlso true for less-equal
negative_infinity < any valid datetrue
not_a_date_time == not_a_date_timetrue
not_a_date_time < not_a_date_timefalseSame is true for less-equal, greater-equal and greater
not_a_date_time == any valid datefalseSame is true for less-equal, greater-equal and greater
positive_infinity > any valid datetrueAlso true for greater-equal
positive_infinity > negative_infinitytrueAlso true for greater-equal, less, less-equal
positive_infinity > negative_infinitytrueAlso true for greater-equal false for less and less-equal
bool operator<  (const basic_date& rhs) const;

Returns: True if date represented by *this < rhs - false otherwise.

bool operator<= (const basic_date&) const;

Returns: True if date represented by *this <= rhs - false otherwise.

bool operator>  (const basic_date&) const;

Returns: True if date represented by *this > rhs - false otherwise.

bool operator>= (const basic_date&) const;

Returns: True if date represented by *this >= rhs - false otherwise.

bool operator== (const basic_date&) const;

Returns: True if date represented by *this >= rhs - false otherwise.

bool operator!= (const basic_date&) const;

Template Class basic_date - arithmetic operators

The following arithmetic operators perform simple subtraction except when the value of the date is a special value. The table defines the rules for special value calculations where 'infinity' represents either positive_infinity or negative_infinity.

Special Value Calculation Rules

Rule --> Result TypeNotes
Timepoint(not_a_date_time) + Duration --> Timepoint(not_a_date_time)
Timepoint(infinity) + Duration --> Timepoint(infinity)
Timepoint + Duration(infinity) --> Timepoint(infinity)
Timepoint - Duration(infinity) --> Timepoint(-infinity)
Timepoint(+infinity) + Duration(-infinity) --> not_a_date_time
Duration(+infinity) + Duration(-infinity) --> not_a_date_time
Duration(infinity) * Zero --> not_a_date_time
Duration(infinity) * Integer(Not Zero) --> Duration(infinity)
Duration(+infinity) * -Integer --> Duration(-infinity)
Duration(infinity) / Integer --> Duration(infinity)
days operator-  (const basic_date&)     const;

Returns: Number of days between this and rhs date value, or special value results.

basic_date       operator-  (const days&) const;

Returns: Date with the specified number of days subtracted or a special value result.

basic_date       operator-= (const days&);

Effects: Set the date the the number of days subtracted or a special value result.

Returns: Date with the specified number of days subtracted or a special value result.

basic_date       operator+  (const days&) const;

Returns: Date with the specified number of days added or a special value result.

basic_date       operator+= (const days&);

Effects: Set the date the the number of days added or a special value result.

Returns: Date with the specified number of days added or a special value result.

Date Construction Exceptions

The following sections detail classes the represent various errors provided by the library to prevent incorrect construction of invalid date and time values.

Class datetime_error

The datetime_error is a base exception for all datetime error reporting. Derived classes provide additional detailed error information.

class datetime_error : public std::runtime_error 
{}

Note

This class derives from std::runtime_error under the presumption that most of the errors involving date construction are a result of bad data input from a user or other data source that can only be read at runtime.

Class bad_day_of_month

class bad_day_of_month : public bad_date_error 
{
 public:
  bad_day_of_month(int month);
  int bad_day() const;
  
};


bad_day_of_month(int month);

Remarks: Constructor that takes the specified month that is out of range. Will be a value > 28 or < 1.

int bad_day() const;

Remarks: Returns the invalid day in month that caused construction failure.

Class bad_day_of_year

class bad_day_of_year : public bad_date_error 
{
 public:
  bad_day_of_year(int day_of_year);
  int bad_day() const;   
};


bad_day_of_year(int day_of_year);

Remarks: Constructor that takes the specified day of year that is out of range. Will be a value > 365 or < 1.

int bad_day() const;

Remarks: Returns the invalid day in year that caused construction failure.

Class bad_week_of_year

class bad_week_of_year : public bad_date_error 
{
 public:
  bad_week_of_year(int week_of_year);
  int bad_week() const;   
};


bad_week_of_year(int week_of_year);

Remarks: Constructor that takes the specified week of year that is out of range. Will be a value > 53 or < 1.

int bad_week() const;

Remarks: Returns the invalid week in year that caused construction failure.

Class bad_year

class bad_year : public bad_date_error 
{
 public:
  bad_year(int year);
  int bad_year() const;   
};


bad_year(int year);

Remarks: Constructor that takes the specified year that is out of range. Will be a year > calendar::max_ymd().year or year < calendar::min_ymd().year

int bad_year() const;

Remarks: Returns the invalid year that caused construction failure.

Class bad_month

class bad_month : public bad_date_error 
{
 public:
  bad_month(int month);
  int bad_month() const;   
};


bad_month(int month);

Remarks: Constructor that takes the specified month that is out of range. Will be a month value < 1 or greater than 12.

int bad_month() const;

Remarks: Returns the invalid month that caused construction failure.

Class bad_weekday

class bad_weekday : public bad_date_error 
{
 public:
  bad_weekday(int weekday);
  int bad_weekday() const;   
};


bad_weekday(int weekday);

Remarks: Constructor that takes the specified weekday that is out of range. Will be a weekday value < 1 or greater than 7. int bad_weekday() const;

Remarks: Returns the invalid weekday that caused construction failure.

Class bad_date_conversion

class bad_date_conversion : public bad_date_error 
{
 public:
  enum conversion_error_type = {max_date_exceeded, min_date_exceeded};
  bad_date_conversion(int year, int month, int day, 
                      conversion_error_type, const char* date_system);
};


  baddate_conversion(int year, int month, int day, 
                     conversion_error_type, const char* date_system);

Effects: Constructs a what string for the base class representative of the error.

Note

The intent is to create and error to along the lines of: "date 2039-10-31 value exceeds maximum range of time_t."

Basic Duration

template<class duration_rep_traits>
class basic_duration
{ 
public:
  typedef typename duration_rep_traits::int_type  duration_rep_type;
  typedef typename duration_rep_traits::impl_type duration_rep;

  //constructors    
  explicit basic_duration(duration_rep day_count);
  basic_duration(special_values);
  duration_rep get_rep()   const;
  duration_rep get_broken_down_duration()      const;

  //accessors
  bool           is_special()  const;
  special_values as_special()  const; 

  static duration_type unit();

  //comparison operators
  bool operator<  (const date_duration&) const;
  bool operator<= (const date_duration&) const;
  bool operator>  (const date_duration&) const;
  bool operator>= (const date_duration&) const;
  bool operator== (const date_duration&) const;
  bool operator!= (const date_duration&) const;

  //arithmetic operations
  duration_type operator-  (const duration_type&) const;
  duration_type operator-= (const duration_type&);
  duration_type operator+  (const duration_type&) const;
  duration_type operator+= (const duration_type&);
  duration_type operator/= (int);
  duration_type operator/  (int);
  duration_type operator*  (int) const;
  duration_type operator*= (int);

  //Sign inversion
  date_duration operator-() const;

  //! return sign information (todo?)
  bool is_negative() const
};

Time Durations

template<class time_impl>
class basic_time_duration 
{
public:
  typedef T duration_type;  //the subclass
  typedef typename time_impl::day_type  day_type;
  typedef typename time_impl::hour_type hour_type;
  typedef typename time_impl::min_type  min_type;
  typedef typename time_impl::sec_type  sec_type;
  typedef typename time_impl::fractional_seconds_type fractional_seconds_type;
  typedef typename time_impl::tick_type tick_type;
  typedef typename time_impl::impl_type impl_type;

  time_duration();
  time_duration(hour_type hours, 
                min_type minutes, 
                sec_type seconds=0,
                fractional_seconds_type frac_sec = 0);

  time_duration(const time_duration<T, rep_type>& other)
  time_duration(special_values sv);

  //traits information
  static duration_type unit(); //support for periods
  static unsigned short num_fractional_digits();
  static tick_type ticks_per_second();
  static time_resolutions resolution();

  hour_type hours()   const;
  min_type minutes()  const;
  sec_type seconds()  const;
  fractional_seconds_type fractional_seconds() const;

  sec_type  total_seconds()      const;
  tick_type total_milliseconds() const;
  tick_type total_nanoseconds()  const;
  tick_type total_microseconds() const;

  //special value accessors
  bool is_special() const();
  special_values as_special() const;


  //comparison operatators
  bool operator<  (const time_duration&) const;
  bool operator<= (const time_duration&) const;
  bool operator>  (const time_duration&) const;
  bool operator>= (const time_duration&) const;
  bool operator== (const time_duration&) const;
  bool operator!= (const time_duration&) const;


  //sign inversion
  duration_type operator-() const

  //arithmetic operations
  duration_type operator- (const duration_type& d) const
  duration_type operator-=(const duration_type& d)
  duration_type operator+ (const duration_type& d) const
  duration_type operator+=(const duration_type& d)
  duration_type operator/ (int divisor) const
  duration_type operator/=(int divisor) 
  duration_type operator* (int rhs) const
  duration_type operator*=(int divisor) 

  tick_type ticks() const 

};



//typedef to the given resolution

//Concrete Time Duration instanciations
class hours;
class minutes;
class seconds;
class milliseconds;
class microseconds;
class nanoseconds;

Template class basic_time_duration - constructors

Template class basic_time_duration - arithmetic operators

Effects:

Remarks:

Template Class basic_date_time

template <class time_impl>
class basic_date_time
{
public:
  typedef typename time_impl::time_type;
  typedef typename time_impl::time_rep_type time_rep_type;
  typedef typename time_impl::date_type date_type;
  typedef typename time_impl::date_duration_type date_duration_type;
  typedef typename time_impl::time_duration_type time_duration_type;
  
  basic_date_time(const date_type& day, 
                  const time_duration_type& td);
  base_date_time(special_values sv)
  base_date_time(const time_rep_type& rhs);

  //accessors
  date_type date()  const;
  time_duration_type time_of_day() const;
  bool is_special() const;
  special_value as_special() const;

  //comparison operators
  bool operator<  (const time_type&) const;
  bool operator<= (const time_type&) const;
  bool operator>  (const time_type&) const;
  bool operator>= (const time_type&) const;
  bool operator== (const time_type&) const;
  bool operator!= (const time_type&) const;

  //arithmetic operators
  time_duration_type operator-(const time_type& rhs) const;
  time_type operator+(const date_duration_type& dd) const;
  time_type operator+=(const date_duration_type& dd);
  time_type operator-(const date_duration_type& dd) const;
  time_type operator-=(const date_duration_type& dd);
  time_type operator+(const time_duration_type& td) const;
  time_type operator+=(const time_duration_type& td);
  time_type operator-(const time_duration_type& rhs) const;
  time_type operator-=(const time_duration_type& td);
  
};

basic_date_time operator+ (const basic_date_time& t, const months& m)
basic_date_time operator+=(basic_date_time& t, const months& m)
basic_date_time operator- (const basic_date_time& t, const months& m)
basic_date_time operator-=(basic_date_time& t, const months& m)

basic_date_time operator+ (const basic_date_time& t, const years& y)
basic_date_time operator+=(basic_date_time& t, const years& y)
basic_date_time operator- (const basic_date_time& t, const years& y)
basic_date_time operator-=(basic_date_time& t, const years& y)

Template Class basic_date_time - typedefs

To Be Specified

Template Class basic_date_time - constructors

To Be Specified

Template Class basic_date_time - comparison operators

To Be Specified

Template Class basic_date_time - arithmetic operators

To Be Specified

Basic Time Period

Provides a generalized interval for use with date and time types.

A time period can be specified by providing either the begining point and a duration or the begining point and the end point. The end is NOT part of the period but 1 unit past it. A period will be "null" if either end_point <= begin_point or the given duration is <= 0. Any non-null period will return false for is_null().

template<class point_rep, class duration_rep>
class basic_time_period 
{
public:
  typedef point_rep    point_type;
  typedef duration_rep duration_type;
  
  //constructors
  basic_time_period(point_type first_point, point_type end_point);
  basic_time_period(point_type first_point, duration_type len);

  //basic accessors
  point_rep begin()     const;
  point_rep end()       const;
  point_rep last()      const;
  duration_rep length() const;
  bool is_null()        const;

  //specialized accessors
  bool contains    (const point_type& point) const;
  bool contains    (const period& other)    const;
  bool intersects  (const period& other)    const;
  bool is_adjacent (const period& other)    const;
  bool is_before   (const point_type& point) const;
  bool is_after    (const point_type& point) const;
  basic_time_period intersection (const basic_time_period& other) const;
  basic_time_period merge        (const basic_time_period& other) const;
  basic_time_period span         (const basic_time_period& other) const;
  basic_time_period expand       (const duration_type& len) const;
  basic_time_period shift        (const duration_rep& len);

  //comparison operators
  bool operator<  (const period&) const;
  bool operator<= (const period&) const;
  bool operator>  (const period&) const;
  bool operator>= (const period&) const;
  bool operator== (const period&) const;
  bool operator!= (const period&) const;


};

Template class basic_time_period - template parameter types

point_rep and duration_rep (TODO: fix me)

Note

The basic_time_period will have implementation-defined date members to represent the beginning and end of the period. For example, an implemenation could use pointrep begin and pointrep last. These data members are used to implement all of the accessors and operations on the period. Implementations are free optimize this combination of values.

Template class basic_time_period - constructors

basic_time_period(point_type first_point, point_type end_point);

Remarks: Construct a period from a starting point and a non-inclusive end point.

If passed a start time of 3 and an end time of 6 the following interval would be constructed

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7

If end_point < first_point then the period is a null period. If end_point == first_point then the period has a zero length.

Effects: Set the internal data members to represent the specfied period.

Throws: None.

basic_time_period(point_type first_point, duration_type duration);

Remarks: Construct a period from a starting point in time and a time length.

If passed a start time of 3 and a duration of 2 the following interval would be constructed

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7

If duration is negative then the period is a null period. If duration is zero then the period has a zero length.

Effects: Set the internal data members to represent the specfied period.

Throws: None.

Template class basic_time_period - basic accessors

point_rep begin()     const;

Returns: The first time point in the interval.

point_rep end()       const;

Returns: One past the last time point of the interval.

If an interval from 3 to 5 is specified 6 is returned.

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
                        ^
point_rep last()      const;

Returns: the last time point included in the interval.

If an interval from 3 to 5 is specified 5 is returned.

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
                    ^
duration_rep length() const;

Returns: Time duration between period.start() and period.end()

Example: if an interval from 3 to 5 is specified 2 is returned.

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7                    
bool is_null()        const;

Returns: True if the period.last < period.start

Template class basic_time_period - specialized accessors

bool contains    (const point_type& point) const;

Returns: True if the time point is contained in the interval. ((point >= begin) && (point <= last)) Zero length and null intervals return false for all values.

Example: if a time interval from 3 to 5 is specified values 3, 4 and 5
     will return true, all others return false.

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
    f   f   t   t   t   f  f                    
bool contains    (const basic_time_period& other)    const;

Returns: True if the time period is completely contained. ((begin <= other.begin) && (last >= other.last)) Zero length and null intervals return false for values.

Example: P1 contains p2 and p3.
          --p1---
          --p2---
           p3-
                    --p4---
    p5- 
bool intersects  (const basic_time_period& other)    const;

Returns: True if the time period is completely contained. Zero length and null intervals return false for values.

In the example below p1 intersects with p2, p4, and p6.
          [---p1---]
                [---p2---]
                   [---p3---]
     [---p4---]
    [-p5-] 
            [-p6-

]

bool is_adjacent (const basic_time_period& other)    const;

Returns: True if periods are next to each other without a gap.

Example: p1 and p2 are adjacent, but p3 is not adjacent
     with either of p1 or p2.
      [-p1-)
           [-p2-)
             [-p3-) 
bool is_before   (const point_type& point) const;

Returns: True point < period.start.

Example: If a time interval from 3 to 5 is values 1 and 2
     will return true, all others return false.

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
    t   t   f   f   f   f  f                    
bool is_after    (const point_type& point) const;

Returns: True point < period.last

Example: If a time interval from 3 to 5 is values 1 and 2
     will return true, all others return false.

            [-------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
    f   f   f   f   f   t  t                    
basic_time_period intersection (const basic_time_period& other) const;

Returns: Returns time period that represents the intersection of two time time periods. Null and zero length time periods return null time period of unspecified value.

Example the intersection of 3,7 with 2,4 is 3,4
     will return true, all others return false.
        [-------]
            [-------]
result->    [---]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
basic_time_period merge        (const basic_time_period& other) const;

Returns: Returns merging the union of two intesecting periods or an unspecified null period if the two periods do not intersect. Null and zero length time periods return null time period of unspecified value.

Example merge of 3,7 with 2,4 is 3,4
     will return true, all others return false.
        [-------]
            [-------]
result->[-----------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
basic_time_period span         (const basic_time_period& other) const;

Returns: Returns a period defined by min(p1.start, p2.start) max(p1.last, p2.last)

Example span of 2,3 with 4,6 is 2,6
        [---]
                [------]
result->[--------------]
    ^   ^   ^   ^   ^   ^  ^
    1   2   3   4   5   6  7
basic_time_period expand       (const duration_type& len) const;

Returns: Returns a period defined by start-len, last+len.

Example: expand of 3,5 by 2 is 1,7
                [--------]
result-> [----------------------]
         ^   ^   ^   ^   ^   ^  ^
         1   2   3   4   5   6  7
basic_time_period shift        (const duration_rep& len);

Returns: Returns a period defined by start+len, last+len.

Example: shift of 3,5 by -2 is 1,3
                 [-------]
result-> [-------]
         ^   ^   ^   ^   ^   ^   ^
         1   2   3   4   5   6   7

Template class basic_time_period - comparison operators

Comparison operators implemented strictly in terms of the period start value.

bool operator<  (const period& rhs) const;

Returns: Returns true if this.start < rhs.start.

bool operator== (const period&) const;

Returns: Returns true if this.start = rhs.start and this.last = rhs.last

bool operator<= (const period&) const;
bool operator>  (const period&) const;
bool operator>= (const period&) const;
bool operator!= (const period&) const;

The remaining operators can be defined as expected based on operator< and operator==.

template class time_zone_base

template<typename time_type, typename CharT = char>
class time_zone_base  {
public:
  typedef std::basic_string<CharT> string_type;
  typedef std::basic_stringstream<CharT> stringstream_type;
  typedef typename time_type::date_type::year_type year_type;
  typedef typename time_type::time_duration_type time_duration_type;

  time_zone_base() {};
  virtual ~time_zone_base() {};
 
  //Time zone names information
  virtual string_type dst_zone_abbrev() const=0;
  virtual string_type std_zone_abbrev() const=0;
  virtual string_type dst_zone_name()   const=0;
  virtual string_type std_zone_name()   const=0;

  //Offsets from UTC
  virtual time_duration_type base_utc_offset()                 const=0;
  virtual time_duration_type dst_offset()                      const=0;

  //Daylight savings details
  virtual bool               has_dst()                         const=0;
  virtual time_type          dst_local_start_time(year_type y) const=0;
  virtual time_type          dst_local_end_time  (year_type y) const=0;

  //Printing function
  virtual string_type        to_posix_string()                 const=0;
  
};

Concrete Temporal Types

The following typedefs will constitute the primary user programming interface.

//Date Programming

typedef basic_date<implementation-defined>                  date;
typedef basic_duration<implementation-defined>              days;
typedef basic_duration<implementation-defined>              weeks;
typedef basic_duration<implementation-defined>              months;
typedef basic_duration<implementation-defined>              years;
typedef basic_time_period<date, days>    date_period;
  //Time Programming
typedef basic_date_time<implementation-defined>             date_time;
typedef basic_time_durationimplementation-defined>          hours;
typedef basic_time_duration<implementation-defined>         minutes;
typedef basic_time_duration<implementation-defined>         seconds;
typedef basic_time_duration<implementation-defined>         milliseconds;
typedef basic_time_duration<implementation-defined>         microseconds;
typedef basic_time_duration<implementation-defined>         nanoseconds;
typedef basic_time_period<date_time, milliseconds>                 date_time_period;

Additional Types

Time Zone Types

The following time zone classes provide the basis for specification and management of local time conversions.

template class time_zone

template<class CharT = char>
class time_zone_names_base
{
public:
  typedef std::basic_string<CharT> string_type;
  time_zone_names_base(const string_type& std_zone_name,
                       const string_type& std_zone_abbrev,
                       const string_type& dst_zone_name,
                       const string_type& dst_zone_abbrev) 
  {}
  string_type dst_zone_abbrev() const
  string_type std_zone_abbrev() const
  string_type dst_zone_name() const
  string_type std_zone_name() const
};


//Timezone base type 
class time_zone : public time_zone_base<> {
public:
  typedef typename time_type::year_type year_type;
  typedef boost::posix_time::time_duration time_duration_type;
  typedef time_zone_base base_type;
  typedef base_type::string_type string_type;
  typedef base_type::stringstream_type stringstream_type;

  time_zone(const time_zone_names& zone_names,   
            const time_duration_type& base_utc_offset,
            const dst_adjustment_offsets& dst_offset,
            boost::shared_ptr<dst_calc_rule> calc_rule) :
  {};
  virtual ~time_zone() {};
  virtual std::string dst_zone_abbrev() const
  virtual std::string std_zone_abbrev() const
  virtual std::string dst_zone_name() const
  virtual std::string std_zone_name() const
  virtual bool has_dst() const
  virtual date_time dst_local_start_time(year_type y) const
  virtual date_time dst_local_end_time(year_type y) const
  virtual time_duration_type base_utc_offset() const
  virtual time_duration_type dst_offset() const
  virtual string_type to_posix_string() const
};

template class posix_time_zone

Posix time zone leverages one of the most widely used specifcations of timezones to provide for the calculation of local times.

template<typename time_type, typename charT=char>
class posix_time_zone : public time_zone<time_type, charT>  {
public:
  typedef typename time_type::year_type year_type;

  posix_time_zone(const std::string& s);
  virtual ~posix_time_zone();

  //various zone name strings
  virtual std::string std_zone_abbrev() const
  virtual std::string dst_zone_abbrev() const;
  virtual std::string std_zone_name()   const;
  virtual std::string dst_zone_name()   const;

  virtual bool has_dst() const;

  //calculate start / end of dst
  virtual time_type dst_local_start_time(year_type y) const;
  virtual time_type dst_local_end_time(year_type y) const;

  virtual time_duration_type base_utc_offset() const;
  virtual time_duration_type dst_offset() const;

  //! Returns a POSIX time_zone string for this object
  virtual string_type to_posix_string() const
};

Clock Types

The following types interact with the local computer clock to retrieve the current or UTC time. The different clocks provide time values with different levels of resolution.

template class day_clock

template<class date_type>
class day_clock
{
public:
  //returns a time adjusted to the specified time zone
  template<class time_zone_type>
  static date_type local_time(const time_zone_type& zone_spec);

  static date_type local_time();
  static date_type universal_time();
};

template class microsecond_clock

template<class time_type>
class microsecond_clock
{
public:
  //returns a time adjusted to the specified time zone
  template<class time_zone_type>
  static time_type local_time(const time_zone_type& zone_spec);

  static time_type local_time();
  static time_type universal_time();
};

template class second_clock

template<class time_type>
class second_clock
{
public:
  //returns a time adjusted to the specified time zone
  template<class time_zone_type>
  static time_type local_time(const time_zone_type& zone_spec);

  static time_type local_time();
  static time_type universal_time();
};

Date Time Input-Output

Input-Output Formatting Strings

The following are proposed additions and changes to input output formatting strings accepted for proposed facet classes that follow.

The following table describes the new flags to be supported by time_put facet.

New Formatting Flags for Facets

FlagDescription
%fFractional seconds and separator - always used even when value is zero.
%FFractional seconds and separator - only output when non-zero.
%sSeconds separator and fractional seconds
%TTime in 24-hour notation %H:%M:%S (from strftime)
%qISO time zone
%QISO extended time zone
%rTime in AM/PM notation - same as '%I:%M:%S %p' (from strftime)
%VISO week number in range from 0 to 53 (from strftime)
%ZTime zone name - long (eg: 'Eastern Standard Time').
%ZPPosix time zone string (eg: EST-05EDT+01,M4.1.0/02:00,M10.5.0/02:00

The following table summarizes the proposed default i/o formats for the temporal types.

Preferred Formatting

Temporal TypeFormatExampleComment
date%Y-%b-%d2004-Jan-31
daysNone45No formatting or adornment
date_period[%Y-%b-%d/%Y-%b-%d)[2004-Jan-31/2004-Feb-25]
date_time%Y-%b-%d %H:%M:%S.%f2004-Jan-31 05:10:31.00000030
time duration types%H:%M:%S.%f05:10:31.00000030
date_time_period[%Y-%b-%d %H:%M:%S.%f/%Y-%b-%d %H:%M:%S.%f)[2004-Jan-31 05:10:31.00000030/2004-Feb-25 05:10:31.00000030]

Input-Output Classes and Functions

template class date_output_facet

/* Class that provides format based I/O facet for date types.
 *
 * This class allows the formatting of dates by using format string.
 * Format strings are:
 *
 *  - %A => long_weekday_format - Full name Ex: Tuesday
 *  - %a => short_weekday_format - Three letter abbreviation Ex: Tue
 *  - %B => long_month_format - Full name Ex: October
 *  - %b => short_month_format - Three letter abbreviation Ex: Oct
 *  - %x => standard_format_specifier - defined by the locale
 *  - %Y-%b-%d => default_date_format - YYYY-Mon-dd
 *
 * Default month format == %b
 * Default weekday format == %a
 *
 *
 */
template <class date_type,
          class CharT, 
          class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
class date_output_facet : public std::locale::facet {
public:
  typedef typename date_type::duration_type duration_type;
  typedef typename date_type::day_of_week_type day_of_week_type;
  typedef typename date_type::day_type day_type;
  typedef typename date_type::month_type month_type;
  typedef boost::date_time::period<date_type,duration_type> period_type;
  typedef std::basic_string<CharT> string_type;
  typedef CharT                    char_type;
  typedef boost::date_time::period_formatter<CharT>  period_formatter_type;
  typedef boost::date_time::special_values_formatter<CharT>  special_values_formatter_type;
  typedef std::vector<std::basic_string<CharT> > input_collection_type;

  explicit date_output_facet(::size_t a_ref = 0);

  explicit date_output_facet(const char_type* format,
                      const input_collection_type& short_month_names,
                      ::size_t ref_count = 0);
   
  explicit date_output_facet(const char_type* format, 
                      period_formatter_type period_formatter = period_formatter_type(), 
                      special_values_formatter_type special_values_formatter = special_values_formatter_type(),
                      ::size_t ref_count = 0);

  void format(const char_type* const format);
  virtual void set_iso_format();
  virtual void set_iso_extended_format();
  void month_format(const char_type* const format);
  void weekday_format(const char_type* const format);
  
  void period_formatter(period_formatter_type period_formatter);
  void special_values_formatter(const special_values_formatter_type& svf);
  void short_weekday_names(const input_collection_type& short_weekday_names);
  void long_weekday_names(const input_collection_type& long_weekday_names);
  void short_month_names(const input_collection_type& short_month_names);
  void long_month_names(const input_collection_type& long_month_names);
  OutItrT put(OutItrT next,  std::ios_base& a_ios,  
       char_type fill_char, const date_type& d) const ;
  OutItrT put(OutItrT next,  std::ios_base& a_ios, 
              char_type fill_char, const duration_type& dd) const ;
  OutItrT put(OutItrT next,  std::ios_base& a_ios, 
              char_type fill_char, const month_type& m) const;
  // puts the day of month
  OutItrT put(OutItrT next,  std::ios_base& a_ios, 
              char_type fill_char, const day_type& day) const;
  OutItrT put(OutItrT next,  std::ios_base& a_ios, 
              char_type fill_char, const day_of_week_type& dow) const;
  OutItrT put(OutItrT next,  std::ios_base& a_ios, 
              char_type fill_char, const period_type& p) const 
  
};

To Be Specified...

template class date_input_facet

// Input facet that uses format strings to parse dates, 
// date durations, and date periods. Like the output facet allows 
// for customization of all strings associated with date type 
// including days of week, month names, and special values.
template <class date_type,
          class CharT, 
          class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
class date_input_facet : public std::locale::facet {
public:
  typedef typename date_type::duration_type duration_type;
  typedef typename date_type::day_of_week_type day_of_week_type;
  typedef typename date_type::day_type day_type;
  typedef typename date_type::month_type month_type;
  typedef typename date_type::year_type year_type;
  typedef basic_time_period<date_type,duration_type> period_type;
  typedef std::basic_string<CharT> string_type;
  typedef CharT                    char_type;
  typedef boost::date_time::period_parser<date_type, CharT>  period_parser_type;
  typedef special_values_parser<date_type,CharT> special_values_parser_type; 
  typedef std::vector<std::basic_string<CharT> > input_collection_type;
  typedef format_date_parser<date_type, CharT> format_date_parser_type;

  
  explicit date_input_facet(::size_t a_ref = 0);

  explicit date_input_facet(const string_type& format,
                            ::size_t a_ref = 0);

  explicit date_input_facet(const string_type& format,
                            const format_date_parser_type& date_parser,
                            const special_values_parser_type& sv_parser,
                            const period_parser_type& per_parser,
                            const date_gen_parser_type& date_gen_parser,
                            ::size_t ref_count = 0);


  void format(const char_type* const format);
  virtual void set_iso_format();
  virtual void set_iso_extended_format();
  void month_format(const char_type* const format);
  void weekday_format(const char_type* const format);
  void year_format(const char_type* const format);

  //set the various strings associated with dates
  void short_weekday_names(const input_collection_type& weekday_names);
  void long_weekday_names(const input_collection_type& weekday_names);
  void short_month_names(const input_collection_type& month_names);
  void long_month_names(const input_collection_type& month_names);

  //allow user specialization of period and special value handling
  void period_parser(period_parser_type period_parser);
  void special_values_parser(special_values_parser_type sv_parser);

  InItrT get(InItrT& from, 
             InItrT& to, 
             std::ios_base& /*a_ios*/, 
             date_type& d) const;
  InItrT get(InItrT& from, 
             InItrT& to, 
             std::ios_base& /*a_ios*/, 
             month_type& m) const;
  InItrT get(InItrT& from, 
             InItrT& to, 
             std::ios_base& /*a_ios*/, 
             day_of_week_type& wd) const;
  InItrT get(InItrT& from, 
             InItrT& to, 
             std::ios_base& /*a_ios*/, 
             day_type& d) const;
  InItrT get(InItrT& from, 
             InItrT& to, 
             std::ios_base& /*a_ios*/, 
             year_type& y) const;
  InItrT get(InItrT& from, 
             InItrT& to, 
             std::ios_base& a_ios, 
             duration_type& dd) const;
  InItrT get(InItrT& from, 
             InItrT& to, 
             std::ios_base& a_ios, 
             period_type& p) const;
};

template class time_output_facet

/* Facet used for format-based output of date_time types 
 * This class provides for the use of format strings to output times.  In addition
 * to the flags for formatting date elements, the following are the allowed format flags:
 *  - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z")
 *  - %f => fractional seconds ".123456"
 *  - %F => fractional seconds or none: like frac sec but empty if frac sec == 0
 *  - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f) 
 *  - %S => seconds "02"
 *  - %z => abbreviated time zone "EDT"
 *  - %Z => full time zone name "Eastern Daylight Time"
 */
template <class time_type,
          class CharT, 
          class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
class time_output_facet : 
  public date_output_facet<typename time_type::date_type , CharT, OutItrT> {
 public:
  typedef typename time_type::date_type date_type;
  typedef typename time_type::time_duration_type time_duration_type;
  typedef basic_time_period<time_type,time_duration_type> period_type;
  typedef date_output_facet<typename time_type::date_type, CharT, OutItrT> base_type;
  typedef typename base_type::string_type string_type;
  typedef typename base_type::char_type   char_type;
  typedef typename base_type::period_formatter_type period_formatter_type;
  typedef typename base_type::special_values_formatter_type special_values_formatter_type;

  explicit time_facet(::size_t a_ref = 0);
  explicit time_facet(const char_type* a_format,
                      period_formatter_type period_formatter = period_formatter_type(), 
                      const special_values_formatter_type& special_value_formatter = special_values_formatter_type(),
                       ::size_t a_ref = 0);

  // Changes format for time_duration
  void time_duration_format(const char_type* const format);
  virtual void set_iso_format();
  virtual void set_iso_extended_format();

  //write out a date_time time point
  OutItrT put(OutItrT a_next, 
              std::ios_base& a_ios, 
              char_type a_fill, 
              const time_type& a_time) const;

  //write out a duration
  OutItrT put(OutItrT a_next, 
              std::ios_base& a_ios, 
              char_type a_fill, 
              const time_duration_type& a_time_dur) const;

  //wirte out a date_time period
  OutItrT put(OutItrT next, std::ios_base& a_ios, 
              char_type fill, const period_type& p) const;


};

To Be Specified...

template class time_input_facet

// Facet for format-based input of date_time types
//default date_time format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz]
//default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...]
template <class time_type,
          class CharT, 
          class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
class time_input_facet : 
  public date_input_facet<typename time_type::date_type , CharT, InItrT> {
  public:
    typedef typename time_type::date_type date_type;
    typedef typename time_type::time_duration_type time_duration_type;
    typedef typename time_duration_type::fractional_seconds_type fractional_seconds_type;
    typedef basic_time_period<time_type,time_duration_type> period_type;
    typedef date_input_facet<typename time_type::date_type, CharT, InItrT> base_type;
    typedef typename base_type::duration_type date_duration_type;
    typedef typename base_type::year_type year_type;
    typedef typename base_type::month_type month_type;
    typedef typename base_type::day_type day_type;
    typedef typename base_type::string_type string_type;
    typedef typename string_type::const_iterator const_itr;
    typedef typename base_type::char_type   char_type;
    typedef typename base_type::format_date_parser_type format_date_parser_type;
    typedef typename base_type::period_parser_type period_parser_type;
    typedef typename base_type::special_values_parser_type special_values_parser_type;
    typedef typename base_type::date_gen_parser_type date_gen_parser_type;
    typedef typename base_type::special_values_parser_type::match_results match_results;

    explicit time_input_facet(const string_type& format, ::size_t a_ref = 0);

    explicit time_input_facet(const string_type& format,
                              const format_date_parser_type& date_parser,
                              const special_values_parser_type& sv_parser,
                              const period_parser_type& per_parser,
                              const date_gen_parser_type& date_gen_parser,
                              ::size_t a_ref = 0);

    InItrT get(InItrT& sitr, 
               InItrT& stream_end, 
               std::ios_base& a_ios, 
               time_duration_type& td) const;

    InItrT get(InItrT& sitr, 
               InItrT& stream_end, 
               std::ios_base& a_ios, 
               time_type& t) const;

    InItrT get_local_time(InItrT& sitr, 
                          InItrT& stream_end, 
                          std::ios_base& a_ios, 
                          time_type& t,
                          string_type& tz_str) const;

    InItrT get(InItrT& sitr, 
               InItrT& stream_end, 
               std::ios_base& a_ios, 
               time_type& t,
               string_type& tz_str,
               bool time_is_local) const;

};

To Be Specified...

Output Operators for Temporal Types

The following functions specify input and output operators for all temporal types.

//dates
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_date&);

template <class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is, basic_date&);

//date_time
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_date_time&);

template <class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is, basic_date_time&);
     //date durations
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& os, basic_duration&);

template <class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is,  basic_duration&);

//time_periods
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_time_period&);

template <class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is, basic_time_period&);

//posix time zone
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& os, posix_time_zone&);
  template <class CharT, class Traits>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is,  posix_time_zone&);

Acknowledgments

First thanks goes to the Boost Community for all the constructive suggestions for evolving Boost Date-Time Library into a great C++ date-time library. Special thanks goes to my family for allowing me to work on this.

References