Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r75429 - in sandbox/chrono_date: . boost boost/chrono boost/chrono/date boost/chrono/date/detail boost/chrono/date/io boost/chrono/date/tmp libs libs/date libs/date/build libs/date/doc libs/date/example libs/date/perf libs/date/src libs/date/test libs/date/test/contextual libs/date/test/contextual/nth libs/date/test/contextual/nth_week libs/date/test/dates libs/date/test/dates/days libs/date/test/dates/ydoy libs/date/test/dates/ymd libs/date/test/dates/ywwd libs/date/test/durations libs/date/test/durations/days libs/date/test/durations/months libs/date/test/durations/weeks libs/date/test/durations/years libs/date/test/factories libs/date/test/formats libs/date/test/formats/days libs/date/test/formats/year_day_of_year libs/date/test/formats/year_month_day libs/date/test/formats/year_week_weekday libs/date/test/generators libs/date/test/io libs/date/test/wrappers
From: vicente.botet_at_[hidden]
Date: 2011-11-09 18:17:36


Author: viboes
Date: 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
New Revision: 75429
URL: http://svn.boost.org/trac/boost/changeset/75429

Log:
Chrono.Date Added first poc version adapted from H. Hinnant standard Date proposal.
Added:
   sandbox/chrono_date/
   sandbox/chrono_date/boost/
   sandbox/chrono_date/boost/chrono/
   sandbox/chrono_date/boost/chrono/date/
   sandbox/chrono_date/boost/chrono/date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/compressed_tuple.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/config.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/conversions.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/date_durations.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/date_generators.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/date_io.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/day.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/day_of_year.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/days_date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/detail/
   sandbox/chrono_date/boost/chrono/date/detail/helpers.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/detail/to_string.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/exceptions.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/include.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/io/
   sandbox/chrono_date/boost/chrono/date/is_date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/month.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/month_nth.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/month_nth_weekday.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/no_check.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/nth.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/nth_week.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/nth_weekday.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/optional_date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/relative_date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tmp/
   sandbox/chrono_date/boost/chrono/date/tmp/date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tmp/date_fwd.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tmp/factories.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tmp/formats.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tmp/gregorian.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tmp/relative_date_save.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tmp/xx.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/tuples.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/week.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/weekday.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/ydoy_date.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/year.hpp (contents, props changed)
   sandbox/chrono_date/boost/chrono/date/ymd_date.hpp (contents, props changed)
   sandbox/chrono_date/libs/
   sandbox/chrono_date/libs/date/
   sandbox/chrono_date/libs/date/build/
   sandbox/chrono_date/libs/date/build/Jamfile.v2 (contents, props changed)
   sandbox/chrono_date/libs/date/doc/
   sandbox/chrono_date/libs/date/doc/Jamfile.v2 (contents, props changed)
   sandbox/chrono_date/libs/date/doc/date.html (contents, props changed)
   sandbox/chrono_date/libs/date/example/
   sandbox/chrono_date/libs/date/example/ex_julian.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/example/ex_week_based_year.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/example/hello_world.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/example/julian.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/example/julian.hpp (contents, props changed)
   sandbox/chrono_date/libs/date/example/week_based_year.hpp (contents, props changed)
   sandbox/chrono_date/libs/date/perf/
   sandbox/chrono_date/libs/date/perf/Jamfile.v2 (contents, props changed)
   sandbox/chrono_date/libs/date/perf/no_check.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/src/
   sandbox/chrono_date/libs/date/src/conversions.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/src/date.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/src/days_date.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/src/rel_date.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/src/vars.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/src/ydoy_date.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/src/ymd_date.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/
   sandbox/chrono_date/libs/date/test/Jamfile.v2 (contents, props changed)
   sandbox/chrono_date/libs/date/test/contextual/
   sandbox/chrono_date/libs/date/test/contextual/nth/
   sandbox/chrono_date/libs/date/test/contextual/nth_week/
   sandbox/chrono_date/libs/date/test/dates/
   sandbox/chrono_date/libs/date/test/dates/days/
   sandbox/chrono_date/libs/date/test/dates/days/days_date_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/dates/days/nth_days_date_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/dates/ydoy/
   sandbox/chrono_date/libs/date/test/dates/ydoy/ydoy_date_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/dates/ymd/
   sandbox/chrono_date/libs/date/test/dates/ymd/ymd_date_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/dates/ywwd/
   sandbox/chrono_date/libs/date/test/durations/
   sandbox/chrono_date/libs/date/test/durations/days/
   sandbox/chrono_date/libs/date/test/durations/months/
   sandbox/chrono_date/libs/date/test/durations/weeks/
   sandbox/chrono_date/libs/date/test/durations/years/
   sandbox/chrono_date/libs/date/test/factories/
   sandbox/chrono_date/libs/date/test/formats/
   sandbox/chrono_date/libs/date/test/formats/days/
   sandbox/chrono_date/libs/date/test/formats/year_day_of_year/
   sandbox/chrono_date/libs/date/test/formats/year_month_day/
   sandbox/chrono_date/libs/date/test/formats/year_week_weekday/
   sandbox/chrono_date/libs/date/test/generators/
   sandbox/chrono_date/libs/date/test/io/
   sandbox/chrono_date/libs/date/test/wrappers/
   sandbox/chrono_date/libs/date/test/wrappers/day_of_year_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/wrappers/day_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/wrappers/month_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/wrappers/nth_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/wrappers/nth_week_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/wrappers/week_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/wrappers/weekday_pass.cpp (contents, props changed)
   sandbox/chrono_date/libs/date/test/wrappers/year_pass.cpp (contents, props changed)

Added: sandbox/chrono_date/boost/chrono/date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,13 @@
+// date --------------------------------------------------------------//
+
+// Copyright 2011 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHRONO_DATE_HPP
+#define BOOST_CHRONO_DATE_HPP
+
+#include <boost/chrono/date/include.hpp>
+
+#endif // BOOST_CHRONO_DATE_HPP

Added: sandbox/chrono_date/boost/chrono/date/compressed_tuple.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/compressed_tuple.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,63 @@
+// compressed_tuple
+//
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_COMPRESSED_TUPLE_HPP
+#define BOOST_CHRONO_DATE_MONTH_NTH_HPP
+
+#include <boost/cstdint.hpp>
+
+namespace boost
+{
+ namespace compressed
+ {
+
+ template <typename T>
+ struct width_bits : integral_constant<std::size, sizeof(T)> {};
+
+ template <typename T>
+ struct compress
+ {
+ static int64_t apply(T);
+ };
+ template <typename T>
+ struct decompress
+ {
+ static T apply(int64_t);
+ };
+
+ template <typename T>
+ struct Compressable {
+
+
+ };
+
+
+ template <typename T1, typename T2>
+ class tuple2
+ {
+ typedef least<T1,T2>::type storage;
+ storage value_;
+ public:
+ template <std::size N>
+ void save(typename types<N>::type);
+ template <std::size N>
+ typename types<N>::type load();
+
+ tuple2(T1 v1, T2 v2)
+ {
+ save<0>(v1);
+ save<1>(v2);
+ }
+
+ };
+
+ } // compressed
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/config.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/config.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,39 @@
+// config.hpp
+//
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_CONFIG_HPP
+#define BOOST_CHRONO_DATE_CONFIG_HPP
+
+#include <boost/chrono/config.hpp>
+
+
+// 1 => days +ymd +leap
+// 2 => days
+// 3 => ymd +leap
+// 4 => ydoy +leap
+#ifndef BOOST_CHRONO_DATE_DATE_DESIGN
+#define BOOST_CHRONO_DATE_DATE_DESIGN 4
+#endif
+
+// 1 => days +ymd +leap
+// 3 => ymd +leap
+#ifndef BOOST_CHRONO_DATE_YMD_DATE_DESIGN
+#define BOOST_CHRONO_DATE_YMD_DATE_DESIGN 3
+#endif
+
+// 1 => days +ymd +leap
+// 2 => days
+// 3 => ymd +leap
+#ifndef BOOST_CHRONO_DATE_REL_DATE_DESIGN
+#define BOOST_CHRONO_DATE_REL_DATE_DESIGN 2
+#endif
+
+
+//#define BOOST_CHRONO_DATE_DATE_DESIGN_BUG
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/conversions.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/conversions.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,51 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_CONVERSIONS_HPP
+#define BOOST_CHRONO_DATE_CONVERSIONS_HPP
+
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/tuples.hpp>
+#include <boost/chrono/date/config.hpp>
+
+//! @file Conversion between the different date formats
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * days to ymd conversion.
+ * @param d the days to convert.
+ * @pre d is a valid number of days.
+ * @return the ymd calculated from the parameter d.
+ */
+ year_month_day to_ymd(days d) BOOST_NOEXCEPT;
+ year_month_day_leap to_ymd_leap(days) BOOST_NOEXCEPT;
+ year_month_day to_ymd(year_day_of_year) BOOST_NOEXCEPT;
+ year_month_day to_ymd(year_week_weekday) BOOST_NOEXCEPT;
+
+ year_day_of_year to_ydoy(days) BOOST_NOEXCEPT;
+ year_day_of_year to_ydoy(year_month_day) BOOST_NOEXCEPT;
+ year_day_of_year to_ydoy(year_week_weekday) BOOST_NOEXCEPT;
+
+ days to_days(year_month_day) BOOST_NOEXCEPT;
+ days to_days(year_day_of_year) BOOST_NOEXCEPT;
+ days to_days(year_week_weekday) BOOST_NOEXCEPT;
+
+ year_week_weekday to_ywwd(year_month_day) BOOST_NOEXCEPT;
+ year_week_weekday to_ywwd(year_day_of_year) BOOST_NOEXCEPT;
+ year_week_weekday to_ywwd(days) BOOST_NOEXCEPT;
+
+ } // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,76 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_TMP_DATE_HPP
+#define BOOST_CHRONO_DATE_TMP_DATE_HPP
+
+
+#include <boost/chrono/date/config.hpp>
+#include <boost/chrono/date/ymd_date.hpp>
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 | BOOST_CHRONO_DATE_DATE_DESIGN == 3
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+#include <boost/chrono/date/days_date.hpp>
+#if defined BOOST_CHRONO_DATE_DATE_DESIGN_BUG
+#include <boost/chrono/date/tmp/date.hpp>
+#endif
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 4
+#include <boost/chrono/date/ydoy_date.hpp>
+#endif
+
+namespace boost
+{
+ namespace chrono
+ {
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 | BOOST_CHRONO_DATE_DATE_DESIGN == 3
+
+ /**
+ * A type representing the default date.
+ */
+ typedef ymd_date date;
+// /**
+// * A type representing an optional of the default date.
+// */
+// typedef optional_ymd_date optional_date;
+// /**
+// * @Returns If the parameters represents a valid date the date,
+// * otherwise a none optional.
+// */
+// inline optional_date make_valid_date(year y,month m,day d) BOOST_NOEXCEPT
+// {
+// return make_valid_ymd_date(y,m,d);
+// }
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+#if ! defined BOOST_CHRONO_DATE_DATE_DESIGN_BUG
+ typedef days_date date;
+// typedef optional_days_date optional_date;
+//
+//
+// inline optional_date make_valid_date(year y,month m,day d) BOOST_NOEXCEPT
+// {
+// return make_valid_days_date(y,m,d);
+// }
+
+#endif
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 4
+ typedef ydoy_date date;
+// typedef optional_ydoy_date optional_date;
+//
+//
+// inline optional_date make_valid_date(year y,month m,day d) BOOST_NOEXCEPT
+// {
+// return make_valid_ydoy_date(y,m,d);
+// }
+#endif
+
+ } // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/date_durations.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/date_durations.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,313 @@
+// date_durations.hpp
+//
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+/**
+ * @file
+ *
+ * There are some chrono date duration types: days, weeks, months and years.
+ * days and weeks are a chrono::duration.
+ * The latter two types are modeled after chrono::duration except that there are
+ * no conversions to and from the the different durations, not even amongst
+ * themselves. These durations represent time durations, as opposed to
+ * representing a date component (e.g. 7 months) and are used in date arithmetic.
+ * These durations are based on a signed integral type that must be at
+ * least 32 bits.
+ */
+#ifndef BOOST_CHRONO_DATE_DATE_DURATIONS_HPP
+#define BOOST_CHRONO_DATE_DATE_DURATIONS_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/duration.hpp>
+//#include <boost/chrono/io/duration_unit_string.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * A duration counting days.
+ */
+ typedef duration<boost::int_least64_t, boost::ratio<86400> > days;
+ /**
+ * A duration counting weeks.
+ */
+ typedef duration<boost::int_least32_t, boost::ratio<7 * 86400> > weeks;
+ typedef duration<boost::int_least32_t, boost::ratio<2629746> >
+ average_months;
+ typedef duration<boost::int_least32_t, boost::ratio<31556952> >
+ average_years;
+ typedef duration<boost::int_least32_t, boost::ratio<400 * 31556952> >
+ _400_years;
+
+
+// /**
+// * partial duration_unit_strings specialization for days
+// */
+// template <class CharT>
+// struct duration_unit_strings<days::period, CharT >
+// {
+// static std::basic_string<CharT> plural()
+// {
+// static const CharT u[] =
+// { 'd', 'a', 'y', 's' };
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> singular()
+// {
+// static const CharT u[] =
+// { 'd', 'a', 'y' };
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> symbol()
+// {
+// //static const std::basic_string<CharT> str(1, 'd');
+// return plural();
+// }
+// };
+// /**
+// * partial duration_unit_strings specialization for weeks
+// */
+// template <class CharT>
+// struct duration_unit_strings<weeks::period, CharT >
+// {
+// static std::basic_string<CharT> plural()
+// {
+// static const CharT u[] =
+// { 'w', 'e', 'e', 'k', 's' };
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> singular()
+// {
+// static const CharT u[] =
+// { 'w', 'e', 'e', 'k' };
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> symbol()
+// {
+// //static const std::basic_string<CharT> str(1, 'W');
+// return plural();
+// }
+// };
+//
+// template <class CharT>
+// struct duration_unit_strings<average_months::period, CharT >
+// {
+// static std::basic_string<CharT> plural()
+// {
+// static const CharT u[] =
+// { 'm', 'o', 'n', 't', 'h', 's' };
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> singular()
+// {
+// static const CharT u[] =
+// { 'm', 'o', 'n', 't', 'h'};
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> symbol()
+// {
+// //static const std::basic_string<CharT> str(1, 'M');
+// return plural();
+// }
+// };
+//
+// template <class CharT>
+// struct duration_unit_strings<average_years::period, CharT >
+// {
+// static std::basic_string<CharT> plural()
+// {
+// static const CharT u[] =
+// { 'y', 'e', 'a', 'r', 's' };
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> singular()
+// {
+// static const CharT u[] =
+// { 'y', 'e', 'a', 'r' };
+// static const std::basic_string<CharT> suffix(u, u + sizeof(u)
+// / sizeof(u[0]));
+// return suffix;
+// }
+// static std::basic_string<CharT> symbol()
+// {
+// //static const std::basic_string<CharT> str(1, 'M');
+// return plural();
+// }
+// };
+
+ namespace detail
+ {
+ template <class T, int>
+ class duration_type
+ {
+ public:
+ typedef T rep;
+ private:
+ rep x_;
+ public:
+ explicit duration_type(rep x = rep()) BOOST_NOEXCEPT : x_(x)
+ {
+ }
+
+ rep count() const BOOST_NOEXCEPT
+ {
+ return x_;
+ }
+
+ duration_type operator+() const BOOST_NOEXCEPT
+ {
+ return *this;
+ }
+ duration_type operator-() const BOOST_NOEXCEPT
+ {
+ return duration_type(-x_);
+ }
+
+ duration_type& operator++() BOOST_NOEXCEPT
+ {
+ ++x_;
+ return *this;
+ }
+ duration_type operator++(int) BOOST_NOEXCEPT
+ {
+ return duration_type(x_++);
+ }
+ duration_type& operator--() BOOST_NOEXCEPT
+ {
+ --x_;
+ return *this;
+ }
+ duration_type operator--(int) BOOST_NOEXCEPT
+ {
+ return duration_type(x_--);
+ }
+
+ duration_type& operator+=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ += rhs.x_;
+ return *this;
+ }
+ duration_type& operator-=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ -= rhs.x_;
+ return *this;
+ }
+
+ friend duration_type operator+(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x += y;
+ return x;
+ }
+ friend duration_type operator-(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x -= y;
+ return x;
+ }
+
+ duration_type& operator*=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ *= rhs;
+ return *this;
+ }
+ duration_type& operator/=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ /= rhs;
+ return *this;
+ }
+ duration_type& operator%=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ %= rhs;
+ return *this;
+ }
+ duration_type& operator%=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ %= rhs.x_;
+ return *this;
+ }
+
+ friend duration_type operator*(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x *= y;
+ return x;
+ }
+ friend duration_type operator*(rep x, duration_type y) BOOST_NOEXCEPT
+ {
+ y *= x;
+ return y;
+ }
+ friend duration_type operator/(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x /= y;
+ return x;
+ }
+ friend rep operator/(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ / y.x_;
+ }
+ friend duration_type operator%(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x %= y;
+ return x;
+ }
+ friend duration_type operator%(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x %= y.x_;
+ return x;
+ }
+
+ friend bool operator==(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ friend bool operator!=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ friend bool operator< (duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+ friend bool operator> (duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ friend bool operator<=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ friend bool operator>=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+ //friend class date;
+ };
+ }
+
+ typedef detail::duration_type<int32_t, 1> months;
+ typedef detail::duration_type<int32_t, 2> years;
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/date_generators.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/date_generators.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,202 @@
+// date_generators.hpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_GENERATORS_HPP
+#define BOOST_CHRONO_DATE_DATE_GENERATORS_HPP
+
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/date.hpp>
+#include <boost/chrono/date/relative_date.hpp>
+#include <boost/chrono/date/nth_weekday.hpp>
+#include <boost/chrono/date/month_nth_weekday.hpp>
+#include <boost/chrono/date/month_nth.hpp>
+#include <boost/chrono/date/nth_week.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/date_io.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * Generates a date satisfying the constraint parameter gt the Date parameter.
+ * @tparam Date any model of a Date (is_date<Date> is true_type).
+ * @param wd the constraint applied to the date @c x parameter.
+ * @param x the reference date.
+ * @return Let @c a be @c wd converted to an @c int, and @c b be @c x.weekday()
+ * converted to an @c int. If <c>a < b</c>, returns <c>x - days(b-a)</c>, else returns <c>x - days(7 - (a-b))</c>.
+ */
+ template <typename Date>
+ inline Date
+ operator<(weekday wd, Date x)
+ {
+ const week::rep a = static_cast<week::rep>(wd);
+ const week::rep b = static_cast<week::rep>(x.get_weekday());
+ if (a < b)
+ {
+ return x - days(b-a);
+ }
+ return x - days(weekday::size - (a-b));
+ }
+
+ template <typename Date>
+ inline Date
+ operator<=(weekday wd, Date x)
+ {
+ const week::rep a = static_cast<week::rep>(wd);
+ const week::rep b = static_cast<week::rep>(x.get_weekday());
+ if (a <= b)
+ {
+ return x - days(b-a);
+ }
+ return x - days(weekday::size - (a-b));
+ }
+
+ template <typename Date>
+ inline Date
+ operator>(weekday wd, Date x)
+ {
+ const week::rep a = static_cast<week::rep>(x.get_weekday());
+ const week::rep b = static_cast<week::rep>(wd);
+ if (a < b)
+ {
+ return x + days(b-a);
+ }
+ return x + days(weekday::size - (a-b));
+ }
+
+ template <typename Date>
+ inline Date
+ operator>=(weekday wd, Date x)
+ {
+ const week::rep a = static_cast<week::rep>(x.get_weekday());
+ const week::rep b = static_cast<week::rep>(wd);
+ if (a <= b)
+ {
+ return x + days(b-a);
+ }
+ return x + days(weekday::size - (a-b));
+ }
+
+ template <typename Date>
+ inline Date
+ operator >(month_day md, Date d)
+ {
+ Date res;
+ if (res.set_if_valid_date(d.get_year(),md.get_month(),md.get_day()) && res > d ) return res;
+ if (res.set_if_valid_date(year(d.get_year()+1),md.get_month(),md.get_day()) && res > d ) return res;
+ res=Date(d.get_year()+2,md.get_month(),md.get_day(),no_check);
+ return res;
+ }
+ template <typename Date>
+ inline Date
+ operator >=(month_day md, Date d)
+ {
+ Date res;
+ if (res.set_if_valid_date(d.get_year(),md.get_month(),md.get_day()) && res >= d) return res;
+ if (res.set_if_valid_date(year(d.get_year()+1),md.get_month(),md.get_day()) && res >= d) return res;
+ res=Date(d.get_year()+2,md.get_month(),md.get_day(),no_check);
+ return res;
+ }
+
+ template <typename Date>
+ inline Date
+ operator >(nth n, Date d)
+ {
+ std::cout << __FILE__<<"["<<__LINE__ <<"] "<< d << '\n';
+ Date res;
+ if (d.get_month()==dec)
+ { // dec and jan have 31 days
+ res = Date(d.get_year(),d.get_month(),n.value(),no_check);
+ std::cout << __FILE__<<"["<<__LINE__ <<"] "<< res << '\n';
+
+ if (res > d) return res;
+ return Date(d.get_year(),jan,n.value(),no_check);
+ }
+
+ if (n.value()>28)
+ { // As feb could have 29,30 and 31, we need to validate the two first dates
+ if (res.set_if_valid_date(d.get_year(),d.get_month(),day(n.value())) && res > d) return res;
+ if (res.set_if_valid_date(d.get_year(),month(d.get_month()+1),day(n.value())) && res > d) return res;
+ return Date(d.get_year(),d.get_month()+2,n.value(),no_check) ;
+ }
+ // nth <= 28 is always valid, so the next is either in this month or the next one
+ res = Date(d.get_year(),d.get_month(),n.value(),no_check);
+ std::cout << __FILE__<<"["<<__LINE__ <<"] "<< res << '\n';
+ if (res > d) return res;
+ std::cout << __FILE__<<"["<<__LINE__ <<"] "<< int(d.get_month()+1) << '\n';
+ return Date(d.get_year(),d.get_month()+1,n.value(),no_check);
+ }
+ template <typename Date>
+ inline Date
+ operator >=(nth n, Date d)
+ {
+ Date res;
+ if (d.get_month()==dec)
+ { // dec and jan have 31 days
+ res = Date(d.get_year(),d.get_month(),n.value(),no_check);
+ if (res >= d) return res;
+ return Date(d.get_year(),jan,n.value(),no_check);
+ }
+
+ if (n.value()>28)
+ { // As feb could have 29,30 and 31, we need to validate the two first dates
+ if (res.set_if_valid_date(d.get_year(),d.get_month(),day(n.value())) && res >= d) return res;
+ if (res.set_if_valid_date(d.get_year(),month(d.get_month()+1),day(n.value())) && res >= d) return res;
+ return Date(d.get_year(),d.get_month()+2,n.value(),no_check) ;
+ }
+ // nth <= 28 is always valid, so the next is either in this month or the next one
+ res = Date(d.get_year(),d.get_month(),n.value(),no_check);
+ if (res >= d) return res;
+ return Date(d.get_year(),month(d.get_month()+1,no_check),n.value(),no_check);
+ }
+
+
+ template <typename Constraint>
+ class forward_generator
+ {
+ private:
+ Constraint constraint_;
+ public:
+ explicit forward_generator(Constraint constraint)
+ : constraint_(constraint)
+ {
+ }
+ template <typename Date>
+ Date operator()(Date d)
+ {
+ return constraint_ > d;
+ }
+ };
+ template <typename Constraint, typename Date>
+ class forward_range
+ {
+ private:
+ Constraint constraint_;
+ Date dt_;
+ public:
+ explicit forward_range(Constraint constraint, Date dt)
+ : constraint_(constraint),
+ dt_(dt)
+ {
+ }
+ Date operator()()
+ {
+ dt_ = constraint_ > dt_;
+ return dt_;
+ }
+ };
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/date_io.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/date_io.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,357 @@
+// date_io.hpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_IO_HPP
+#define BOOST_CHRONO_DATE_DATE_IO_HPP
+
+/*
+ Date i/o synopsis
+
+ namespace boost
+ {
+ namespace chrono
+ {
+
+
+ template <class CharT>
+ class datepunct
+ : public std::locale::facet
+ {
+ public:
+ typedef std::basic_string<CharT> string_type;
+
+ private:
+ string_type fmt_; // exposition only
+
+ public:
+ static std::locale::id id;
+
+ explicit datepunct(std::size_t refs = 0,
+ const string_type& fmt = string_type("%F"));
+ explicit datepunct(std::size_t refs,
+ string_type&& fmt);
+
+ const string_type& fmt() const noexcept;
+ };
+
+ template<class CharT>
+ unspecified
+ date_fmt(std::basic_string<CharT> fmt);
+
+ template<class CharT>
+ unspecified
+ date_fmt(const CharT* fmt);
+
+ template<class CharT, class Traits>
+ std::basic_istream<CharT,Traits>&
+ operator>>(std::basic_istream<CharT,Traits>& is, Date& d);
+
+ template<class CharT, class Traits>
+ std::basic_ostream<CharT, Traits>&
+ operator<<(std::basic_ostream<CharT, Traits>& os, const Date& d);
+
+ } // chrono
+ } // std
+
+ */
+
+#include <istream>
+#include <ostream>
+#include <locale>
+#include <boost/cstdint.hpp>
+#include <boost/chrono.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/is_date.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/chrono/config.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * @c datepunct is a facet which holds a string of formatting characters to be used with @c time_get and @c time_put.
+ */
+ template<class charT>
+ class datepunct: public std::locale::facet
+ {
+ public:
+ typedef std::basic_string<charT> string_type;
+
+ static std::locale::id id;
+
+ /**
+ *
+ * @param refs
+ * @Effects Constructs a @c datepunct by constructing the base class with @c refs.
+ * @Postconditions <c>fmt() == "%F"</c>.
+ */
+ explicit datepunct(std::size_t refs = 0) :
+ std::locale::facet(refs)
+ {
+ fmt_.push_back('%');
+ fmt_.push_back('F');
+ }
+
+ /**
+ *
+ * @param fmt
+ * @param refs
+ * @Effects: Constructs a @c datepunct by constructing the base class with @c refs.
+ * @Postconditions: <c>fmt() == frmt</c>.
+ */
+ explicit datepunct(string_type fmt, std::size_t refs = 0) :
+ std::locale::facet(refs),
+ //#if ! defined BOOST_NO_RVALUE_DEFERENCES
+ // fmt_(std::move(fmt))
+ //#else
+ fmt_(fmt)
+ //#endif
+ {
+ }
+
+ /**
+ * @Returns: the stored format.
+ */
+ const string_type& fmt() const BOOST_NOEXCEPT
+ {
+ return fmt_;
+ }
+ private:
+ string_type fmt_;
+
+ };
+
+ template<class CharT>
+ std::locale::id datepunct<CharT>::id;
+
+ template<class charT>
+ struct date_manip
+ {
+ std::basic_string<charT> fmt_;
+
+ explicit date_manip(std::basic_string<charT> fmt)
+ //#if ! defined BOOST_NO_RVALUE_DEFERENCES
+ // : fmt_(std::move(fmt))
+ // {
+ // }
+ //#else
+ :
+ fmt_(fmt)
+ {
+ }
+ //#endif
+ };
+
+ template<class charT, class traits>
+ std::basic_ostream<charT, traits>&
+ operator <<(std::basic_ostream<charT, traits>& os, date_manip<charT> m)
+ {
+ //#if ! defined BOOST_NO_RVALUE_DEFERENCES
+ // os.imbue(std::locale(os.getloc(), new datepunct<charT>(std::move(m.fmt_))));
+ //#else
+ os.imbue(std::locale(os.getloc(), new datepunct<charT> (m.fmt_)));
+ //#endif
+ return os;
+ }
+
+ template<class charT, class traits>
+ std::basic_istream<charT, traits>&
+ operator >>(std::basic_istream<charT, traits>& is, date_manip<charT> m)
+ {
+ //#if ! defined BOOST_NO_RVALUE_DEFERENCES
+ // is.imbue(std::locale(is.getloc(), new datepunct<charT>(std::move(m.fmt_))));
+ //#else
+ is.imbue(std::locale(is.getloc(), new datepunct<charT> (m.fmt_)));
+ //#endif
+ return is;
+ }
+
+ /**
+ * Date format manipulator
+ * @param fmt the format following the syntax in specified in $.
+ * @Returns: An object of unspecified type such that if @c out is an object
+ * of type @c basic_ostream<CharT,Traits> then the expression
+ * <c>out << date_fmt(fmt)</c> behaves as if it called
+ * <c>f(out, fmt)</c>, or if @c in is an object of type
+ * <c>basic_istream<charT, traits></c> then the expression
+ * <c>in >> date_fmt(fmt)</c> behaves as if it called <c>f(in, fmt)</c>,
+ * where the function @c f is defined as:
+ * @code
+ * template<class charT, class traits>
+ * void f(basic_ios<charT, traits>& str, basic_string<charT> fmt)
+ * {
+ * str.imbue(locale(str.getloc(), new datepunct<charT>(move(fmt))));
+ * }
+ * @endcode
+ */
+ template<class charT>
+ inline date_manip<charT> date_fmt(std::basic_string<charT> fmt)
+ {
+ //#if ! defined BOOST_NO_RVALUE_DEFERENCES
+ // return date_manip<charT>(std::move(fmt));
+ //#else
+ return date_manip<charT> (fmt);
+ //#endif
+ }
+
+ /**
+ * Date format manipulator
+ * @param fmt the format following the syntax in specified in $.
+ * @return <c>date_fmt(std::string(fmt))</c>
+ */
+ template<class charT>
+ inline date_manip<charT> date_fmt(const charT* fmt)
+ {
+ return date_manip<charT> (fmt);
+ }
+
+ /**
+ *
+ * @param is
+ * @param item
+ * @Effects: Behaves as a formatted input function. After constructing a
+ * @c sentry object, if the @c sentry converts to @c true, acquires the
+ * @c time_get facet from the stream's locale. If the locale has a
+ * @c datepunct facet,obtains the conversion specifier string from that
+ * facet, otherwise sets the conversion specifier string to @c "%F".
+ * Then extracts a @c tm from is as if:
+ * @code
+ * tg.get(is, 0, is, err, &t, fmt, fmtend);
+ * @endcode
+ *
+ * Where @c tg is the @c time_get facet, @c err is a local variable of type
+ * @c ios_base::iostate, @c t is a local variable of type @c tm, and
+ * [@cfmt, @cfmtend) are local variables of type @c charT* which delimit
+ * the conversion specifier string.
+ *
+ * If <c>(err & ios_base::failbit)</c> is @c false, assigns a date to @c d
+ * which is constructed from the @c year, @c month and @c day information
+ * stored within t. In any case, then calls <c>is.setstate(err)</c>.
+
+ Returns: is.
+
+ */
+ template<class charT, class traits, typename Date>
+ typename enable_if<is_date<Date> , std::basic_istream<charT, traits>&>::type
+ 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;
+ charT pattern[] =
+ { '%', 'F' };
+ const charT* pb = pattern;
+ const charT* pe = pb + 2;
+ typedef datepunct<charT> F;
+ std::locale loc = is.getloc();
+ if (std::has_facet<F>(loc))
+ {
+ const F& f = std::use_facet<F>(loc);
+ pb = f.fmt().data();
+ pe = pb + f.fmt().size();
+ }
+ tg.get(is, 0, is, err, &t, pb, pe);
+ if (!(err & std::ios_base::failbit))
+ {
+ item
+ = Date(year(t.tm_year + 1900), month(t.tm_mon + 1), day(t.tm_mday));
+ }
+ }
+ catch (...)
+ {
+ err |= std::ios_base::badbit | std::ios_base::failbit;
+ }
+ is.setstate(err);
+ }
+ return is;
+ }
+
+ /**
+ *
+ * @param os
+ * @param item
+ * @Effects: Behaves as a formatted output function. After constructing a
+ * @c sentry object, if the @c sentry converts to @c true, acquires the
+ * @c time_put facet from the stream's locale. If the locale has a
+ * @c datepunct facet, obtains the formatting string from that facet,
+ * otherwise sets the formatting string to @c "%F". Then creates a local
+ * variable @c t of type @c tm. The variable @c t is filled with the @c year,
+ * @c month, @c day and @c weekday information contained in @c d. @c t is
+ * then inserted into @c os as if:
+ * @code
+ * bool failed = tp.put(os, os, os.fill(), &t, pattern, pat_end).failed();
+ * @endcode
+ *
+ * Where @c tp is the @c time_put facet, and <c>[pattern, pat_end)<c> are
+ * local variables of type @c charT* which delimit the formatting string.
+ *
+ * If @c failed is @c true, calls <c>os.setstate(ios_base::failbit | ios_base::badbit)</c>.
+ *
+ * @Returns: os.
+ */
+ template<class charT, class traits, typename Date>
+ typename enable_if<is_date<Date> , std::basic_ostream<charT, traits>&>::type
+ operator <<(std::basic_ostream<
+ charT, traits>& os, const Date& item)
+ {
+ typename 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.get_day();
+ t.tm_mon = item.get_month() - 1;
+ t.tm_year = item.get_year() - 1900;
+ t.tm_wday = item.get_weekday();
+ charT pattern[] =
+ { '%', 'F' };
+ const charT* pb = pattern;
+ const charT* pe = pb + 2;
+ typedef datepunct<charT> F;
+ std::locale loc = os.getloc();
+ if (std::has_facet<F>(loc))
+ {
+ const F& f = std::use_facet<F>(loc);
+ pb = f.fmt().data();
+ pe = pb + f.fmt().size();
+ }
+ failed = tp.put(os, os, os.fill(), &t, pb, pe).failed();
+ }
+ catch (...)
+ {
+ failed = true;
+ }
+ if (failed)
+ {
+ os.setstate(std::ios_base::failbit | std::ios_base::badbit);
+ }
+ }
+ return os;
+ }
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/day.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/day.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,110 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_DAY_HPP
+#define BOOST_CHRONO_DATE_DATE_DAY_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class @c day is used to specify the day of the month when constructing dates.
+ */
+ class day
+ {
+ public:
+ typedef int_least8_t rep;
+ static const rep last_=31;
+ static const rep first_=1;
+ static const std::size_t size=last_-first_+1; // :5 bits
+
+ /**
+ * @Effects: Constructs an object of class @c day by storing @c d.
+ * @Postconditions: <c>value() == d && is_valid()</c>.
+ * @Throws: if @c d is outside of the range [1, 31], throws an exception of type @c bad_date.
+ */
+ explicit day(rep d)
+ : value_(d)
+ {
+ if (!is_valid())
+ {
+ throw bad_date("day " + boost::chrono::to_string(int(d)) + " is out of range");
+ }
+ }
+
+ /**
+ * @Effects: Constructs an object of class @c day by storing @c d.
+ * @Postconditions: <c>value() == d</c>.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ day(rep d,no_check_t) BOOST_NOEXCEPT
+ : value_(d)
+ {}
+ /**
+ * @Return if the stored value is a valid one.
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+ /**
+ * @Returns: the underlying value of that day.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Returns: the underlying value of that day.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Returns: the min valid value for a day of a month.
+ */
+ static BOOST_CONSTEXPR day min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return day(first_,no_check);
+ }
+ /**
+ * @Returns: the first day of a month.
+ */
+ static BOOST_CONSTEXPR day first()
+ {
+ return day(first_,no_check);
+ }
+ /**
+ * @Returns: the max valid value for a day of a month.
+ */
+ static BOOST_CONSTEXPR day max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return day(last_,no_check);
+ }
+ private:
+ rep value_;
+ };
+
+ typedef day day_of_month;
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/day_of_year.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/day_of_year.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,106 @@
+// date
+//
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_DAY_OF_YEAR_HPP
+#define BOOST_CHRONO_DATE_DATE_DAY_OF_YEAR_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class day_of_year is used to specify the day of the year when constructing a date.
+ */
+ class day_of_year
+ {
+ public:
+ typedef int_least16_t rep;
+ static const rep last_=366;
+ static const rep first_=1;
+ static const std::size_t size=last_-first_+1; // :9 bits
+
+ /**
+ * @Effects: Constructs an object of class @c day_of_year by storing @c d.
+ * @Postconditions: <c>value() == d && is_valid()</c>.
+ * @Throws: if @c d is outside of the range [1, 366], throws an exception of type @c bad_date.
+ */
+ explicit day_of_year(rep d)
+ : value_(d)
+ {
+ if (!is_valid())
+ {
+ throw bad_date("day_of_year " + boost::chrono::to_string(d) + " is out of range");
+ }
+ }
+ /**
+ * @Effects: Constructs an object of class @c day_of_year by storing @c d.
+ * @Postconditions: <c>value() == d</c>.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ day_of_year(rep d,no_check_t) BOOST_NOEXCEPT
+ : value_(d)
+ {}
+ /**
+ * @Return if the stored value is a valid one, i.e. in the range [1,366].
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+ /**
+ * @Returns: the underlying value of that day of year.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Returns: the underlying value of that day of year.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Returns: the min valid value for a day of a year.
+ */
+ static BOOST_CONSTEXPR day_of_year min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return day_of_year(first_,no_check);
+ }
+ /**
+ * @Returns: the first day of a month.
+ */
+ static BOOST_CONSTEXPR day_of_year first()
+ {
+ return day_of_year(first_,no_check);
+ }
+ /**
+ * @Returns: the max valid value for a day of a year.
+ */
+ static BOOST_CONSTEXPR day_of_year max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return day_of_year(last_,no_check);
+ }
+ private:
+ rep value_;
+ };
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/days_date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/days_date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,518 @@
+// days_date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DAYS_DATE_HPP
+#define BOOST_CHRONO_DATE_DAYS_DATE_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/day_of_year.hpp>
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/week.hpp>
+#include <boost/chrono/date/tuples.hpp>
+#include <boost/chrono/date/config.hpp>
+#include <boost/chrono/date/conversions.hpp>
+#include <boost/chrono/date/optional_date.hpp>
+#include <boost/chrono/date/is_date.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class days_date is a model of Date storing
+ * - the number of @c days since an undetermined epoch.
+ */
+ class days_date
+ {
+ // Store x. Total 32 bits
+ boost::uint_least32_t x_;
+
+ public:
+ /**
+ * Effects: Constructs a @c days_date as if by @c year(0)/jan/1.
+ * Note: the purpose of this constructor is to have a very efficient means
+ * of @c days_date valid construction when the specific value for that @c days_date is unimportant.
+ */
+ days_date() BOOST_NOEXCEPT
+ : x_(11979588)
+ {
+ }
+
+ /**
+ * @Effect Constructs a @c days_date using the @c year, @c month, @c day stored in the arguments as follows:
+ * If the value stored in @c d is outside the range of valid dates for the month @c m and year @c y,
+ * throws an exception of type @c bad_date.
+ * Else constructs a @c days_date for which <c>get_year() == y && get_month() == m && get_day() == d</c>.
+ * @Throws bad_date if the specified days_date is invalid.
+ */
+ days_date(chrono::year y, chrono::month m, chrono::day d);
+ /**
+ * @Effect Constructs a @c days_date constructor from @c year, @c month, @c day stored in the arguments as follows:
+ * Constructs a @c days_date so that <c>get_year() == y && get_month() == m && get_day() == d</c>.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ days_date(year::rep y, month::rep m, day::rep d, no_check_t)
+BOOST_NOEXCEPT ;
+ /**
+ * @Effect Constructs a @c days_date using the @c year, @c month_day stored in the arguments as follows:
+ * If the value stored in @c md is outside the range of valid dates for the year @c y,
+ * throws an exception of type @c bad_date.
+ * Else constructs a @c days_date for which <c>get_year() == y && get_month() == md.get_month() && get_day() == md.get_day()</c>.
+ *
+ * @Throws @c bad_date if the specified @c days_date is invalid.
+ * @Note This constructor can be more efficient as the @c month_day is already valid.
+ */
+ days_date(chrono::year y, chrono::month_day md);
+ /**
+ * @Effect Constructs a @c days_date using the @c year, @c month_day stored in the arguments as follows:
+ * Constructs a @c days_date for which <c>get_year() == y && get_month() == md.get_month() && get_day() == md.get_day()</c>.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ days_date(chrono::year::rep, chrono::month_day, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a @c days_date using the @c year, @c day_of_year stored in the arguments as follows:
+ * If the value stored in @c doy is @c 366 and @c year.is_leap()
+ * throws an exception of type @c bad_date.
+ * Else constructs a @c days_date for which <c>days_since_epoch() == y.days_since_epoch()+doy.value()<c>
+ * @Throws @c bad_date if the specified @c days_date is invalid.
+ * @Note This constructor can be more efficient as the check is simpler.
+ */
+ days_date(chrono::year y, chrono::day_of_year doy);
+ /**
+ * @Effect Constructs a days_date using the year, day_of_year stored in the arguments as follows:
+ * Constructs a days_date for which days_since_epoch() == y.days_since_epoch()+doy.value()
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ days_date(year::rep y, day_of_year::rep doy, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a @c days_date using the @c days given as parameter so that:
+ * <c>days_since_epoch() == ds.count()</c>.
+ * @Throws @bad_date if the days is not in the range [11322,23947853].
+ */
+ explicit days_date(chrono::days d)
+ : x_(d.count())
+ {
+ if (!is_valid())
+ {
+ throw bad_date("days " + boost::chrono::to_string(d.count()) + " is out of range");
+ }
+ }
+
+ /**
+ * Unchecked constructor from @c days
+ * @Effect Constructs a @c days_date using the @c days given as parameter so that:
+ * <c>days_since_epoch() == ds.count()</c>.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ days_date(days::rep x, no_check_t) BOOST_NOEXCEPT
+ : x_(x)
+ {
+ }
+ /**
+ * @Effect Constructs a @c days_date constructor from @c year, @c month, @c day stored in the arguments as follows:
+ * Constructs a @c days_date so that <c>get_year() == y @@ get_month() = m && get_day() == d</c>.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ days_date(days::rep x, year::rep, month::rep, day::rep, bool, no_check_t) BOOST_NOEXCEPT
+ : x_(x)
+ {
+ }
+ /**
+ * @Effect Constructs a @c days_date constructor from @c year, @c month, @c day stored in the arguments as follows:
+ * Constructs a @c days_date so that <c>get_year() == y && get_month() = m && get_day() == d</c>.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ days_date(year::rep, month::rep, day::rep, bool, no_check_t) BOOST_NOEXCEPT;
+
+ // setters
+ /**
+ * @Effects Update the @c days_date if the parameters @c year, @c month, @c day represents a valid date.
+ * @Returns @c true if the parameters represents a valid date.
+ */
+ bool set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT;
+ /**
+ * @Effects Update the days_date if the parameters represents a valid date.
+ * @Returns @c true if the parameters represents a valid date.
+ */
+ bool set_if_valid_date(year y, day_of_year doy) BOOST_NOEXCEPT;
+ /**
+ * @Effects Update the days_date if the parameter represents a valid days_date.
+ * @Returns true if the parameters represents a valid days_date.
+ */
+ bool set_if_valid_date(days d) BOOST_NOEXCEPT;
+
+ // factories
+ /**
+ * @Return A days_date which represents the current day taking the local time zone into account.
+ */
+ static days_date today() BOOST_NOEXCEPT;
+
+
+ // Conversions
+ /**
+ * @Effects: @c tp is converted to UTC, and then truncated to 00:00:00 hours.
+ * A @c days_date is created which reflects this point in time.
+ * @Throws If the conversion from @c tp overflows the range of @c days_date, throws
+ * an exception of type @c bad_date.
+ *
+ */
+ explicit days_date(boost::chrono::system_clock::time_point tp);
+ /**
+ * @Returns: A chrono::system_clock::time_point which represents the @c days_date
+ * referred to by *this at 00:00:00 UTC.
+ *
+ * @Throws: If the conversion to @c tp overflows the range of
+ * boost::chrono::system_clock::time_point, throws an exception of type @c bad_date.
+ *
+ */
+ // explicit
+ operator boost::chrono::system_clock::time_point () const;
+
+
+ // Observers
+ /**
+ * @return @c true if the stored days are in the range [11322,23947853].
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return x_ >= 11322 && x_ <= 23947853;
+ }
+
+ /**
+ * @Returns: the number of days since an undefined epoch.
+ */
+ days days_since_epoch()
+ {
+ return days(x_);
+ }
+
+ /**
+ * Returns: <c>chrono::day(d_,no_check)</c>.
+ */
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(day_from_day_number(),no_check);
+ }
+ /**
+ * Returns: <c>chrono::month(m_,no_check)</c>.
+ */
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(month_from_day_number(),no_check);
+ }
+ /**
+ * Returns: <c>chrono::year(y_,no_check)</c>.
+ */
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(year_from_day_number(),no_check);
+ }
+ /**
+ * Returns: @c true if @c year() is a leap year, and @c false otherwise.
+ */
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_from_day_number();
+ }
+ /**
+ * @return the @c month_day built from the @c month and @c day associated to the date.
+ */
+ month_day get_month_day() const BOOST_NOEXCEPT;
+ /**
+ * @return the @c year_month built from the @c year and @c month associated to the date.
+ */
+ year_month get_year_month() const BOOST_NOEXCEPT;
+ /**
+ * @return the @c year_month_day built from the @c year, @c month and @c day associated to the date.
+ */
+ year_month_day get_year_month_day() const BOOST_NOEXCEPT;
+
+ /**
+ * @Returns: A weekday constructed with an int corresponding to *this
+ * days_date's day of the week (a value in the range of [0 - 6], 0 is Sunday).
+ */
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((x_ + 1) % weekday::size, no_check);
+ }
+
+ // Days Based Arithmetic
+ /**
+ * @Effects: Adds @c d.count() days to the current @c days_date.
+ * @Returns: <c>*this</c>.
+ * @Throws: If the addition would create a @c days_date with a year() outside of the
+ * range of @c year, throws an exception of type @c bad_date.
+ *
+ */
+ days_date& operator+=(days d);
+
+ /**
+ * @Effects: <c>*this += days(1)</c>.
+ * @Returns: <c>*this</c>.
+ */
+ days_date& operator++()
+ {
+ return *this += days(1);
+ }
+ /**
+ * @Effects: <c>*this += days(1)</c>.
+ * @Returns: A copy of @c *this prior to the increment.
+ */
+ days_date operator++(int)
+ {
+ days_date tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+ /**
+ * @Effects: <c>*this += -d</c>.
+ * @Returns: <c>*this</c>.
+ */
+ days_date& operator-=(days d)
+ {
+ return *this += -d;
+ }
+ /**
+ * @Effects: <c>*this -= days(1)</c>.
+ * @Returns: <c>*this</c>.
+ */
+ days_date& operator--()
+ {
+ return *this -= days(1);
+ }
+ /**
+ * @Effects: <c>*this -= days(1)</c>.
+ * @Returns: A copy of @c *this prior to the increment.
+ */
+ days_date operator--(int)
+ {
+ days_date tmp(*this); --(*this); return tmp;
+ }
+
+ /**
+ * @Returns: <c>dt += d</c>.
+ *
+ */
+ friend days_date operator+(days_date dt, days d)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: <c>dt += d</c>.
+ *
+ */
+ friend days_date operator+(days d, days_date dt)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: <c>dt -= d</c>.
+ *
+ */
+ friend days_date operator-(days_date dt, days d)
+ {
+ dt -= d;
+ return dt;
+ }
+ /**
+ * @Returns: Computes the number of days @c x is ahead of @c y in the calendar,
+ * and returns that signed integral number @c n as days(n).
+ */
+ friend days operator-(days_date x, days_date y) BOOST_NOEXCEPT
+ {
+ return x.days_since_epoch() - y.days_since_epoch();
+ }
+
+ // Month Based Arithmetic
+
+ /**
+ * @Effects Adds @c m.count() months to the current date.
+ * This is accomplished as if by storing temporary values of the days_date's @c year @c y_, @c month @c m_, @c day @c _d.
+ * Computing new values for @c y_ and @c m_ based on @c m. And then assigning to
+ * @c *this a new @c days_date constructed from the newly computed @c y_ and @c m_, and the
+ * original @c d_.
+ *
+ * @Returns: @c *this.
+ *
+ * @Throws: If the addition would create a @c days_date with a @c y_ outside of the
+ * range of @c year, or a @c d_ outside the range for the newly computed @c y_/@c m_,
+ * throws an exception of type @c bad_date.
+ *
+ */
+ days_date& operator+=(months m);
+
+ /**
+ * Returns: <c>*this += -m</c>.
+ */
+ days_date& operator-=(months m)
+ {
+ return *this += months(-m.count());
+ }
+
+ /**
+ * @Returns: <c>dt += m</c>.
+ *
+ */
+ friend days_date operator+(days_date dt, months m)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: <c>dt += m</c>.
+ *
+ */
+ friend days_date operator+(months m, days_date dt)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: <c>dt += -m</c>.
+ *
+ */
+ friend days_date operator-(days_date dt, months m)
+ {
+ dt -= m;
+ return dt;
+ }
+
+ // Years Based Arithmetic
+
+ /*
+ * @Effects: Adds @c y.count() years to the current date.
+ * This is accomplished as if by storing temporary values of the days_date's
+ * @c year @c y_, @c month @c m_, @c day @c d_. Computing a new value for @c y_. And then assigning to @c *this
+ * a new @c days_date constructed from the newly computed @c y_, and the original @c m_, @c d_.
+ * @Returns: @c *this.
+ * @Throws: If the addition would create a @c days_date with a @c y_ outside of the
+ * range of @c year, or a @c d_ outside the range for the newly computed @c y_/@c m_,
+ * throws an exception of type @c bad_date.
+ */
+ days_date& operator+=(years y);
+
+ /**
+ * @Returns: <c>*this += -y</c>.
+ *
+ */
+ days_date& operator-=(years y)
+ {
+ return *this += years(-y.count());
+ }
+
+ /**
+ * @Returns: <c>dt += y</c>.
+ *
+ */
+ friend days_date operator+(days_date dt, years y)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: <c>dt += y</c>.
+ *
+ */
+ friend days_date operator+(years y, days_date dt)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: <c>dt -= y</c>.
+ *
+ */
+ friend days_date operator-(days_date dt, years y)
+ {
+ dt -= y;
+ return dt;
+ }
+
+ // Relational operators
+ /**
+ * Returns: <c>x.days_since_epoch() == y.days_since_epoch()</c>.
+ */
+ friend bool operator==(const days_date& x, const days_date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ /**
+ * Returns: <c>x.days_since_epoch() < y.days_since_epoch()</c>.
+ */
+ friend bool operator< (const days_date& x, const days_date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+ /**
+ * @Returns: <c>!(x == y)</c>.
+ */
+ friend bool operator!=(const days_date& x, const days_date& y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ /**
+ * @Returns: <c>y < x</c>.
+ */
+ friend bool operator> (const days_date& x, const days_date& y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ /**
+ * @Returns: <c>!(y < x)</c>.
+ */
+ friend bool operator<=(const days_date& x, const days_date& y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ /**
+ * @Returns: <c>!(x < y)</c>.
+ */
+ friend bool operator>=(const days_date& x, const days_date& y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+
+ private:
+
+ day::rep day_from_day_number() const BOOST_NOEXCEPT;
+ month::rep month_from_day_number() const BOOST_NOEXCEPT;
+ year::rep year_from_day_number() const BOOST_NOEXCEPT;
+ bool leap_from_day_number() const BOOST_NOEXCEPT;
+ };
+
+ /**
+ * Partial specialization of @c is_date<days_date> as a true type.
+ */
+ template <>
+ struct is_date<days_date> : true_type {};
+
+ } // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/detail/helpers.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/detail/helpers.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,61 @@
+// days_date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_HELPERS_HPP
+#define BOOST_CHRONO_DATE_HELPERS_HPP
+
+#include <boost/cstdint.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ typedef boost::int_least8_t day_rep;
+ typedef boost::int_least64_t days_rep;
+ typedef boost::int_least8_t month_rep;
+ typedef boost::int_least16_t day_of_year_rep;
+ typedef boost::int_least32_t year_rep;
+
+ inline bool
+ is_leap(year_rep y)
+ BOOST_NOEXCEPT
+ {
+ return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
+ }
+
+ inline days_rep days_before_year(year_rep y)
+ {
+ return y * 365 + y / 4 - y / 100 + y / 400;
+ }
+
+ inline year_rep
+ to_average_year(days_rep ds)
+ BOOST_NOEXCEPT
+ {
+ return static_cast<year_rep>(static_cast<int64_t>(ds+2) * 400 / 146097);
+ }
+
+ day_rep days_in_month(bool, month_rep)
+ BOOST_NOEXCEPT;
+ day_of_year_rep days_in_year_before(bool, month_rep)
+ BOOST_NOEXCEPT;
+ const day_of_year_rep* days_in_year_before(bool)
+ BOOST_NOEXCEPT;
+ month_rep day_of_year_month(bool, day_of_year_rep)
+ BOOST_NOEXCEPT;
+ day_rep day_of_year_day_of_month(bool, day_of_year_rep)
+ BOOST_NOEXCEPT;
+ day_of_year_rep month_day_to_day_of_year(bool, month_rep, day_rep)
+BOOST_NOEXCEPT ;
+
+} // chrono
+} // boost
+
+#endif
+

Added: sandbox/chrono_date/boost/chrono/date/detail/to_string.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/detail/to_string.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,27 @@
+// date_io.hpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DETAIL_TO_STRING_HPP
+#define BOOST_CHRONO_DETAIL_TO_STRING_HPP
+
+#include <boost/lexical_cast.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+ template <typename T>
+ std::string to_string(T const&v) {
+ return lexical_cast<std::string>(v);
+ }
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/exceptions.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/exceptions.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,55 @@
+// exceptions.hpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_EXCEPTIONS_HPP
+#define BOOST_CHRONO_DATE_DATE_EXCEPTIONS_HPP
+
+
+#include <exception>
+#include <stdexcept>
+
+
+namespace boost
+{
+ namespace chrono
+ {
+
+
+ /**
+ * The class @c bad_date is thrown when an exceptional condition is created
+ * within the chrono library.
+ */
+ class bad_date: public std::runtime_error
+ {
+ public:
+ /*
+ * @Effects: Constructs an object of class @c bad_date.
+ * @Postcondition: <c>what() == s</c>.
+ */
+ explicit bad_date(const std::string& s) :
+ std::runtime_error(s)
+ {
+ }
+
+ /**
+ * @Effects: Constructs an object of class @c bad_date.
+ * @Postcondition: <c>strcmp(what(), s) == 0</c>.
+ */
+ explicit bad_date(const char* s) :
+ std::runtime_error(s)
+ {
+ }
+ };
+
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/include.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/include.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,316 @@
+// date --------------------------------------------------------------//
+
+// Copyright 2011 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_CHRONO_DATE_INCLUDE_HPP
+#define BOOST_CHRONO_DATE_INCLUDE_HPP
+
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+
+#include <boost/chrono/date/date_durations.hpp>
+
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/month_nth.hpp>
+#include <boost/chrono/date/month_nth_weekday.hpp>
+#include <boost/chrono/date/week.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/nth_week.hpp>
+#include <boost/chrono/date/nth_weekday.hpp>
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/day_of_year.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/tuples.hpp>
+#include <boost/chrono/date/conversions.hpp>
+
+#include <boost/chrono/date/date.hpp>
+#include <boost/chrono/date/days_date.hpp>
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/date/date_generators.hpp>
+
+#include <boost/chrono/date/relative_date.hpp>
+
+
+/*
+ date synopsis
+
+ namespace boost
+ {
+ namespace chrono
+ {
+
+ // A date
+ class date
+ {
+ public:
+ static date today();
+
+ // system_clock::time_point conversions
+ explicit date(boost::chrono::system_clock::time_point tp);
+ explicit operator boost::chrono::system_clock::time_point () const;
+
+ // obervers
+ day get_day() const noexcept;
+ month get_month() const noexcept;
+ year get_year() const noexcept;
+ weekday get_weekday() const noexcept;
+ bool is_leap_year() const noexcept;
+
+ // day arithmetic
+ date& operator+=(days d);
+ date& operator++();
+ date operator++(int);
+ date& operator-=(days d);
+ date& operator--();
+ date operator--(int);
+
+ // month arithmetic
+ date& operator+=(months m);
+ date& operator-=(months m);
+
+ // year arithmetic
+ date& operator+=(years y);
+ date& operator-=(years y);
+ };
+
+ // date relational
+ bool operator==(const date& x, const date& y) noexcept;
+ bool operator!=(const date& x, const date& y) noexcept;
+ bool operator< (const date& x, const date& y) noexcept;
+ bool operator> (const date& x, const date& y) noexcept;
+ bool operator<=(const date& x, const date& y) noexcept;
+ bool operator>=(const date& x, const date& y) noexcept;
+
+ // date day arithmetic
+ date operator+(date dt, days d);
+ date operator+(days d, date dt);
+ date operator-(date dt, days d);
+ days operator-(date x, date y) noexcept;
+
+ // date month arithmetic
+ date operator+(date dt, months m);
+ date operator+(months m, date dt);
+ date operator-(date dt, months m);
+
+ // date year arithmetic
+ date operator+(date dt, years y);
+ date operator+(years y, date dt);
+ date operator-(date dt, years y);
+
+ // Specifiers
+
+ // A year specifier
+ class year
+ {
+ public:
+ explicit year(std::int16_t y);
+ operator int() const noexcept;
+ };
+
+ // A month specifier
+ class month
+ {
+ public:
+ explicit month(int);
+ operator int() const noexcept;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ // A day specifier
+ class day
+ {
+ public:
+ explicit day(int);
+ day(__unnamed) noexcept;
+ operator int() const noexcept;
+ };
+
+ // A day of the week specifier
+ class weekday
+ {
+ public:
+ explicit weekday(int);
+ operator int() const noexcept;
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ // A year + month specifier
+ class year_month
+ {
+ // no public members
+ };
+
+ // A month + day specifier
+ class month_day
+ {
+ // no public members
+ };
+
+ class __unnamed
+ {
+ // no public members
+ };
+
+ extern const __unnamed _1st;
+ extern const __unnamed _2nd;
+ extern const __unnamed _3rd;
+ extern const __unnamed _4th;
+ extern const __unnamed _5th;
+ extern const __unnamed last;
+
+ // Date generation functions
+
+ date operator/(year_month, day); // year(2011)/month(8)/day(19)
+ date operator/(month_day, year); // month(8)/day(19)/year(2011)
+ // day(19)/month(8)/year(2011)
+
+ year_month operator/(year, month) noexcept; // year(2011)/month(8)
+
+ month_day operator/(day, month) noexcept; // day(19)/month(8)
+ month_day operator/(month, day) noexcept; // month(8)/day(19)
+
+ // Date durations
+
+ typedef duration<int_least32_t, ratio<86400>> days;
+
+ days operator+(days x, days y);
+ days operator-(days x, days y);
+ days operator*(days x, days::rep y);
+ days operator*(days::rep x, days y);
+ days operator/(days x, days::rep y);
+ days::rep operator/(days x, days y);
+ days operator%(days x, days::rep y);
+ days operator%(days x, days y);
+
+ bool operator==(days x, days y);
+ bool operator!=(days x, days y);
+ bool operator< (days x, days y);
+ bool operator> (days x, days y);
+ bool operator<=(days x, days y);
+ bool operator>=(days x, days y);
+
+ class months
+ {
+ public:
+ typedef std::int32_t rep;
+ months() = default;
+ explicit months(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ months operator+() const noexcept;
+ months operator-() const noexcept;
+
+ months& operator++() noexcept;
+ months operator++(int) noexcept;
+ months& operator--() noexcept;
+ months operator--(int) noexcept;
+
+ months& operator+=(const months& x) noexcept;
+ months& operator-=(const months& x) noexcept;
+
+ months& operator*=(const rep& rhs) noexcept;
+ months& operator/=(const rep& rhs) noexcept;
+ months& operator%=(const rep& rhs) noexcept;
+ months& operator%=(const months& rhs) noexcept;
+ };
+
+ months operator+(months x, months y) noexcept;
+ months operator-(months x, months y) noexcept;
+ months operator*(months x, months::rep y) noexcept;
+ months operator*(months::rep x, months y) noexcept;
+ months operator/(months x, months::rep y) noexcept;
+ months::rep operator/(months x, months y) noexcept;
+ months operator%(months x, months::rep y) noexcept;
+ months operator%(months x, months y) noexcept;
+
+ bool operator==(months x, months y) noexcept;
+ bool operator!=(months x, months y) noexcept;
+ bool operator< (months x, months y) noexcept;
+ bool operator> (months x, months y) noexcept;
+ bool operator<=(months x, months y) noexcept;
+ bool operator>=(months x, months y) noexcept;
+
+ class years
+ {
+ public:
+ typedef std::int32_t rep;
+ years() = default;
+ explicit years(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ years operator+() const noexcept;
+ years operator-() const noexcept;
+
+ years& operator++() noexcept;
+ years operator++(int) noexcept;
+ years& operator--() noexcept;
+ years operator--(int) noexcept;
+
+ years& operator+=(const years& x) noexcept;
+ years& operator-=(const years& x) noexcept;
+
+ years& operator*=(const rep& rhs) noexcept;
+ years& operator/=(const rep& rhs) noexcept;
+ years& operator%=(const rep& rhs) noexcept;
+ years& operator%=(const years& rhs) noexcept;
+ };
+
+ years operator+(years x, years y) noexcept;
+ years operator-(years x, years y) noexcept;
+ years operator*(years x, years::rep y) noexcept;
+ years operator*(years::rep x, years y) noexcept;
+ years operator/(years x, years::rep y) noexcept;
+ years::rep operator/(years x, years y) noexcept;
+ years operator%(years x, years::rep y) noexcept;
+ years operator%(years x, years y) noexcept;
+
+ bool operator==(years x, years y) noexcept;
+ bool operator!=(years x, years y) noexcept;
+ bool operator< (years x, years y) noexcept;
+ bool operator> (years x, years y) noexcept;
+ bool operator<=(years x, years y) noexcept;
+ bool operator>=(years x, years y) noexcept;
+
+ date operator< (weekday wd, date x) noexcept;
+ date operator<=(weekday wd, date x) noexcept;
+ date operator> (weekday wd, date x) noexcept;
+ date operator>=(weekday wd, date x) noexcept;
+
+ class bad_date
+ : public std::exception
+ {
+ public:
+ virtual const char* what() const noexcpt();
+ };
+
+ } // chrono
+ } // std
+
+ */
+#endif // BOOST_CHRONO_DATE_INCLUDE_HPP

Added: sandbox/chrono_date/boost/chrono/date/is_date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/is_date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,33 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_IS_DATE_HPP
+#define BOOST_CHRONO_DATE_IS_DATE_HPP
+
+
+#include <boost/chrono/date/config.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /*
+ * Trait type for Date classes.
+ */template <typename Date>
+ struct is_date : false_type {};
+
+
+ } // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/month.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/month.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,149 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_MONTH_HPP
+#define BOOST_CHRONO_DATE_DATE_MONTH_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class @c month is used to specify the month of the year when constructing a date.
+ */
+ class month
+ {
+ public:
+ typedef int_least8_t rep;
+ static const rep last_ = 12;
+ static const rep first_ = 1;
+ static const std::size_t size = last_ - first_ + 1; // 4 bits
+
+ /**
+ * @Effects: Constructs an object of class @c month by storing @c m.
+ * @Postconditions: <c>value() == m && is_valid()</c>.
+ * @Throws: if @c m is outside of the range [1, 12], throws an exception of type @c bad_date.
+ */
+ BOOST_CONSTEXPR explicit month(rep v) :
+ value_(v)
+ {
+ if (!(is_valid()))
+ {
+ throw bad_date("month " + boost::chrono::to_string(int(v))
+ + " is out of range");
+ }
+ }
+ /**
+ * @Effects: Constructs an object of class @c month by storing @c m.
+ * @Postconditions: value() == m.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ explicit month(rep m, no_check_t) :
+ value_(m)
+ {
+ }
+
+ /**
+ * @Return if the stored value is a valid one, i.e. on the range [1, 12].
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+
+ /**
+ * @Returns: the value of the stored int.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Returns: the value of the stored int.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ month next() const BOOST_NOEXCEPT
+ {
+ return month(((value_-first_+1)%size)+first_,no_check);
+ }
+ month prev()BOOST_NOEXCEPT
+ {
+ return month(((value_-first_+size-1)%size)+first_,no_check);
+ }
+ static BOOST_CONSTEXPR month first()
+ {
+ return month(first_,no_check);
+ }
+ static BOOST_CONSTEXPR month last()
+ {
+ return month(last_,no_check);
+ }
+ static BOOST_CONSTEXPR month min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return month(first_,no_check);
+ }
+ static BOOST_CONSTEXPR month max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return month(last_,no_check);
+ }
+
+ // friend class date;
+ // friend class rel_date;
+ private:
+ rep value_;
+
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ inline std::string to_string(month v) {
+ switch (v) {
+ case 1: return "Jan";
+ case 2: return "Feb";
+ case 3: return "Mar";
+ case 4: return "Apr";
+ case 5: return "May";
+ case 6: return "Jun";
+ case 7: return "Jul";
+ case 8: return "Aug";
+ case 9: return "Sep";
+ case 10: return "Oct";
+ case 11: return "Nov";
+ case 12: return "Dec";
+ default: throw bad_date("month " + boost::chrono::to_string(int(v)) + " is out of range");
+
+ }
+ }
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/month_nth.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/month_nth.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,153 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_MONTH_NTH_HPP
+#define BOOST_CHRONO_DATE_MONTH_NTH_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class @c month_nth is a tuple of @c month and @c nth that is useful when constructing dates.
+ */
+ class month_nth
+ {
+ month m_; // :4
+ nth d_; // :6
+ public:
+ /**
+ * @Effects: Constructs an object of class @c month_nth by storing @c m and @c d.
+ * @Postconditions: get_month() == m && get_nth() == d && is_valid().
+ * @Throws: if d is outside of the valid range of days of month @c m, throws an exception of type bad_date.
+ */
+ month_nth(month m, nth d)BOOST_NOEXCEPT
+ : m_(m),
+ d_(d)
+ {
+ if (!(d_<= days_in_month(1,m_)))
+ {
+ throw bad_date("nth " + boost::chrono::to_string(int(d)) + "is out of range respect to month" + boost::chrono::to_string(m));
+ }
+ }
+ /**
+ * @Effects: Constructs an object of class @c month_nth by storing @c m and @c d.
+ * @Postconditions: get_month() == m && get_nth() == d.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ month_nth(month::rep m, nth::rep d, no_check_t)BOOST_NOEXCEPT
+ : m_(m),
+ d_(d)
+ {
+ }
+ /**
+ * @Return the @c month component.
+ */
+ month get_month() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+ /**
+ * @Return the @c nth component.
+ */
+ nth get_nth() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+ /**
+ * @Return if the stored value is a valid one.
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (m_.is_valid() && d_.is_valid() && d_<= days_in_month(1,m_));
+ }
+ };
+ /**
+ * @Return a the @c month_nth with the associated parameters.
+ * @Throws if d is outside of the valid range of days of month @c m, throws an exception of type bad_date.
+ */
+ inline month_nth operator/(month m, nth d)
+ BOOST_NOEXCEPT
+ {
+ return month_nth(m, d);
+ }
+ inline month_nth operator/(month m, last_t)
+ BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(6,no_check));
+ }
+ inline month_nth operator/(month m, _1st_t) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(1,no_check));
+ }
+ inline month_nth operator/(month m, _2nd_t) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(2,no_check));
+ }
+ inline month_nth operator/(month m, _3rd_t) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(3,no_check));
+ }
+ inline month_nth operator/(month m, _4th_t) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(4,no_check));
+ }
+ inline month_nth operator/(month m, _5th_t) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(5,no_check));
+ }
+ /**
+ * @Return a the @c month_nth with the associated parameters.
+ * @Throws if d is outside of the valid range of days of month @c m, throws an exception of type bad_date.
+ */
+ inline month_nth operator/(nth d, month m)
+BOOST_NOEXCEPT {
+ return month_nth(m, d);
+ }
+ inline month_nth operator/(last_t, month m)
+BOOST_NOEXCEPT {
+ return month_nth(m, nth(6,no_check));
+ }
+
+ inline month_nth operator/(_1st_t, month m) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(1,no_check));
+ }
+ inline month_nth operator/(_2nd_t, month m) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(2,no_check));
+ }
+ inline month_nth operator/(_3rd_t, month m) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(3,no_check));
+ }
+ inline month_nth operator/(_4th_t, month m) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(4,no_check));
+ }
+ inline month_nth operator/(_5th_t, month m) BOOST_NOEXCEPT
+ {
+ return month_nth(m, nth(5,no_check));
+ }
+
+
+} // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/month_nth_weekday.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/month_nth_weekday.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,157 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_MONTH_NTH_WEEKDAY_HPP
+#define BOOST_CHRONO_DATE_MONTH_NTH_WEEKDAY_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/nth_week.hpp>
+#include <boost/chrono/date/nth_weekday.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class @c month_nth_weekday is a tuple of @c month and @c nth_weekday that is useful when constructing dates.
+ */
+ class month_nth_weekday
+ {
+ month m_; // :4
+ nth_weekday d_; // :6
+ public:
+ /**
+ * @Effects: Constructs an object of class @c month_nth_weekday by storing @c m and @c nwd.
+ * @Postconditions: get_month() == m && get_nth_weekday() == nwd && is_valid().
+ */
+ month_nth_weekday(month m, nth_weekday nwd) BOOST_NOEXCEPT
+ : m_(m),
+ d_(nwd)
+ {
+ // There is no bad combination, so no exception is thrown
+ }
+ /**
+ * @Effects: Constructs an object of class @c month_nth_weekday by storing @c m and @c nwd.
+ * @Postconditions: get_month() == m && get_nth_weekday() == nwd.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ month_nth_weekday(month::rep m, nth_weekday d, no_check_t) BOOST_NOEXCEPT
+ : m_(m),
+ d_(d)
+ {
+ }
+ /**
+ * @Return the @c month component.
+ */
+ month get_month() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+ /**
+ * @Return the @c nth_weekday component.
+ */
+ nth_weekday get_nth_weekday() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+ /**
+ * @Return if the stored value is a valid one.
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return ( m_.is_valid() && d_.is_valid() );
+ }
+ };
+
+ /**
+ * @return a @c month_nth_weekday build with the given parameters.
+ */
+ inline month_nth_weekday operator/(month m, nth_weekday d) BOOST_NOEXCEPT
+ {
+ return month_nth_weekday(m, d);
+ }
+ /**
+ * @return a @c month_nth_weekday build with the given parameters.
+ */
+ inline month_nth_weekday operator/(nth_weekday d, month m) BOOST_NOEXCEPT
+ {
+ return month_nth_weekday(m, d);
+ }
+
+ /**
+ *
+ * The class dom is used to specify a small integral value that indicates the nth day of the month (example: last, 1st).
+ * valid from -32..31,
+ * 1..31 means the nth day of the month,
+ * 0 means last and
+ * -30..-1 means last but -nth.
+ * -32 means not_applicable
+ */
+ class dom
+ {
+ public:
+ typedef int_least8_t rep;
+ static const rep not_applicable=-31;
+
+ dom(rep s) BOOST_NOEXCEPT : value_(s)
+ {
+ }
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ bool is_not_applicable() const BOOST_NOEXCEPT
+ {
+ return value_==not_applicable;
+ }
+ private:
+ rep value_; // :6 bits
+ };
+
+ class month_dom
+ {
+ month m_; // :4
+ dom d_; // :6
+ public:
+ month_dom(month m, dom d) BOOST_NOEXCEPT
+ : m_(m),
+ d_(d)
+ {
+ }
+ month get_month() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+ dom get_dom() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+ };
+
+ inline month_dom operator/(month m, dom d) BOOST_NOEXCEPT
+ {
+ return month_dom(m, d);
+ }
+ inline month_dom operator/(dom d, month m) BOOST_NOEXCEPT
+ {
+ return month_dom(m, d);
+ }
+
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/no_check.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/no_check.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,27 @@
+// date
+//
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_NO_CHECK_HPP
+#define BOOST_CHRONO_DATE_DATE_NO_CHECK_HPP
+
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ struct no_check_t
+ {};
+ const no_check_t no_check =
+ {};
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/nth.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/nth.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,98 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_NTH_HPP
+#define BOOST_CHRONO_DATE_NTH_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class nth is used to specify a small integral value that indicates the nth day of the month (example: last, 1st).
+ */
+ class nth
+ {
+ public:
+ typedef int_least8_t rep;
+ static const rep not_applicable=7;
+ //static const rep not_applicable=-32;
+ static const rep last_=31;
+ static const rep first_=-32;
+ //static const rep last_=6;
+ //static const rep first_=1;
+ static const std::size_t size=last_-first_+1; // :3 bits
+
+ nth(rep s) BOOST_NOEXCEPT
+ : value_(s)
+ {
+ if (!is_valid())
+ {
+ throw bad_date("day " + boost::chrono::to_string(int(s)) + " is out of range");
+ }
+ }
+ nth(rep s, no_check_t) BOOST_NOEXCEPT
+ : value_(s)
+ {
+ }
+
+ /**
+ * @Return The nth stored component.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Return The nth stored component.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Return if the stored value is a valid one.
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+ bool is_not_applicable() const BOOST_NOEXCEPT
+ {
+ return value_==not_applicable;
+ }
+ private:
+ rep value_; // 3 bits if only valid up to _5th
+ };
+
+ struct last_t {};
+ const last_t last = {};
+ struct _1st_t {};
+ const _1st_t _1st = {};
+ struct _2nd_t {};
+ const _2nd_t _2nd = {};
+ struct _3rd_t {};
+ const _3rd_t _3rd = {};
+ struct _4th_t {};
+ const _4th_t _4th = {};
+ struct _5th_t {};
+ const _5th_t _5th = {};
+
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/nth_week.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/nth_week.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,98 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_NTH_WEEK_HPP
+#define BOOST_CHRONO_DATE_NTH_WEEK_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class nth_week is used to specify a small integral value that indicates the nth week of the year (example: last_week, 1st_week).
+ */
+ class nth_week
+ {
+ public:
+ typedef int_least8_t rep;
+ static const rep not_applicable=7;
+ static const rep last_=6;
+ static const rep first_=1;
+ static const std::size_t size=last_-first_+1; // :5 bits
+
+ /**
+ * @Effects: Constructs an object of class @c nth_week by storing @c s.
+ * Throws: if @c s is outside of the range [1, 6], throws an exception of type bad_date.
+ */
+ nth_week(rep s) : value_(s)
+ {
+ if (!is_valid())
+ {
+ throw bad_date("day " + boost::chrono::to_string(int(s)) + " is out of range");
+ }
+ }
+ /**
+ * @Effects: Constructs an object of class @c nth_week by storing @c s.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ nth_week(rep s, no_check_t) BOOST_NOEXCEPT
+ : value_(s)
+ {
+ }
+ /**
+ * @Return The nth week stored component.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Return The nth stored component.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+
+ /**
+ * @Return if the stored value is a valid one, i.e. in the range [1,6].
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+ bool is_not_applicable() const BOOST_NOEXCEPT
+ {
+ return value_==not_applicable;
+ }
+ private:
+ rep value_; // 3 bits if only valid up to _5th
+ };
+
+// extern const nth_week last_week;
+// extern const nth_week _1st_week;
+// extern const nth_week _2nd_week;
+// extern const nth_week _3rd_week;
+// extern const nth_week _4th_week;
+// extern const nth_week _5th_week;
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/nth_weekday.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/nth_weekday.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,167 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_NTH_WEEKDAY_HPP
+#define BOOST_CHRONO_DATE_NTH_WEEKDAY_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/nth_week.hpp>
+#include <boost/chrono/date/no_check.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class nth_weekday is used to specify the nth weekday of a month (example: 2nd Sunday).
+ */
+ class nth_weekday
+ {
+ nth_week n_; // :3
+ weekday dow_; // :3
+
+ public:
+ /**
+ * @param n the nth week
+ * @param dow the day of the year
+ * @Effects: Constructs a pair of nth-weekday.
+ * Throws: if nth.value() is outside of the range [1, 5], throws an exception of type bad_date.
+ */
+ nth_weekday(nth_week n, weekday dow) BOOST_NOEXCEPT
+ :
+ n_(n),
+ dow_(dow)
+ {
+ // No invalid condition
+ }
+ /**
+ * @param n the nth week
+ * @param dow the day of the year
+ * @param tag to state that no check is performed.
+ * @Effects: Constructs a pair of nth-weekday.
+ * @Note This function doesn't check the parameters validity.
+ * It is up to the user to provide a valid ones.
+ */
+ nth_weekday(nth_week::rep n, weekday::rep dow, no_check_t) BOOST_NOEXCEPT
+ :
+ n_(n),
+ dow_(dow)
+ {
+ }
+
+ /**
+ * @Return if the stored value is a valid one.
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (n_.is_valid() && dow_.is_valid());
+ }
+ /**
+ * @Return The nth stored component.
+ */
+ nth_week get_nth() const BOOST_NOEXCEPT
+ {
+ return n_;
+ }
+ /**
+ * @Return The weekday stored component.
+ */
+ weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return dow_;
+ }
+ };
+
+ /**
+ *
+ * @param nw the nth week
+ * @param wd the weekday
+ * @return a nth_weekday with the given parameters
+ */
+ inline nth_weekday operator*(nth_week nw, weekday wd) BOOST_NOEXCEPT
+ {
+ return nth_weekday(nw, wd);
+ }
+
+ inline nth_weekday operator*(last_t, weekday wd) BOOST_NOEXCEPT
+ {
+ return nth_weekday(nth_week(6,no_check), wd);
+ }
+ inline nth_weekday operator*(_1st_t, weekday wd) BOOST_NOEXCEPT
+ {
+ return nth_weekday(nth_week(1,no_check), wd);
+ }
+ inline nth_weekday operator*(_2nd_t, weekday wd) BOOST_NOEXCEPT
+ {
+ return nth_weekday(nth_week(2,no_check), wd);
+ }
+ inline nth_weekday operator*(_3rd_t, weekday wd) BOOST_NOEXCEPT
+ {
+ return nth_weekday(nth_week(3,no_check), wd);
+ }
+ inline nth_weekday operator*(_4th_t, weekday wd) BOOST_NOEXCEPT
+ {
+ return nth_weekday(nth_week(4,no_check), wd);
+ }
+ inline nth_weekday operator*(_5th_t, weekday wd) BOOST_NOEXCEPT
+ {
+ return nth_weekday(nth_week(5,no_check), wd);
+ }
+
+ extern const nth_weekday last_sun;
+ extern const nth_weekday last_mon;
+ extern const nth_weekday last_tue;
+ extern const nth_weekday last_wed;
+ extern const nth_weekday last_thu;
+ extern const nth_weekday last_fri;
+ extern const nth_weekday last_sat;
+ extern const nth_weekday _1st_sun;
+ extern const nth_weekday _1st_mon;
+ extern const nth_weekday _1st_tue;
+ extern const nth_weekday _1st_wed;
+ extern const nth_weekday _1st_thu;
+ extern const nth_weekday _1st_fri;
+ extern const nth_weekday _1st_sat;
+ extern const nth_weekday _2nd_sun;
+ extern const nth_weekday _2nd_mon;
+ extern const nth_weekday _2nd_tue;
+ extern const nth_weekday _2nd_wed;
+ extern const nth_weekday _2nd_thu;
+ extern const nth_weekday _2nd_fri;
+ extern const nth_weekday _2nd_sat;
+ extern const nth_weekday _3rd_sun;
+ extern const nth_weekday _3rd_mon;
+ extern const nth_weekday _3rd_tue;
+ extern const nth_weekday _3rd_wed;
+ extern const nth_weekday _3rd_thu;
+ extern const nth_weekday _3rd_fri;
+ extern const nth_weekday _3rd_sat;
+ extern const nth_weekday _4th_sun;
+ extern const nth_weekday _4th_mon;
+ extern const nth_weekday _4th_tue;
+ extern const nth_weekday _4th_wed;
+ extern const nth_weekday _4th_thu;
+ extern const nth_weekday _4th_fri;
+ extern const nth_weekday _4th_sat;
+ extern const nth_weekday _5th_sun;
+ extern const nth_weekday _5th_mon;
+ extern const nth_weekday _5th_tue;
+ extern const nth_weekday _5th_wed;
+ extern const nth_weekday _5th_thu;
+ extern const nth_weekday _5th_fri;
+ extern const nth_weekday _5th_sat;
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/optional_date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/optional_date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,50 @@
+// date_generators.hpp
+//
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_OPTIONAL_DATE_HPP
+#define BOOST_CHRONO_DATE_OPTIONAL_DATE_HPP
+
+#include <boost/chrono/date/config.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/day_of_year.hpp>
+#include <boost/optional.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * @Returns If the parameters represents a valid Date the Date,
+ * otherwise a none optional.
+ */
+
+ template < typename Date>
+ optional<Date> make_optional(year y, month m, day d)
+ BOOST_NOEXCEPT
+ {
+ Date res;
+ if (res.set_if_valid_date(y,m,d)) return optional<Date>(res);
+ else return optional<Date>();
+ }
+
+ template < typename Date>
+ optional<Date> make_optional(year y, day_of_year doy)
+ BOOST_NOEXCEPT
+ {
+ Date res;
+ if (res.set_if_valid_date(y,doy)) return optional<Date>(res);
+ else return optional<Date>();
+ }
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/relative_date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/relative_date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,397 @@
+// rel_date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_RELATIVE_DATE_HPP
+#define BOOST_CHRONO_DATE_RELATIVE_DATE_HPP
+
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/date.hpp>
+#include <boost/chrono/date/nth_weekday.hpp>
+#include <boost/chrono/date/month_nth_weekday.hpp>
+#include <boost/chrono/date/month_nth.hpp>
+#include <boost/chrono/date/nth_week.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/days_date.hpp>
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/ydoy_date.hpp>
+#include <boost/chrono/date/is_date.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+
+ /**
+ * The class @c rel_date is a model of Date storing
+ * - the @c year,
+ * - the @c month,
+ * - the @c day of the month
+ * and optionally
+ * - the number of @c days since an undetermined epoch.
+ * - whether the year is leap or not.
+ */
+ class rel_date
+ {
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+ // Store x, y/m/d, n, dow. Total 64 bits
+ uint_least32_t x_;
+ int_least16_t y_;
+
+ uint_least8_t m_ : 4;
+ uint_least8_t leap_ : 1;
+ uint_least8_t dow_ : 3;
+
+ uint_least8_t d_ : 5; // :5
+ uint_least8_t n_ : 3; // :3
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+ // Store x, n, dow. Total 64 bits
+ uint_least32_t x_;
+ uint_least8_t n_ :5;
+ uint_least8_t dow_ :3;
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+ // Store y/m/d, n, dow. Total 32 bits
+ int_least16_t y_;
+ uint_least8_t m_ : 4;
+ uint_least8_t leap_ : 1;
+ uint_least8_t dow_ : 3;
+ uint_least8_t d_ : 5;
+ uint_least8_t n_ : 3;
+#endif
+
+ public:
+
+ /**
+ * Effects: Constructs a @c rel_date as if by @c year(0)/jan/1.
+ * Note: the purpose of this constructor is to have a very efficient means
+ * of @c rel_date valid construction when the specific value for that @c days_date is unimportant.
+ */
+ rel_date() BOOST_NOEXCEPT;
+ rel_date(chrono::year, chrono::month, chrono::nth_weekday);
+ rel_date(chrono::year::rep, chrono::month::rep, chrono::nth_weekday, no_check_t)BOOST_NOEXCEPT;
+ rel_date(chrono::year, chrono::month, chrono::nth);
+ rel_date(chrono::year::rep, chrono::month::rep, chrono::nth, no_check_t)BOOST_NOEXCEPT;
+#if BOOST_CHRONO_DATE_REL_DATE_IS_A_MODEL_OF_DATE
+ rel_date(chrono::year, chrono::month, chrono::day); // TODO
+ rel_date(chrono::year::rep, chrono::month::rep, chrono::day::rep, no_check_t)BOOST_NOEXCEPT;// TODO
+ rel_date(chrono::year y, chrono::month_day md);// TODO
+ rel_date(chrono::year::rep, chrono::month_day, no_check_t) BOOST_NOEXCEPT;// TODO
+
+ explicit rel_date(chrono::days d);// TODO
+
+ rel_date(chrono::year y, chrono::day_of_year doy);// TODO
+ rel_date(year::rep y, day_of_year::rep doy, no_check_t) BOOST_NOEXCEPT;// TODO
+
+ bool set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT;// TODO
+ bool set_if_valid_date(year y, day_of_year doy) BOOST_NOEXCEPT;// TODO
+ bool set_if_valid_date(days d) BOOST_NOEXCEPT;// TODO
+
+ static rel_date today() BOOST_NOEXCEPT;// TODO
+
+ explicit rel_date(boost::chrono::system_clock::time_point tp);// TODO
+ // explicit
+ operator boost::chrono::system_clock::time_point () const;// TODO
+
+#endif
+ // conversions
+ //explicit rel_date(ymd_date dt);
+ operator ymd_date() const;
+ //explicit rel_date(days_date dt);
+ operator days_date() const;
+ //explicit rel_date(ydoy_date dt);
+ operator ydoy_date() const;
+
+ // observers
+ //bool is_valid() const BOOST_NOEXCEPT;
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ std::cout << "KKKKKKKKKKKKK" << std::endl;
+ if (d_!=0)
+ return chrono::day(d_,no_check);
+ else {
+ std::cout << "KKKKKKKKKKKKK" << std::endl;
+ return chrono::day(d_,no_check);
+ }
+
+ }
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(m_,no_check);
+ }
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(y_,no_check);
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_;
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(day_from_day_number(),no_check);
+ }
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(month_from_day_number(),no_check);
+ }
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(year_from_day_number(),no_check);
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_from_day_number();
+ }
+#endif
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((x_+1) % weekday::size,no_check);
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((day_number_from_ymd()+1) % weekday::size,no_check);
+ }
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+ days days_since_epoch() const
+ {
+ return days(x_);
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+ days days_since_epoch() const
+ {
+ return days(day_number_from_ymd());
+ }
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_IS_A_MODEL_OF_DATE
+
+ rel_date& operator+=(days d);
+ rel_date& operator++()
+ {
+ return *this += days(1);
+ }
+ rel_date operator++(int)
+ {
+ rel_date tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+ rel_date& operator-=(days d)
+ {
+ return *this += -d;
+ }
+ rel_date& operator--()
+ {
+ return *this -= days(1);
+ }
+ rel_date operator--(int)
+ {
+ rel_date tmp(*this);
+ --(*this); return tmp;
+ }
+
+ friend rel_date operator+(rel_date dt, days d)
+ {
+ dt += d;
+ return dt;
+ }
+ friend rel_date operator+(days d, rel_date dt)
+ {
+ dt += d;
+ return dt;
+ }
+ friend rel_date operator-(rel_date dt, days d)
+ {
+ dt -= d;
+ return dt;
+ }
+#endif
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+ friend days operator-(rel_date x, rel_date y) BOOST_NOEXCEPT
+ {
+ return x.days_since_epoch() - y.days_since_epoch();
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+ friend days operator-(rel_date x, rel_date y) BOOST_NOEXCEPT
+ {
+ return x.days_since_epoch() - y.days_since_epoch();
+ }
+#endif
+ friend days operator-(rel_date x, ymd_date y) BOOST_NOEXCEPT
+ {
+ return x.days_since_epoch() - y.days_since_epoch();
+ }
+
+ friend days operator-(ymd_date x, rel_date y) BOOST_NOEXCEPT
+ {
+ return x.days_since_epoch() - y.days_since_epoch();
+ }
+
+ rel_date& operator+=(months m);
+ rel_date& operator-=(months m)
+ {
+ return *this += months(-m.count());
+ }
+
+ friend rel_date operator+(rel_date dt, months m)
+ {
+ dt += m;
+ return dt;
+ }
+ friend rel_date operator+(months m, rel_date dt)
+ {
+ dt += m;
+ return dt;
+ }
+ friend rel_date operator-(rel_date dt, months m)
+ {
+ dt -= m;
+ return dt;
+ }
+
+ rel_date& operator+=(years y);
+ rel_date& operator-=(years y)
+ {
+ return *this += years(-y.count());
+ }
+
+ friend rel_date operator+(rel_date dt, years y)
+ {
+ dt += y;
+ return dt;
+ }
+ friend rel_date operator+(years y, rel_date dt)
+ {
+ dt += y;
+ return dt;
+ }
+ friend rel_date operator-(rel_date dt, years y)
+ {
+ dt -= y;
+ return dt;
+ }
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+ friend bool operator==(const rel_date& x, const rel_date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ friend bool operator< (const rel_date& x, const rel_date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+ friend bool operator==(const rel_date& x, const rel_date& y) BOOST_NOEXCEPT
+ {
+ return x.y_ == y.y_ && x.m_ == y.m_ && x.d_ == y.d_;
+ }
+ friend bool operator< (const rel_date& x, const rel_date& y)
+ {
+ return x.y_ < y.y_ ||
+ (!(y.y_ < x.y_) && (x.m_ < y.m_ ||
+ (!(y.m_ < x.m_) && x.d_ < y.d_)));
+ }
+#endif
+ friend bool operator!=(const rel_date& x, const rel_date& y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ friend bool operator> (const rel_date& x, const rel_date& y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ friend bool operator<=(const rel_date& x, const rel_date& y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ friend bool operator>=(const rel_date& x, const rel_date& y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+ private:
+ uint16_t day_from_day_number() const BOOST_NOEXCEPT;
+ uint16_t month_from_day_number() const BOOST_NOEXCEPT;
+ int16_t year_from_day_number() const BOOST_NOEXCEPT;
+ bool leap_from_day_number() const BOOST_NOEXCEPT;
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+ uint32_t day_number_from_ymd() const BOOST_NOEXCEPT;
+#endif
+ };
+
+ template <>
+ struct is_date<rel_date> : true_type {};
+
+ inline rel_date operator/(year_month ym, nth_weekday d)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), d);
+ }
+ inline rel_date operator/(year_month ym, nth d)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), d);
+ }
+ inline rel_date operator/(year_month ym, last_t)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), nth(6));
+ }
+ inline rel_date operator/(year_month ym, _1st_t)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), nth(1));
+ }
+ inline rel_date operator/(year_month ym, _2nd_t)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), nth(2));
+ }
+ inline rel_date operator/(year_month ym, _3rd_t)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), nth(3));
+ }
+ inline rel_date operator/(year_month ym, _4th_t)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), nth(4));
+ }
+ inline rel_date operator/(year_month ym, _5th_t)
+ {
+ return rel_date(ym.get_year(), ym.get_month(), nth(5));
+ }
+ inline rel_date operator/(month_nth_weekday md, year y)
+ {
+ return rel_date(y, md.get_month(), md.get_nth_weekday());
+ }
+
+ inline rel_date operator/(month_nth_weekday md, year::rep y)
+ {
+ return md / year(y);
+ }
+
+ inline rel_date operator/(month_nth md, year y)
+ {
+ return rel_date(y, md.get_month(), md.get_nth());
+ }
+
+ inline rel_date operator/(month_nth md, year::rep y)
+ {
+ return md / year(y);
+ }
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/tmp/date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tmp/date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,608 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_HPP
+#define BOOST_CHRONO_DATE_DATE_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/day_of_year.hpp>
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/week.hpp>
+#include <boost/chrono/date/tuples.hpp>
+#include <boost/optional.hpp>
+#include <boost/chrono/date/config.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ class date
+ {
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1
+ // Store x, y/m/d, leap. Total 64 bits
+ uint_least32_t x_;
+ int_least16_t y_;
+
+ uint_least8_t m_ : 4;
+ uint_least8_t reserved1_ : 4;
+
+ uint_least8_t d_ : 5;
+ uint_least8_t leap_ : 1;
+ uint_least8_t reserved2_ : 2;
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ // Store x. Total 32 bits
+ uint32_t x_;
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ // Store y/m/d. Total 32 bits
+ int_least16_t y_;
+ uint_least8_t m_ : 4;
+ uint_least8_t reserved1_ : 4;
+ uint_least8_t d_ : 5;
+ uint_least8_t leap_ : 1;
+ uint_least8_t reserved2_ : 2;
+#endif
+
+ public:
+ /**
+ * @Effect Constructs a date using the year, month, day stored in the arguments as follows:
+ * If the value stored in d is outside the range of valid dates for this month m and year y,
+ * throws an exception of type bad_date.
+ * Else constructs a date for which get_year() == y, get_month() == m, get_day() == d.
+ * @Throws bad_date if the specified date is invalid.
+ */
+ date(chrono::year y, chrono::month m, chrono::day d);
+ /**
+ * @Effect Constructs a date constructor from year, month, day stored in the arguments as follows:
+ * Constructs a date so that get_year() == y, get_month() = m=, get_day() == d.
+ */
+ date(year::rep y, month::rep m, day::rep d, no_check_t) BOOST_NOEXCEPT;
+ /**
+ * @Effect Constructs a date using the year, month_day stored in the arguments as follows:
+ * If the value stored in md is outside the range of valid dates for this year y,
+ * throws an exception of type bad_date.
+ * Else constructs a date for which get_year() == y, get_month() == md.get_month(), get_day() == md.get_month().
+ *
+ * @Throws bad_date if the specified date is invalid.
+ * @Note This constructor can be more efficient as the month_day is already valid.
+ */
+ date(chrono::year y, chrono::month_day md);
+ /**
+ * @Effect Constructs a date using the year, month_day stored in the arguments as follows:
+ * Constructs a date for which get_year() == y, get_month() == md.get_month(), get_day() == md.get_month().
+ * @Note This constructor can be more efficient as the month_day is already valid.
+ */
+ date(chrono::year::rep, chrono::month_day, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a date using the year, day_of_year stored in the arguments as follows:
+ * If the value stored in doy is 366 and the year.is_leap()
+ * throws an exception of type bad_date.
+ * Else constructs a date for which days_since_epoch() == y.days_since_epoch()+doy.value()
+ * @Throws bad_date if the specified date is invalid.
+ * @Note This constructor can be more efficient as the check is simple.
+ */
+ date(chrono::year y, chrono::day_of_year doy);
+ /**
+ * @Effect Constructs a date using the year, day_of_year stored in the arguments as follows:
+ * Constructs a date for which days_since_epoch() == y.days_since_epoch()+doy.value()
+ * @Throws bad_date if the specified date is invalid.
+ */
+ date(year::rep y, day_of_year::rep m, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a date using the days given as parameter so that:
+ * days_since_epoch() == ds.count()
+ */
+ date(chrono::days) BOOST_NOEXCEPT;
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ /**
+ * Unchecked constructor from days.
+ */
+ date(days::rep m, no_check_t) BOOST_NOEXCEPT;
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ /**
+ * Unchecked constructor from days
+ */
+ date(days::rep x, no_check_t) BOOST_NOEXCEPT
+ : x_(x)
+ {
+ }
+#endif
+
+ //private:
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ date(days::rep x, year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ : x_(x),
+ y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ }
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT;
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ date(days::rep x, year::rep, month::rep, day::rep, bool, no_check_t) BOOST_NOEXCEPT
+ : x_(x)
+ {
+ }
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT;
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ date(days::rep , year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ :
+ y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ }
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ : y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ }
+#endif
+ public:
+ /**
+ * @Return A date which represents the current day taking the local time zone into account.
+ */
+ static date today() BOOST_NOEXCEPT;
+
+ /**
+ * Effects: Constructs a date as if by year(0)/jan/1.
+ * Note: the purpose of this constructor is to have a very efficient means
+ * of date construction when the specific value for that date is unimportant.
+ */
+ date() BOOST_NOEXCEPT;
+
+ /**
+ * @Effects: tp is converted to UTC, and then trucated to 00:00:00 hours.
+ * A date is created which reflects this point in time.
+ * @Throws If the conversion from tp overflows the range of date, throws
+ * an exception of type bad_date.
+ *
+ */
+ explicit date(boost::chrono::system_clock::time_point tp);
+ /**
+ * @Returns: A chrono::system_clock::time_point which represents the date
+ * referred to by *this at 00:00:00 UTC.
+ *
+ * @Throws: If the conversion to tp overflows the range of
+ * boost::chrono::system_clock::time_point, throws an exception of type bad_date.
+ *
+ */
+ // explicit
+ operator boost::chrono::system_clock::time_point () const;
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return true;
+ }
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ bool is_valid() const BOOST_NOEXCEPT;
+#endif
+
+ /**
+ * @Returns: the number of days since an undefined epoch.
+ */
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ days days_since_epoch()
+ {
+ return days(x_);
+ }
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ days days_since_epoch()
+ {
+ return days(day_number_from_ymd());
+ }
+#endif
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ /**
+ * Returns: chrono::day(d_,no_check).
+ */
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(d_,no_check);
+ }
+ /**
+ * Returns: chrono::month(m_,no_check).
+ */
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(m_,no_check);
+ }
+ /**
+ * Returns: chrono::year(y_,no_check).
+ */
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(y_,no_check);
+ }
+ month_day get_month_day() const BOOST_NOEXCEPT
+ {
+ return month_day(m_, d_, no_check);
+ }
+ year_month get_year_month() const BOOST_NOEXCEPT
+ {
+ return year_month(y_,m_,no_check);
+ }
+ year_month_day get_year_month_day() const BOOST_NOEXCEPT
+ {
+ return year_month_day(y_,m_,d_, no_check);
+ }
+ /**
+ * Returns: true if year() is a leap year, and otherwise returns false.
+ */
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_;
+ }
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(day_from_day_number(),no_check);
+ }
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(month_from_day_number(),no_check);
+ }
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(year_from_day_number(),no_check);
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_from_day_number();
+ }
+ month_day get_month_day() const BOOST_NOEXCEPT;
+ year_month get_year_month() const BOOST_NOEXCEPT;
+ year_month_day get_year_month_day() const BOOST_NOEXCEPT;
+
+#endif
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ /**
+ * @Returns: A weekday constructed with an int corresponding to *this
+ * date's day of the week (a value in the range of [0 - 6], 0 is Sunday).
+ */
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((x_ + 1) % weekday::size, no_check);
+ }
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((day_number_from_ymd()+1) % weekday::size,no_check);
+ }
+#endif
+
+ /**
+ * @Effects: Adds d.count() days to the current date.
+ * @Returns: *this.
+ * @Throws: If the addition would create a date with a y_ outside of the
+ * range of year, throws an exception of type bad_date.
+ *
+ */
+ date& operator+=(days d);
+
+ /**
+ * @Effects: *this += days(1).
+ * @Returns: *this.
+ */
+ date& operator++()
+ {
+ return *this += days(1);
+ }
+ /**
+ * @Effects: *this += days(1).
+ * @Returns: A copy of *this prior to the increment.
+ */
+ date operator++(int)
+ {
+ date tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+ /**
+ * @Effects: *this += -d.
+ * @Returns: *this.
+ */
+ date& operator-=(days d)
+ {
+ return *this += -d;
+ }
+ /**
+ * @Effects: *this -= days(1).
+ * @Returns: *this.
+ */
+ date& operator--()
+ {
+ return *this -= days(1);
+ }
+ /**
+ * @Effects: *this -= days(1).
+ * @Returns: A copy of *this prior to the increment.
+ */
+ date operator--(int)
+ {
+ date tmp(*this); --(*this); return tmp;
+ }
+
+ /**
+ * @Returns: dt += d.
+ *
+ */
+ friend date operator+(date dt, days d)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: dt += d.
+ *
+ */
+ friend date operator+(days d, date dt)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: dt -= d.
+ *
+ */
+ friend date operator-(date dt, days d)
+ {
+ dt -= d;
+ return dt;
+ }
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ /**
+ * @Returns: Computes the number of days x is ahead of y in the calendar,
+ * and returns that signed integral number n as days(n).
+ */
+ friend days operator-(date x, date y) BOOST_NOEXCEPT
+ {
+ return days(x.x_ - y.x_);
+ }
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ friend days operator-(date x, date y) BOOST_NOEXCEPT
+ {
+ return days(x.day_number_from_ymd() - y.day_number_from_ymd());
+ }
+#endif
+
+ /**
+ * @Effects Adds m.count() months to the current date.
+ * This is accomplished as if by storing temporary values of the date's y_, m_, d_.
+ * Computing new values for y_ and m_ based on m. And then assigning to
+ * *this a new date constructed from the newly computed y_ and m_, and the
+ * original d_.
+ *
+ * @Note Thus for example if a date is constructed as the second Sunday
+ * in May, adding two months to this date results in the second Sunday
+ * in July.
+ *
+ * @Returns: *this.
+ *
+ * @Throws: If the addition would create a date with a y_ outside of the
+ * range of year, or a d_ outside the range for the newly computed y_/m_,
+ * throws an exception of type bad_date.
+ *
+ */
+ date& operator+=(months m);
+
+ /**
+ * Returns: *this += -m.
+ */
+ date& operator-=(months m)
+ {
+ return *this += months(-m.count());
+ }
+
+ /**
+ * @Returns: dt += m.
+ *
+ */
+ friend date operator+(date dt, months m)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: dt += m.
+ *
+ */
+ friend date operator+(months m, date dt)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: dt += -m.
+ *
+ */
+ friend date operator-(date dt, months m)
+ {
+ dt -= m;
+ return dt;
+ }
+
+ /*
+ * @Effects: Adds y.count() years to the current date.
+ * This is accomplished as if by storing temporary values of the date's
+ * y_, m_, d_. Computing a new value for y_. And then assigning to *this
+ * a new date constructed from the newly computed y_, and the original m_, d_.
+ * @Note: Thus for example if a date is constructed as the second Sunday
+ * in May 2011, adding two years to this date results in the second Sunday
+ * in May 2013.
+ * @Returns: *this.
+ * @Throws: If the addition would create a date with a y_ outside of the
+ * range of year, or a d_ outside the range for the newly computed y_/m_,
+ * throws an exception of type bad_date.
+ */
+ date& operator+=(years y);
+
+ /**
+ * @Returns: *this += -y.
+ *
+ */
+ date& operator-=(years y)
+ {
+ return *this += years(-y.count());
+ }
+
+ /**
+ * @Returns: dt += y.
+ *
+ */
+ friend date operator+(date dt, years y)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: dt += y.
+ *
+ */
+ friend date operator+(years y, date dt)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: dt -= y.
+ *
+ */
+ friend date operator-(date dt, years y)
+ {
+ dt -= y;
+ return dt;
+ }
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ /**
+ * Returns: x.days_since_epoch() == y.days_since_epoch()
+ */
+ friend bool operator==(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ /**
+ * Returns: x.days_since_epoch() < y.days_since_epoch()
+ */
+ friend bool operator< (const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ friend bool operator==(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.y_ == y.y_ && x.m_ == y.m_ && x.d_ == y.d_;
+ }
+ friend bool operator< (const date& x, const date& y)
+ {
+ return x.y_ < y.y_ ||
+ (!(y.y_ < x.y_) && (x.m_ < y.m_ ||
+ (!(y.m_ < x.m_) && x.d_ < y.d_)));
+ }
+#endif
+ /**
+ * @Returns: !(x == y).
+ */
+ friend bool operator!=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ /**
+ * @Returns: y < x.
+ */
+ friend bool operator> (const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ /**
+ * @Returns: !(y < x).
+ */
+ friend bool operator<=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ /**
+ * @Returns: !(x < y).
+ */
+ friend bool operator>=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+ /**
+ * @Effects Update the date if the parameters represents a valid date.
+ * @Returns true if the parameters represents a valid date.
+ */
+ bool set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT;
+ private:
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ day::rep day_from_day_number() const BOOST_NOEXCEPT;
+ month::rep month_from_day_number() const BOOST_NOEXCEPT;
+ year::rep year_from_day_number() const BOOST_NOEXCEPT;
+ bool leap_from_day_number() const BOOST_NOEXCEPT;
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ days::rep day_number_from_ymd() const BOOST_NOEXCEPT;
+#endif
+ };
+
+ /**
+ * A type representing an optional date.
+ */
+ typedef optional<date> optional_date;
+ /**
+ * @Returns If the parameters represents a valid date the date,
+ * otherwise a none optional.
+ */
+ optional_date make_valid_date(year,month,day) BOOST_NOEXCEPT;
+
+ date make_ymd_date(year::rep,month::rep,day::rep) BOOST_NOEXCEPT;
+ date make_ydoy_date(year::rep,day_of_year::rep) BOOST_NOEXCEPT;
+ date make_epoch_date(days::rep) BOOST_NOEXCEPT;
+
+
+ } // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/tmp/date_fwd.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tmp/date_fwd.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,34 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_DATE_FWD_HPP
+#define BOOST_CHRONO_DATE_DATE_DATE_FWD_HPP
+#error
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ //class date;
+// class year;
+// class month;
+// class day;
+// class week;
+// class day_of_year;
+// class weekday;
+// class year_month;
+// class month_day;
+// class rel_date;
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/tmp/factories.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tmp/factories.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,64 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+/**
+ * @file Includes the date generators form several date formats.
+ */
+
+#error
+#ifndef BOOST_CHRONO_DATE_DATE_FACTORIES_HPP
+#define BOOST_CHRONO_DATE_DATE_FACTORIES_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/week.hpp>
+#include <boost/chrono/date/date.hpp>
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/tuples.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+
+
+
+
+// inline date operator/(year_week yw, weekday wd)
+// {
+// return date(ym.get_year(), ym.get_week(), wd);
+// }
+// inline date operator/(week_weekday md, year y)
+// {
+// return date(y, md.get_week(), md.get_weekday());
+// }
+// inline date operator/(year_week yw, weekday::rep wd)
+// {
+// return ym / weekday(wd);
+// }
+// inline date operator/(week_weekday wwd, year::rep y)
+// {
+// return wwd / year(y);
+// }
+
+
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/tmp/formats.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tmp/formats.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,37 @@
+// date
+//
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_FORMATS_HPP
+#define BOOST_CHRONO_DATE_DATE_FORMATS_HPP
+
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ struct ymd_t
+ {};
+ const ymd_t ymd =
+ {};
+
+ struct ydoy_t
+ {};
+ const ydoy_t ydoy =
+ {};
+
+ struct epoch_t
+ {};
+ const epoch_t epoch =
+ {};
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/tmp/gregorian.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tmp/gregorian.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,973 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_HPP
+#define BOOST_CHRONO_DATE_DATE_HPP
+
+/*
+ calendar synopsis
+
+ namespace boost
+ {
+ namespace chrono
+ {
+ typedef duration<boost::int_least32_t, boost::ratio<86400> > days;
+
+ class gregorian // calendar
+ {
+ public:
+ typedef ... clock;
+ typedef ... date;
+ typedef date_time<gregorian> date_time;
+ typedef ... year;
+ typedef ... month;
+ typedef ... weekday;
+ typedef ... day;
+ typedef ... date;
+ static date today();
+ static date_time now();
+ };
+
+
+ class date
+ {
+
+ // conversions to other calendards
+ ...
+ // obervers
+ day day() const noexcept;
+ month month() const noexcept;
+ year year() const noexcept;
+ weekday weekday() const noexcept;
+
+ // Other observers
+ bool is_leap_year() const noexcept;
+
+ // day arithmetic
+ date& operator+=(days d);
+ date& operator++();
+ date operator++(int);
+ date& operator-=(days d);
+ date& operator--();
+ date operator--(int);
+
+ // month arithmetic
+ date& operator+=(months m);
+ date& operator-=(months m);
+
+ // year arithmetic
+ date& operator+=(years y);
+ date& operator-=(years y);
+
+ };
+ // A date
+ class date
+ {
+ public:
+ static date today();
+
+ // system_clock::time_point conversions
+ explicit date(boost::chrono::system_clock::time_point tp);
+ explicit operator boost::chrono::system_clock::time_point () const;
+
+ // obervers
+ day day() const noexcept;
+ month month() const noexcept;
+ year year() const noexcept;
+ weekday weekday() const noexcept;
+ bool is_leap_year() const noexcept;
+
+ // day arithmetic
+ date& operator+=(days d);
+ date& operator++();
+ date operator++(int);
+ date& operator-=(days d);
+ date& operator--();
+ date operator--(int);
+
+ // month arithmetic
+ date& operator+=(months m);
+ date& operator-=(months m);
+
+ // year arithmetic
+ date& operator+=(years y);
+ date& operator-=(years y);
+ };
+
+ // date relational
+ bool operator==(const date& x, const date& y) noexcept;
+ bool operator!=(const date& x, const date& y) noexcept;
+ bool operator< (const date& x, const date& y) noexcept;
+ bool operator> (const date& x, const date& y) noexcept;
+ bool operator<=(const date& x, const date& y) noexcept;
+ bool operator>=(const date& x, const date& y) noexcept;
+
+ // date day arithmetic
+ date operator+(date dt, days d);
+ date operator+(days d, date dt);
+ date operator-(date dt, days d);
+ days operator-(date x, date y) noexcept;
+
+ // date month arithmetic
+ date operator+(date dt, months m);
+ date operator+(months m, date dt);
+ date operator-(date dt, months m);
+
+ // date year arithmetic
+ date operator+(date dt, years y);
+ date operator+(years y, date dt);
+ date operator-(date dt, years y);
+
+ // Specifiers
+
+ // A year specifier
+ class year
+ {
+ public:
+ explicit year(std::int16_t y);
+ operator int() const noexcept;
+ };
+
+ // A month specifier
+ class month
+ {
+ public:
+ explicit month(int);
+ operator int() const noexcept;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ // A day specifier
+ class day
+ {
+ public:
+ explicit day(int);
+ operator int() const noexcept;
+ };
+
+ // A day of the week specifier
+ class weekday
+ {
+ public:
+ explicit weekday(int);
+ operator int() const noexcept;
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ // A year + month specifier
+ class year_month
+ {
+ // no public members
+ };
+
+ // A month + day specifier
+ class month_day
+ {
+ // no public members
+ };
+
+
+ // Date generation functions
+
+ date operator/(year_month, day); // year(2011)/month(8)/day(19)
+ date operator/(month_day, year); // month(8)/day(19)/year(2011)
+ // day(19)/month(8)/year(2011)
+
+ year_month operator/(year, month) noexcept; // year(2011)/month(8)
+
+ month_day operator/(day, month) noexcept; // day(19)/month(8)
+ month_day operator/(month, day) noexcept; // month(8)/day(19)
+
+ // Date durations
+
+ typedef duration<int_least32_t, ratio<86400>> days;
+
+ days operator+(days x, days y);
+ days operator-(days x, days y);
+ days operator*(days x, days::rep y);
+ days operator*(days::rep x, days y);
+ days operator/(days x, days::rep y);
+ days::rep operator/(days x, days y);
+ days operator%(days x, days::rep y);
+ days operator%(days x, days y);
+
+ bool operator==(days x, days y);
+ bool operator!=(days x, days y);
+ bool operator< (days x, days y);
+ bool operator> (days x, days y);
+ bool operator<=(days x, days y);
+ bool operator>=(days x, days y);
+
+ class months
+ {
+ public:
+ typedef std::int32_t rep;
+ months() = default;
+ explicit months(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ months operator+() const noexcept;
+ months operator-() const noexcept;
+
+ months& operator++() noexcept;
+ months operator++(int) noexcept;
+ months& operator--() noexcept;
+ months operator--(int) noexcept;
+
+ months& operator+=(const months& x) noexcept;
+ months& operator-=(const months& x) noexcept;
+
+ months& operator*=(const rep& rhs) noexcept;
+ months& operator/=(const rep& rhs) noexcept;
+ months& operator%=(const rep& rhs) noexcept;
+ months& operator%=(const months& rhs) noexcept;
+ };
+
+ months operator+(months x, months y) noexcept;
+ months operator-(months x, months y) noexcept;
+ months operator*(months x, months::rep y) noexcept;
+ months operator*(months::rep x, months y) noexcept;
+ months operator/(months x, months::rep y) noexcept;
+ months::rep operator/(months x, months y) noexcept;
+ months operator%(months x, months::rep y) noexcept;
+ months operator%(months x, months y) noexcept;
+
+ bool operator==(months x, months y) noexcept;
+ bool operator!=(months x, months y) noexcept;
+ bool operator< (months x, months y) noexcept;
+ bool operator> (months x, months y) noexcept;
+ bool operator<=(months x, months y) noexcept;
+ bool operator>=(months x, months y) noexcept;
+
+ class years
+ {
+ public:
+ typedef std::int32_t rep;
+ years() = default;
+ explicit years(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ years operator+() const noexcept;
+ years operator-() const noexcept;
+
+ years& operator++() noexcept;
+ years operator++(int) noexcept;
+ years& operator--() noexcept;
+ years operator--(int) noexcept;
+
+ years& operator+=(const years& x) noexcept;
+ years& operator-=(const years& x) noexcept;
+
+ years& operator*=(const rep& rhs) noexcept;
+ years& operator/=(const rep& rhs) noexcept;
+ years& operator%=(const rep& rhs) noexcept;
+ years& operator%=(const years& rhs) noexcept;
+ };
+
+ years operator+(years x, years y) noexcept;
+ years operator-(years x, years y) noexcept;
+ years operator*(years x, years::rep y) noexcept;
+ years operator*(years::rep x, years y) noexcept;
+ years operator/(years x, years::rep y) noexcept;
+ years::rep operator/(years x, years y) noexcept;
+ years operator%(years x, years::rep y) noexcept;
+ years operator%(years x, years y) noexcept;
+
+ bool operator==(years x, years y) noexcept;
+ bool operator!=(years x, years y) noexcept;
+ bool operator< (years x, years y) noexcept;
+ bool operator> (years x, years y) noexcept;
+ bool operator<=(years x, years y) noexcept;
+ bool operator>=(years x, years y) noexcept;
+
+
+ class bad_date
+ : public std::exception
+ {
+ public:
+ virtual const char* what() const noexcpt();
+ };
+
+ } // chrono
+ } // std
+
+ */
+
+#include <exception>
+#include <stdexcept>
+#include <boost/cstdint.hpp>
+#include <boost/chrono.hpp>
+#include <boost/chrono/config.hpp>
+
+#ifndef DESIGN
+#define DESIGN 1
+#endif
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ typedef duration<boost::int_least32_t, boost::ratio<86400> > days;
+ typedef duration<boost::int_least32_t, boost::ratio<7*86400> > weeks;
+ typedef duration<boost::int_least32_t, boost::ratio<2629746> > average_months;
+ typedef duration<boost::int_least32_t, boost::ratio<31556952> > average_years;
+ typedef duration<boost::int_least32_t, boost::ratio<400*31556952> > _400_years;
+
+ class BOOST_CHRONO_DECL days_count_clock
+ {
+ public:
+ typedef days duration;
+ typedef duration::rep rep;
+ typedef duration::period period;
+ typedef chrono::time_point<days_count_clock> time_point;
+ BOOST_STATIC_CONSTEXPR bool is_steady = true;
+
+ static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT;
+ #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
+ static BOOST_CHRONO_INLINE time_point now(system::error_code & ec);
+ #endif
+
+ static BOOST_CHRONO_INLINE std::time_t to_time_t(const time_point& t) BOOST_NOEXCEPT;
+ static BOOST_CHRONO_INLINE time_point from_time_t(std::time_t t) BOOST_NOEXCEPT;
+ };
+
+ struct no_check_t {};
+ const no_check_t no_check = { };
+
+ class bad_date: public std::runtime_error
+ {
+ public:
+ explicit bad_date(const std::string& s) :
+ std::runtime_error(s)
+ {
+ }
+ explicit bad_date(const char* s) :
+ std::runtime_error(s)
+ {
+ }
+ };
+
+ class date;
+ class year;
+ class month;
+ class day;
+ class weekday;
+ class year_month;
+ class month_day;
+
+ class rel_date;
+ class rel_day;
+ class rel_weekday;
+ class month_rel_day;
+
+ month_day operator/(day, month) BOOST_NOEXCEPT;
+ month_day operator/(month, day) BOOST_NOEXCEPT;
+ year_month operator/(year, month) BOOST_NOEXCEPT;
+
+ date operator/(year_month, day);
+ date operator/(year_month, int);
+ date operator/(month_day, year);
+ date operator/(month_day, int);
+
+ class year
+ {
+ int32_t y_;
+ public:
+ explicit year(int32_t v) : y_(v)
+ {
+ if (!(-32768 <= v && v <= 32767))
+ {
+ throw bad_date("year is out of range");
+ }
+ }
+
+ year(int32_t y,no_check_t):y_(y) {}
+ operator int() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+
+ bool is_leap() const BOOST_NOEXCEPT;
+
+ friend date operator/(month_day, year);
+ friend rel_date operator/(month_rel_day, year);
+ friend class date;
+ friend class rel_date;
+ };
+
+ class month
+ {
+ int8_t m_;
+ public:
+ explicit month(int);
+ explicit month(int y,no_check_t):m_(y) {}
+ operator int() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+
+ friend class date;
+ friend class rel_date;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ class day
+ {
+ uint16_t d_;
+
+ public:
+ explicit day(int) BOOST_NOEXCEPT;
+ day(int d,no_check_t) BOOST_NOEXCEPT
+ : d_(d)
+ {}
+ operator int() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+
+ friend date operator/(year_month, day);
+ friend class date;
+ friend class weekday;
+ friend class rel_date;
+ friend class rel_weekday;
+ };
+
+ class weekday
+ {
+ uint8_t wd_;
+
+ public:
+ explicit weekday(int);
+ explicit weekday(int wd,no_check_t):wd_(wd){};
+ operator int() const BOOST_NOEXCEPT
+ {
+ return wd_;
+ }
+ friend class rel_weekday;
+
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ class year_month
+ {
+ year y_;
+ month m_;
+ year_month(year y, month m) BOOST_NOEXCEPT
+ : y_(y),
+ m_(m)
+ {
+ }
+
+ int days_in() BOOST_NOEXCEPT;
+
+ friend year_month operator/(year y, month m) BOOST_NOEXCEPT
+ {
+ return year_month(y, m);
+ }
+ friend date operator/(year_month, day);
+ friend rel_date operator/(year_month ym, rel_day d);
+
+ };
+
+ class month_day
+ {
+ month m_;
+ day d_;
+ month_day(month m, day d) BOOST_NOEXCEPT
+ : m_(m),
+ d_(d)
+ {
+ }
+ friend month_day make_month_day(month m, day d) BOOST_NOEXCEPT;
+ friend month_rel_day make_month_day(month m, rel_day d) BOOST_NOEXCEPT;
+
+ friend month_day operator/(month m, day d) BOOST_NOEXCEPT;
+ friend month_rel_day operator/(month m, rel_day d) BOOST_NOEXCEPT;
+ friend month_day operator/(day d, month m) BOOST_NOEXCEPT;
+ friend month_rel_day operator/(rel_day d, month m) BOOST_NOEXCEPT;
+ friend date operator/(month_day, year);
+ friend rel_date operator/(month_rel_day, year);
+ };
+
+ extern const month_day
+ jan_01, jan_02, jan_03, jan_04, jan_05, jan_06, jan_07, jan_08, jan_09,
+ jan_10, jan_11, jan_12, jan_13, jan_14, jan_15, jan_16, jan_17, jan_18,
+ jan_19, jan_20, jan_21, jan_22, jan_23, jan_24, jan_25, jan_26, jan_27,
+ jan_28, jan_29, jan_30, jan_31
+ // ...
+ ;
+
+
+ inline month_day operator/(month m, day d) BOOST_NOEXCEPT
+ {
+ return month_day(m, d);
+ }
+ inline month_day operator/(day d, month m) BOOST_NOEXCEPT
+ {
+ return month_day(m, d);
+ }
+
+ namespace detail
+ {
+ template <class T, int>
+ class duration_type
+ {
+ public:
+ typedef T rep;
+ private:
+ public:
+ rep x_;
+ public:
+ explicit duration_type(rep x = rep()) BOOST_NOEXCEPT : x_(x)
+ {
+ }
+
+ rep count() const BOOST_NOEXCEPT
+ {
+ return x_;
+ }
+
+ duration_type operator+() const BOOST_NOEXCEPT
+ {
+ return *this;
+ }
+ duration_type operator-() const BOOST_NOEXCEPT
+ {
+ return duration_type(-x_);
+ }
+
+ duration_type& operator++() BOOST_NOEXCEPT
+ {
+ ++x_;
+ return *this;
+ }
+ duration_type operator++(int) BOOST_NOEXCEPT
+ {
+ return duration_type(x_++);
+ }
+ duration_type& operator--() BOOST_NOEXCEPT
+ {
+ --x_;
+ return *this;
+ }
+ duration_type operator--(int) BOOST_NOEXCEPT
+ {
+ return duration_type(x_--);
+ }
+
+ duration_type& operator+=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ += rhs.x_;
+ return *this;
+ }
+ duration_type& operator-=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ -= rhs.x_;
+ return *this;
+ }
+
+ friend duration_type operator+(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x += y;
+ return x;
+ }
+ friend duration_type operator-(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x -= y;
+ return x;
+ }
+
+ duration_type& operator*=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ *= rhs;
+ return *this;
+ }
+ duration_type& operator/=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ /= rhs;
+ return *this;
+ }
+ duration_type& operator%=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ %= rhs;
+ return *this;
+ }
+ duration_type& operator%=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ %= rhs.x_;
+ return *this;
+ }
+
+ friend duration_type operator*(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x *= y;
+ return x;
+ }
+ friend duration_type operator*(rep x, duration_type y) BOOST_NOEXCEPT
+ {
+ y *= x;
+ return y;
+ }
+ friend duration_type operator/(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x /= y;
+ return x;
+ }
+ friend rep operator/(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ / y.x_;
+ }
+ friend duration_type operator%(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x %= y;
+ return x;
+ }
+ friend duration_type operator%(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x %= y.x_;
+ return x;
+ }
+
+ friend bool operator==(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ friend bool operator!=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ friend bool operator< (duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+ friend bool operator> (duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ friend bool operator<=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ friend bool operator>=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+ friend class date;
+ };
+ }
+
+ typedef detail::duration_type<int32_t, 1> months;
+ typedef detail::duration_type<int32_t, 2> years;
+
+ class date
+ {
+ friend class rel_date;
+
+#if DESIGN == 1
+ // Store x, y/m/d, n, dow
+ uint32_t x_;
+ int16_t y_;
+ uint16_t m_ : 4;
+ uint16_t d_ : 5;
+ uint16_t leap_ : 1;
+#elif DESIGN == 2
+ // Store x
+ uint32_t x_;
+#elif DESIGN == 3
+ // Store y/m/d
+ int16_t y_;
+ uint16_t m_ : 4;
+ uint16_t d_ : 5;
+ uint16_t leap_ : 1;
+#endif
+
+
+ friend date operator/(year_month ym, day d);
+ friend date operator/(month_day md, year y);
+ public:
+ date(chrono::year, chrono::month, chrono::day);
+ date(uint32_t, int, int, no_check_t);
+#if DESIGN == 1
+#elif DESIGN == 2
+ date(uint32_t x, no_check_t)
+ : x_(x)
+ {
+ }
+#elif DESIGN == 3
+ date(uint32_t, int, int, int, no_check_t)
+ : y_(y),
+ m_(m),
+ d_(d)
+ leap_(is_leap(y_))
+ {
+ }
+#endif
+ static date today() BOOST_NOEXCEPT;
+
+ date() BOOST_NOEXCEPT;
+
+ explicit date(boost::chrono::system_clock::time_point tp);
+ // explicit
+ operator boost::chrono::system_clock::time_point () const;
+
+#if DESIGN == 1 || DESIGN == 3
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(d_,no_check);
+ }
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(m_,no_check);
+ }
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(y_,no_check);
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_;
+ }
+#elif DESIGN == 2
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(day_from_day_number(),no_check);
+ }
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(month_from_day_number(),no_check);
+ }
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(year_from_day_number(),no_check);
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_from_day_number();
+ }
+#endif
+#if DESIGN == 1 || DESIGN == 2
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((x_+1) % 7,no_check);
+ }
+#elif DESIGN == 3
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((day_number_from_ymd()+1) % 7,no_check);
+ }
+#endif
+
+ date& operator+=(days d);
+ date& operator++()
+ {
+ return *this += days(1);
+ }
+ date operator++(int)
+ {
+ date tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+ date& operator-=(days d)
+ {
+ return *this += -d;
+ }
+ date& operator--()
+ {
+ return *this -= days(1);
+ }
+ date operator--(int)
+ {
+ date tmp(*this); --(*this); return tmp;
+ }
+
+ friend date operator+(date dt, days d)
+ {
+ dt += d;
+ return dt;
+ }
+ friend date operator+(days d, date dt)
+ {
+ dt += d;
+ return dt;
+ }
+ friend date operator-(date dt, days d)
+ {
+ dt -= d;
+ return dt;
+ }
+#if DESIGN == 1 || DESIGN == 2
+ friend days operator-(date x, date y) BOOST_NOEXCEPT
+ {
+ return days(x.x_ - y.x_);
+ }
+#elif DESIGN == 3
+ friend days operator-(date x, date y) BOOST_NOEXCEPT
+ {
+ return days(x.day_number_from_ymd() - y.day_number_from_ymd());
+ }
+#endif
+
+ date& operator+=(months m);
+ date& operator-=(months m)
+ {
+ return *this += months(-m.x_);
+ }
+
+ friend date operator+(date dt, months m)
+ {
+ dt += m;
+ return dt;
+ }
+ friend date operator+(months m, date dt)
+ {
+ dt += m;
+ return dt;
+ }
+ friend date operator-(date dt, months m)
+ {
+ dt -= m;
+ return dt;
+ }
+
+ date& operator+=(years y);
+ date& operator-=(years y)
+ {
+ return *this += years(-y.x_);
+ }
+
+ friend date operator+(date dt, years y)
+ {
+ dt += y;
+ return dt;
+ }
+ friend date operator+(years y, date dt)
+ {
+ dt += y;
+ return dt;
+ }
+ friend date operator-(date dt, years y)
+ {
+ dt -= y;
+ return dt;
+ }
+
+#if DESIGN == 1 || DESIGN == 2
+ friend bool operator==(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ friend bool operator< (const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+#elif DESIGN == 3
+ friend bool operator==(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.y_ == y.y_ && x.m_ == y.m_ && x.d_ == y.d_;
+ }
+ friend bool operator< (const date& x, const date& y)
+ {
+ return x.y_ < y.y_ ||
+ (!(y.y_ < x.y_) && (x.m_ < y.m_ ||
+ (!(y.m_ < x.m_) && x.d_ < y.d_)));
+ }
+#endif
+ friend bool operator!=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ friend bool operator> (const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ friend bool operator<=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ friend bool operator>=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+#if DESIGN == 2
+ private:
+ uint16_t day_from_day_number() const BOOST_NOEXCEPT;
+ uint16_t month_from_day_number() const BOOST_NOEXCEPT;
+ int16_t year_from_day_number() const BOOST_NOEXCEPT;
+ bool leap_from_day_number() const BOOST_NOEXCEPT;
+#elif DESIGN == 3
+ uint32_t day_number_from_ymd() const BOOST_NOEXCEPT;
+#endif
+ };
+
+ inline date operator/(year_month ym, day d)
+ {
+ return date(ym.y_, ym.m_, d);
+ }
+ inline date operator/(month_day md, year y)
+ {
+ return date(y, md.m_, md.d_);
+ }
+ inline date operator/(year_month ym, int d)
+ {
+ return ym / day(d);
+ }
+ inline date operator/(month_day md, int y)
+ {
+ return md / year(y);
+ }
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/tmp/relative_date_save.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tmp/relative_date_save.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,1001 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_HPP
+#define BOOST_CHRONO_DATE_DATE_HPP
+
+/*
+ date synopsis
+
+ namespace boost
+ {
+ namespace chrono
+ {
+
+ // A date
+ class date
+ {
+ public:
+ static date today();
+
+ // system_clock::time_point conversions
+ explicit date(boost::chrono::system_clock::time_point tp);
+ explicit operator boost::chrono::system_clock::time_point () const;
+
+ // obervers
+ day day() const noexcept;
+ month month() const noexcept;
+ year year() const noexcept;
+ weekday weekday() const noexcept;
+ bool is_leap_year() const noexcept;
+
+ // day arithmetic
+ date& operator+=(days d);
+ date& operator++();
+ date operator++(int);
+ date& operator-=(days d);
+ date& operator--();
+ date operator--(int);
+
+ // month arithmetic
+ date& operator+=(months m);
+ date& operator-=(months m);
+
+ // year arithmetic
+ date& operator+=(years y);
+ date& operator-=(years y);
+ };
+
+ // date relational
+ bool operator==(const date& x, const date& y) noexcept;
+ bool operator!=(const date& x, const date& y) noexcept;
+ bool operator< (const date& x, const date& y) noexcept;
+ bool operator> (const date& x, const date& y) noexcept;
+ bool operator<=(const date& x, const date& y) noexcept;
+ bool operator>=(const date& x, const date& y) noexcept;
+
+ // date day arithmetic
+ date operator+(date dt, days d);
+ date operator+(days d, date dt);
+ date operator-(date dt, days d);
+ days operator-(date x, date y) noexcept;
+
+ // date month arithmetic
+ date operator+(date dt, months m);
+ date operator+(months m, date dt);
+ date operator-(date dt, months m);
+
+ // date year arithmetic
+ date operator+(date dt, years y);
+ date operator+(years y, date dt);
+ date operator-(date dt, years y);
+
+ // Specifiers
+
+ // A year specifier
+ class year
+ {
+ public:
+ explicit year(std::int16_t y);
+ operator int() const noexcept;
+ };
+
+ // A month specifier
+ class month
+ {
+ public:
+ explicit month(int);
+ operator int() const noexcept;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ // A day specifier
+ class day
+ {
+ public:
+ explicit day(int);
+ day(__unnamed) noexcept;
+ operator int() const noexcept;
+ };
+
+ // A day of the week specifier
+ class weekday
+ {
+ public:
+ explicit weekday(int);
+ operator int() const noexcept;
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ // A year + month specifier
+ class year_month
+ {
+ // no public members
+ };
+
+ // A month + day specifier
+ class month_day
+ {
+ // no public members
+ };
+
+ class __unnamed
+ {
+ // no public members
+ };
+
+ extern const __unnamed _1st;
+ extern const __unnamed _2nd;
+ extern const __unnamed _3rd;
+ extern const __unnamed _4th;
+ extern const __unnamed _5th;
+ extern const __unnamed last;
+
+ // Date generation functions
+
+ date operator/(year_month, day); // year(2011)/month(8)/day(19)
+ date operator/(month_day, year); // month(8)/day(19)/year(2011)
+ // day(19)/month(8)/year(2011)
+
+ year_month operator/(year, month) noexcept; // year(2011)/month(8)
+
+ month_day operator/(day, month) noexcept; // day(19)/month(8)
+ month_day operator/(month, day) noexcept; // month(8)/day(19)
+
+ // Date durations
+
+ typedef duration<int_least32_t, ratio<86400>> days;
+
+ days operator+(days x, days y);
+ days operator-(days x, days y);
+ days operator*(days x, days::rep y);
+ days operator*(days::rep x, days y);
+ days operator/(days x, days::rep y);
+ days::rep operator/(days x, days y);
+ days operator%(days x, days::rep y);
+ days operator%(days x, days y);
+
+ bool operator==(days x, days y);
+ bool operator!=(days x, days y);
+ bool operator< (days x, days y);
+ bool operator> (days x, days y);
+ bool operator<=(days x, days y);
+ bool operator>=(days x, days y);
+
+ class months
+ {
+ public:
+ typedef std::int32_t rep;
+ months() = default;
+ explicit months(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ months operator+() const noexcept;
+ months operator-() const noexcept;
+
+ months& operator++() noexcept;
+ months operator++(int) noexcept;
+ months& operator--() noexcept;
+ months operator--(int) noexcept;
+
+ months& operator+=(const months& x) noexcept;
+ months& operator-=(const months& x) noexcept;
+
+ months& operator*=(const rep& rhs) noexcept;
+ months& operator/=(const rep& rhs) noexcept;
+ months& operator%=(const rep& rhs) noexcept;
+ months& operator%=(const months& rhs) noexcept;
+ };
+
+ months operator+(months x, months y) noexcept;
+ months operator-(months x, months y) noexcept;
+ months operator*(months x, months::rep y) noexcept;
+ months operator*(months::rep x, months y) noexcept;
+ months operator/(months x, months::rep y) noexcept;
+ months::rep operator/(months x, months y) noexcept;
+ months operator%(months x, months::rep y) noexcept;
+ months operator%(months x, months y) noexcept;
+
+ bool operator==(months x, months y) noexcept;
+ bool operator!=(months x, months y) noexcept;
+ bool operator< (months x, months y) noexcept;
+ bool operator> (months x, months y) noexcept;
+ bool operator<=(months x, months y) noexcept;
+ bool operator>=(months x, months y) noexcept;
+
+ class years
+ {
+ public:
+ typedef std::int32_t rep;
+ years() = default;
+ explicit years(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ years operator+() const noexcept;
+ years operator-() const noexcept;
+
+ years& operator++() noexcept;
+ years operator++(int) noexcept;
+ years& operator--() noexcept;
+ years operator--(int) noexcept;
+
+ years& operator+=(const years& x) noexcept;
+ years& operator-=(const years& x) noexcept;
+
+ years& operator*=(const rep& rhs) noexcept;
+ years& operator/=(const rep& rhs) noexcept;
+ years& operator%=(const rep& rhs) noexcept;
+ years& operator%=(const years& rhs) noexcept;
+ };
+
+ years operator+(years x, years y) noexcept;
+ years operator-(years x, years y) noexcept;
+ years operator*(years x, years::rep y) noexcept;
+ years operator*(years::rep x, years y) noexcept;
+ years operator/(years x, years::rep y) noexcept;
+ years::rep operator/(years x, years y) noexcept;
+ years operator%(years x, years::rep y) noexcept;
+ years operator%(years x, years y) noexcept;
+
+ bool operator==(years x, years y) noexcept;
+ bool operator!=(years x, years y) noexcept;
+ bool operator< (years x, years y) noexcept;
+ bool operator> (years x, years y) noexcept;
+ bool operator<=(years x, years y) noexcept;
+ bool operator>=(years x, years y) noexcept;
+
+ date operator< (weekday wd, date x) noexcept;
+ date operator<=(weekday wd, date x) noexcept;
+ date operator> (weekday wd, date x) noexcept;
+ date operator>=(weekday wd, date x) noexcept;
+
+ class bad_date
+ : public std::exception
+ {
+ public:
+ virtual const char* what() const noexcpt();
+ };
+
+ } // chrono
+ } // std
+
+ */
+
+#include <exception>
+#include <istream>
+#include <ostream>
+#include <locale>
+#include <stdexcept>
+#include <boost/cstdint.hpp>
+#include <boost/chrono.hpp>
+#include <boost/chrono/config.hpp>
+
+#ifndef DESIGN
+#define DESIGN 1
+#endif
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ typedef duration<boost::int_least32_t, boost::ratio<86400> > days;
+ typedef duration<boost::int_least32_t, boost::ratio<7*86400> > weeks;
+ typedef duration<boost::int_least32_t, boost::ratio<2629746> > average_months;
+ typedef duration<boost::int_least32_t, boost::ratio<31556952> > average_years;
+ typedef duration<boost::int_least32_t, boost::ratio<400*31556952> > _400_years;
+
+ class BOOST_CHRONO_DECL days_count_clock
+ {
+ public:
+ typedef days duration;
+ typedef duration::rep rep;
+ typedef duration::period period;
+ typedef chrono::time_point<days_count_clock> time_point;
+ BOOST_STATIC_CONSTEXPR bool is_steady = true;
+
+ static BOOST_CHRONO_INLINE time_point now() BOOST_NOEXCEPT;
+ #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
+ static BOOST_CHRONO_INLINE time_point now(system::error_code & ec);
+ #endif
+
+ static BOOST_CHRONO_INLINE std::time_t to_time_t(const time_point& t) BOOST_NOEXCEPT;
+ static BOOST_CHRONO_INLINE time_point from_time_t(std::time_t t) BOOST_NOEXCEPT;
+ };
+
+ struct no_check_t {};
+ const no_check_t no_check = { };
+
+ class bad_date: public std::runtime_error
+ {
+ public:
+ explicit bad_date(const std::string& s) :
+ std::runtime_error(s)
+ {
+ }
+ explicit bad_date(const char* s) :
+ std::runtime_error(s)
+ {
+ }
+ };
+
+ class date;
+ class year;
+ class month;
+ class day;
+ class weekday;
+ class year_month;
+ class month_day;
+
+ namespace detail
+ {
+ class day_spec;
+ }
+
+ month_day operator/(day, month) BOOST_NOEXCEPT;
+ month_day operator/(month, day) BOOST_NOEXCEPT;
+ year_month operator/(year, month) BOOST_NOEXCEPT;
+
+ date operator/(year_month, day);
+ date operator/(year_month, int);
+ date operator/(month_day, year);
+ date operator/(month_day, int);
+
+ class year
+ {
+ int32_t y_;
+ public:
+ explicit year(int32_t v) : y_(v)
+ {
+ if (!(-32768 <= v && v <= 32767))
+ {
+ throw bad_date("year is out of range");
+ }
+ }
+
+ year(int32_t y,no_check_t):y_(y) {}
+ operator int() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+
+ friend date operator/(month_day, year);
+ friend class date;
+ };
+
+ class month
+ {
+ int8_t m_;
+ public:
+ explicit month(int);
+ explicit month(int y,no_check_t):m_(y) {}
+ operator int() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+
+ friend class date;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ class day
+ {
+ uint16_t d_ :5;
+ uint16_t n_ :3;
+ uint16_t dow_ :3;
+
+ day(uint8_t, uint8_t, uint8_t) BOOST_NOEXCEPT;
+ public:
+ explicit day(int);
+ day(int d,no_check_t):d_(d),n_(7),dow_(7) {}
+ day(detail::day_spec) BOOST_NOEXCEPT;
+ operator int() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+
+ friend date operator/(year_month, day);
+ friend class date;
+ friend class weekday;
+ };
+
+ namespace detail
+ {
+
+ //day_spec make_day_spec(uint8_t) BOOST_NOEXCEPT;
+ class day_spec
+ {
+ uint8_t s_;
+ day_spec(uint8_t s) BOOST_NOEXCEPT : s_(s)
+ {
+ }
+ friend day_spec make_day_spec(uint8_t) BOOST_NOEXCEPT;
+ friend class boost::chrono::day;
+ friend class boost::chrono::weekday;
+ };
+ }
+ extern const detail::day_spec last;
+ extern const detail::day_spec _1st;
+ extern const detail::day_spec _2nd;
+ extern const detail::day_spec _3rd;
+ extern const detail::day_spec _4th;
+ extern const detail::day_spec _5th;
+
+ class weekday
+ {
+ uint8_t wd_;
+
+ public:
+ explicit weekday(int);
+ explicit weekday(int wd,no_check_t):wd_(wd){};
+ operator int() const BOOST_NOEXCEPT
+ {
+ return wd_;
+ }
+
+ day operator[](int) const;
+ day operator[](detail::day_spec s) const BOOST_NOEXCEPT
+ {
+ return day(0, s.s_, wd_);
+ }
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ class year_month
+ {
+ year y_;
+ month m_;
+ year_month(year y, month m) BOOST_NOEXCEPT
+ : y_(y),
+ m_(m)
+ {
+ }
+
+ friend year_month operator/(year y, month m) BOOST_NOEXCEPT
+ {
+ return year_month(y, m);
+ }
+ friend date operator/(year_month, day);
+ int days_in() BOOST_NOEXCEPT;
+ };
+
+ class month_day
+ {
+ month m_;
+ day d_;
+ month_day(month m, day d) BOOST_NOEXCEPT
+ : m_(m),
+ d_(d)
+ {
+ }
+ friend month_day make_month_day(month m, day d) BOOST_NOEXCEPT;
+
+ friend month_day operator/(month m, day d) BOOST_NOEXCEPT;
+ friend month_day operator/(day d, month m) BOOST_NOEXCEPT;
+ friend date operator/(month_day, year);
+ };
+
+ extern const month_day
+ jan_01, jan_02, jan_03, jan_04, jan_05, jan_06, jan_07, jan_08, jan_09,
+ jan_10, jan_11, jan_12, jan_13, jan_14, jan_15, jan_16, jan_17, jan_18,
+ jan_19, jan_20, jan_21, jan_22, jan_23, jan_24, jan_25, jan_26, jan_27,
+ jan_28, jan_29, jan_30, jan_31
+ // ...
+ ;
+
+
+ inline month_day operator/(month m, day d) BOOST_NOEXCEPT
+ {
+ return month_day(m, d);
+ }
+ inline month_day operator/(day d, month m) BOOST_NOEXCEPT
+ {
+ return month_day(m, d);
+ }
+
+ namespace detail
+ {
+ template <class T, int>
+ class duration_type
+ {
+ public:
+ typedef T rep;
+ private:
+ public:
+ rep x_;
+ public:
+ explicit duration_type(rep x = rep()) BOOST_NOEXCEPT : x_(x)
+ {
+ }
+
+ rep count() const BOOST_NOEXCEPT
+ {
+ return x_;
+ }
+
+ duration_type operator+() const BOOST_NOEXCEPT
+ {
+ return *this;
+ }
+ duration_type operator-() const BOOST_NOEXCEPT
+ {
+ return duration_type(-x_);
+ }
+
+ duration_type& operator++() BOOST_NOEXCEPT
+ {
+ ++x_;
+ return *this;
+ }
+ duration_type operator++(int) BOOST_NOEXCEPT
+ {
+ return duration_type(x_++);
+ }
+ duration_type& operator--() BOOST_NOEXCEPT
+ {
+ --x_;
+ return *this;
+ }
+ duration_type operator--(int) BOOST_NOEXCEPT
+ {
+ return duration_type(x_--);
+ }
+
+ duration_type& operator+=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ += rhs.x_;
+ return *this;
+ }
+ duration_type& operator-=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ -= rhs.x_;
+ return *this;
+ }
+
+ friend duration_type operator+(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x += y;
+ return x;
+ }
+ friend duration_type operator-(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x -= y;
+ return x;
+ }
+
+ duration_type& operator*=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ *= rhs;
+ return *this;
+ }
+ duration_type& operator/=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ /= rhs;
+ return *this;
+ }
+ duration_type& operator%=(const rep& rhs) BOOST_NOEXCEPT
+ {
+ x_ %= rhs;
+ return *this;
+ }
+ duration_type& operator%=(const duration_type& rhs) BOOST_NOEXCEPT
+ {
+ x_ %= rhs.x_;
+ return *this;
+ }
+
+ friend duration_type operator*(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x *= y;
+ return x;
+ }
+ friend duration_type operator*(rep x, duration_type y) BOOST_NOEXCEPT
+ {
+ y *= x;
+ return y;
+ }
+ friend duration_type operator/(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x /= y;
+ return x;
+ }
+ friend rep operator/(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ / y.x_;
+ }
+ friend duration_type operator%(duration_type x, rep y) BOOST_NOEXCEPT
+ {
+ x %= y;
+ return x;
+ }
+ friend duration_type operator%(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ x %= y.x_;
+ return x;
+ }
+
+ friend bool operator==(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ friend bool operator!=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ friend bool operator< (duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+ friend bool operator> (duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ friend bool operator<=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ friend bool operator>=(duration_type x, duration_type y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+ friend class date;
+ };
+ }
+
+ typedef detail::duration_type<int32_t, 1> months;
+ typedef detail::duration_type<int32_t, 2> years;
+
+ class date
+ {
+#if DESIGN == 1
+ // Store x, y/m/d, n, dow
+ uint32_t x_;
+ int16_t y_;
+ uint16_t m_ : 4;
+ uint16_t d_ : 5;
+ uint16_t leap_ : 1;
+ uint16_t n_ : 3;
+ uint16_t dow_ : 3;
+#elif DESIGN == 2
+ // Store x, n, dow
+ uint32_t x_ : 26;
+ uint32_t n_ : 3;
+ uint32_t dow_ : 3;
+#elif DESIGN == 3
+ // Store y/m/d, n, dow
+ int16_t y_;
+ uint16_t m_ : 4;
+ uint16_t d_ : 5;
+ uint16_t leap_ : 1;
+ uint16_t n_ : 3;
+ uint16_t dow_ : 3;
+#endif
+
+
+ friend date operator/(year_month ym, day d);
+ friend date operator/(month_day md, year y);
+ public:
+ date(chrono::year, chrono::month, chrono::day);
+ date(chrono::year, chrono::month, chrono::day, no_check_t);
+
+ static date today() BOOST_NOEXCEPT;
+
+ date() BOOST_NOEXCEPT;
+
+ explicit date(boost::chrono::system_clock::time_point tp);
+ // explicit
+ operator boost::chrono::system_clock::time_point () const;
+
+#if DESIGN == 1 || DESIGN == 3
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(d_,no_check);
+ }
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(m_,no_check);
+ }
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(y_,no_check);
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_;
+ }
+#elif DESIGN == 2
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(day_from_day_number(),no_check);
+ }
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(month_from_day_number(),no_check);
+ }
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(year_from_day_number(),no_check);
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_from_day_number();
+ }
+#endif
+#if DESIGN == 1 || DESIGN == 2
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((x_+1) % 7,no_check);
+ }
+#elif DESIGN == 3
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((day_number_from_ymd()+1) % 7,no_check);
+ }
+#endif
+
+ date& operator+=(days d);
+ date& operator++()
+ {
+ return *this += days(1);
+ }
+ date operator++(int)
+ {
+ date tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+ date& operator-=(days d)
+ {
+ return *this += -d;
+ }
+ date& operator--()
+ {
+ return *this -= days(1);
+ }
+ date operator--(int)
+ {
+ date tmp(*this); --(*this); return tmp;
+ }
+
+ friend date operator+(date dt, days d)
+ {
+ dt += d;
+ return dt;
+ }
+ friend date operator+(days d, date dt)
+ {
+ dt += d;
+ return dt;
+ }
+ friend date operator-(date dt, days d)
+ {
+ dt -= d;
+ return dt;
+ }
+#if DESIGN == 1 || DESIGN == 2
+ friend days operator-(date x, date y) BOOST_NOEXCEPT
+ {
+ return days(x.x_ - y.x_);
+ }
+#elif DESIGN == 3
+ friend days operator-(date x, date y) BOOST_NOEXCEPT
+ {
+ return days(x.day_number_from_ymd() - y.day_number_from_ymd());
+ }
+#endif
+
+ date& operator+=(months m);
+ date& operator-=(months m)
+ {
+ return *this += months(-m.x_);
+ }
+
+ friend date operator+(date dt, months m)
+ {
+ dt += m;
+ return dt;
+ }
+ friend date operator+(months m, date dt)
+ {
+ dt += m;
+ return dt;
+ }
+ friend date operator-(date dt, months m)
+ {
+ dt -= m;
+ return dt;
+ }
+
+ date& operator+=(years y);
+ date& operator-=(years y)
+ {
+ return *this += years(-y.x_);
+ }
+
+ friend date operator+(date dt, years y)
+ {
+ dt += y;
+ return dt;
+ }
+ friend date operator+(years y, date dt)
+ {
+ dt += y;
+ return dt;
+ }
+ friend date operator-(date dt, years y)
+ {
+ dt -= y;
+ return dt;
+ }
+
+#if DESIGN == 1 || DESIGN == 2
+ friend bool operator==(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ friend bool operator< (const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+#elif DESIGN == 3
+ friend bool operator==(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return x.y_ == y.y_ && x.m_ == y.m_ && x.d_ == y.d_;
+ }
+ friend bool operator< (const date& x, const date& y)
+ {
+ return x.y_ < y.y_ ||
+ (!(y.y_ < x.y_) && (x.m_ < y.m_ ||
+ (!(y.m_ < x.m_) && x.d_ < y.d_)));
+ }
+#endif
+ friend bool operator!=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ friend bool operator> (const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ friend bool operator<=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ friend bool operator>=(const date& x, const date& y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+#if DESIGN == 2
+ private:
+ uint16_t day_from_day_number() const BOOST_NOEXCEPT;
+ uint16_t month_from_day_number() const BOOST_NOEXCEPT;
+ int16_t year_from_day_number() const BOOST_NOEXCEPT;
+ bool leap_from_day_number() const BOOST_NOEXCEPT;
+#elif DESIGN == 3
+ uint32_t day_number_from_ymd() const BOOST_NOEXCEPT;
+#endif
+ };
+
+ inline date operator/(year_month ym, day d)
+ {
+ return date(ym.y_, ym.m_, d);
+ }
+ inline date operator/(month_day md, year y)
+ {
+ return date(y, md.m_, md.d_);
+ }
+ inline date operator/(year_month ym, int d)
+ {
+ return ym / day(d);
+ }
+ inline date operator/(month_day md, int y)
+ {
+ return md / year(y);
+ }
+
+ inline
+ date
+ operator<(weekday wd, date x)
+ {
+ const int a = static_cast<int>(wd);
+ const int b = static_cast<int>(x.get_weekday());
+ if (a < b)
+ {
+ return x - days(b-a);
+ }
+ return x - days(7 - (a-b));
+ }
+
+ inline
+ date
+ operator<=(weekday wd, date x)
+ {
+ const int a = static_cast<int>(wd);
+ const int b = static_cast<int>(x.get_weekday());
+ if (a <= b)
+ {
+ return x - days(b-a);
+ }
+ return x - days(7 - (a-b));
+ }
+
+ inline
+ date
+ operator>(weekday wd, date x)
+ {
+ const int a = static_cast<int>(x.get_weekday());
+ const int b = static_cast<int>(wd);
+ if (a < b)
+ {
+ return x + days(b-a);
+ }
+ return x + days(7 - (a-b));
+ }
+
+ inline
+ date
+ operator>=(weekday wd, date x)
+ {
+ const int a = static_cast<int>(x.get_weekday());
+ const int b = static_cast<int>(wd);
+ if (a <= b)
+ {
+ return x + days(b-a);
+ }
+ return x + days(7 - (a-b));
+ }
+
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/tmp/xx.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tmp/xx.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,7712 @@
+//
+// (C) Copyright Howard Hinnant
+// (C) Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+
+#ifndef BOOST_CHRONO_IO_DURATION_GET_HPP
+#define BOOST_CHRONO_IO_DURATION_GET_HPP
+
+#include <boost/chrono/config.hpp>
+#include <string>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_signed.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/math/common_factor_rt.hpp>
+#include <boost/chrono/detail/scan_keyword.hpp>
+#include <boost/assert.hpp>
+#include <locale>
+/**
+ * Duration formatting facet for input.
+ */
+namespace boost
+{
+ namespace chrono
+ {
+
+ namespace detail
+ {
+ template <class Rep, bool = is_scalar<Rep>::value>
+ struct duration_io_intermediate
+ {
+ typedef Rep type;
+ };
+
+ template <class Rep>
+ struct duration_io_intermediate<Rep, true>
+ {
+ typedef typename mpl::if_c<is_floating_point<Rep>::value, long double, typename mpl::if_c<
+ is_signed<Rep>::value, long long, unsigned long long>::type>::type type;
+ };
+
+ template <typename intermediate_type>
+ typename enable_if<is_integral<intermediate_type>, bool>::type
+ reduce(intermediate_type& r, unsigned long long& den, std::ios_base::iostate& err)
+ {
+ typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
+
+ // Reduce r * num / den
+ common_type_t t = math::gcd<common_type_t>(common_type_t(r), common_type_t(den));
+ r /= t;
+ den /= t;
+ if (den != 1)
+ {
+ // Conversion to Period is integral and not exact
+ err |= std::ios_base::failbit;
+ return false;
+ }
+ return true;
+ }
+ template <typename intermediate_type>
+ typename disable_if<is_integral<intermediate_type>, bool>::type
+ reduce(intermediate_type& , unsigned long long& , std::ios_base::iostate& )
+ {
+ return true;
+ }
+
+ }
+
+ /**
+ * @c duration_get is used to parse a character sequence, extracting
+ * components of a duration into a class duration.
+ * Each get member parses a format as produced by a corresponding format specifier to time_put<>::put.
+ * If the sequence being parsed matches the correct format, the
+ * corresponding member of the class duration argument are set to the
+ * value used to produce the sequence;
+ * otherwise either an error is reported or unspecified values are assigned.
+ * In other words, user confirmation is required for reliable parsing of
+ * user-entered durations, but machine-generated formats can be parsed
+ * reliably. This allows parsers to be aggressive about interpreting user
+ * variations on standard formats.
+ *
+ * If the end iterator is reached during parsing of the get() member
+ * function, the member sets std::ios_base::eofbit in err.
+ */
+ template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> >
+ class duration_get: public std::locale::facet
+ {
+ public:
+ /**
+ * Type of character the facet is instantiated on.
+ */
+ typedef CharT char_type;
+ typedef std::basic_string<CharT> string_type;
+ /**
+ * Type of iterator used to scan the character buffer.
+ */
+ typedef InputIterator iter_type;
+
+ /**
+ * Construct a @c duration_get facet.
+ * @param refs
+ * @Effects Construct a @c duration_get facet.
+ * If the @c refs argument is @c 0 then destruction of the object is
+ * delegated to the @c locale, or locales, containing it. This allows
+ * the user to ignore lifetime management issues. On the other had,
+ * if @c refs is @c 1 then the object must be explicitly deleted;
+ * the @c locale will not do so. In this case, the object can be
+ * maintained across the lifetime of multiple locales.
+ */
+
+ explicit duration_get(size_t refs = 0) :
+ std::locale::facet(refs)
+ {
+ }
+
+ /**
+ * @param s start input stream iterator
+ * @param end end input stream iterator
+ * @param ios a reference to a ios_base
+ * @param err the ios_base state
+ * @param d the duration
+ * @param pattern begin of the formatting pattern
+ * @param pat_end end of the formatting pattern
+ *
+ * Requires: [pattern,pat_end) shall be a valid range.
+ *
+ * Effects: The function starts by evaluating err = std::ios_base::goodbit.
+ * It then enters a loop, reading zero or more characters from s at
+ * each iteration. Unless otherwise specified below, the loop
+ * terminates when the first of the following conditions holds:
+ * - The expression pattern == pat_end evaluates to true.
+ * - The expression err == std::ios_base::goodbit evaluates to false.
+ * - The expression s == end evaluates to true, in which case the
+ * function evaluates err = std::ios_base::eofbit | std::ios_base::failbit.
+ * - The next element of pattern is equal to Õ%Õ, followed by a conversion
+ * specifier character, format.
+ * If the number of elements in the range [pattern,pat_end) is not
+ * sufficient to unambiguously determine whether the conversion
+ * specification is complete and valid, the function evaluates
+ * err = std::ios_base::failbit. Otherwise, the function evaluates
+ * s = do_get(s, end, ios, err, d). If err == std::ios_base::goodbit holds after
+ * the evaluation of the expression, the function increments pattern to
+ * point just past the end of the conversion specification and continues
+ * looping.
+ * - The expression isspace(*pattern, ios.getloc()) evaluates to true, in
+ * which case the function first increments pattern until
+ * pattern == pat_end || !isspace(*pattern, ios.getloc()) evaluates to true,
+ * then advances s until s == end || !isspace(*s, ios.getloc()) is true,
+ * and finally resumes looping.
+ * - The next character read from s matches the element pointed to by
+ * pattern in a case-insensitive comparison, in which case the function
+ * evaluates ++pattern, ++s and continues looping. Otherwise, the function
+ * evaluates err = std::ios_base::failbit.
+ *
+ * Returns: s
+ */
+ template <typename Rep, typename Period>
+ iter_type get(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err,
+ duration<Rep, Period> &d, const char_type *pattern, const char_type *pat_end) const
+ {
+
+ typedef typename detail::duration_io_intermediate<Rep>::type intermediate_type;
+ intermediate_type r;
+ detail::rt_ratio rt;
+ bool value_found=false, unit_found=false, loc_found=false;
+
+ const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc());
+ err = std::ios_base::goodbit;
+ while (pattern != pat_end && err == std::ios_base::goodbit)
+ {
+ if (s == end)
+ {
+ err |= std::ios_base::eofbit;
+ break;
+ }
+ if (ct.narrow(*pattern, 0) == '%')
+ {
+ if (++pattern == pat_end)
+ {
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ char cmd = ct.narrow(*pattern, 0);
+ switch (cmd)
+ {
+ case 'v':
+ {
+ if (value_found) {
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ if (value_found) {
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ value_found=true;
+ s=get_value(s, end, ios, err, r);
+ if ( err & (std::ios_base::badbit |std::ios_base::failbit) )
+ {
+ return s;
+ }
+ break;
+ }
+ case 'u':
+ {
+ if (unit_found) {
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ unit_found=true;
+ s = get_unit(s, end, ios, err, rt);
+ if ( err & (std::ios_base::badbit |std::ios_base::failbit) )
+ {
+ return s;
+ }
+ break;
+ }
+ case 'x':
+ {
+ if (unit_found || value_found || loc_found) {
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ loc_found=true;
+ string_type pat = duration_units<CharT>::imbue_if_has_not(ios).get_pattern();
+ if (pattern+1 != pat_end)
+ pat.append(pattern+1, pat_end);
+ pattern = pat.data();
+ pat_end = pattern + pat.size();
+ break;
+ }
+ default:
+ BOOST_ASSERT(false && "Boost::Chrono internal error.");
+ break;
+ }
+
+ ++pattern;
+ }
+ else if (ct.is(std::ctype_base::space, *pattern))
+ {
+ for (++pattern; pattern != pat_end && ct.is(std::ctype_base::space, *pattern); ++pattern)
+ ;
+ for ( ; s != end && ct.is(std::ctype_base::space, *s); ++s)
+ ;
+ }
+ else if (ct.toupper(*s) == ct.toupper(*pattern))
+ {
+ ++s;
+ ++pattern;
+ }
+ else {
+ err |= std::ios_base::failbit;
+ }
+
+ }
+
+ unsigned long long num = rt.num;
+ unsigned long long den = rt.den;
+
+ // r should be multiplied by (num/den) / Period
+ // Reduce (num/den) / Period to lowest terms
+ unsigned long long gcd_n1_n2 = math::gcd<unsigned long long>(num, Period::num);
+ unsigned long long gcd_d1_d2 = math::gcd<unsigned long long>(den, Period::den);
+ num /= gcd_n1_n2;
+ den /= gcd_d1_d2;
+ unsigned long long n2 = Period::num / gcd_n1_n2;
+ unsigned long long d2 = Period::den / gcd_d1_d2;
+ if (num > (std::numeric_limits<unsigned long long>::max)() / d2 || den > (std::numeric_limits<
+ unsigned long long>::max)() / n2)
+ {
+ // (num/den) / Period overflows
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ num *= d2;
+ den *= n2;
+
+ typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t;
+
+ // num / den is now factor to multiply by r
+ if (!detail::reduce(r, den, err))
+ return s;
+
+ if (r > ( (duration_values<common_type_t>::max)() / num))
+ {
+ // Conversion to Period overflowed
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ common_type_t t = r * num;
+ t /= den;
+ if (t > 0)
+ {
+ Rep pt = t;
+ if ( (duration_values<Rep>::max)() < pt)
+ {
+ // Conversion to Period overflowed
+ err |= std::ios_base::failbit;
+ return s;
+ }
+ }
+ // Success! Store it.
+ r = Rep(t);
+ d = duration<Rep, Period> (r);
+
+
+ return s;
+ }
+
+ /**
+ *
+ * @param s an input stream iterator
+ * @param ios a reference to a ios_base
+ * @param d the duration
+ * @Effects imbue in @c ios the @c duration_units_default facet if not already present.
+ * Retrieves Stores the duration pattern from the @c duration_unit facet in let say @c str. Last as if
+ * @code
+ * return get(s, end, ios, err, ios, d, str.data(), str.data() + str.size());
+ * @codeend
+ * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name
+ */
+ template <typename Rep, typename Period>
+ iter_type get(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err,
+ duration<Rep, Period> & d) const
+ {
+ std::basic_string < CharT > str = duration_units<CharT>::imbue_if_has_not(ios).get_pattern();
+ return get(s, end, ios, err, d, str.data(), str.data() + str.size());
+ }
+
+ /**
+ *
+ * @param s an input stream iterator
+ * @param ios a reference to a ios_base
+ * @param d the duration
+ * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name
+ */
+ template <typename Rep>
+ iter_type get_value(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, Rep& r) const
+ {
+ return std::use_facet<std::num_get<CharT, iter_type> >(ios.getloc()).get(s, end, ios, err, r);
+ }
+
+ /**
+ *
+ * @param s an output stream iterator
+ * @param ios a reference to a ios_base
+ * @param d the duration
+ * @param pattern
+ * @Effects Calls do_put_unit(s, ios, d).
+ * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name
+ */
+ virtual iter_type do_get_prefix_unit(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err,
+ detail::rt_ratio &rt) const
+ {
+ duration_units<CharT> const &facet = duration_units<CharT>::imbue_if_has_not(is);
+
+ // parse SI name, short or long
+ std::size_t pfs = facet.get_plural_forms()+1;
+
+ // scoped_ptr ???
+ string_type* units= new string_type[19*pfs]();
+ string_type* it = units;
+ it = facet.fill_units(it, atto());
+ it = facet.fill_units(it, femto());
+ it = facet.fill_units(it, pico());
+ it = facet.fill_units(it, nano());
+ it = facet.fill_units(it, micro());
+ it = facet.fill_units(it, milli());
+ it = facet.fill_units(it, centi());
+ it = facet.fill_units(it, deci());
+ it = facet.fill_units(it, deca());
+ it = facet.fill_units(it, hecto());
+ it = facet.fill_units(it, kilo());
+ it = facet.fill_units(it, mega());
+ it = facet.fill_units(it, giga());
+ it = facet.fill_units(it, tera());
+ it = facet.fill_units(it, peta());
+ it = facet.fill_units(it, exa());
+ it = facet.fill_units(it, ratio<1>());
+ it = facet.fill_units(it, ratio<60>());
+ it = facet.fill_units(it, ratio<3600>());
+
+ string_type* units_end= units +19*pfs;
+
+
+ err = std::ios_base::goodbit;
+ const string_type* k = chrono_detail::scan_keyword(i, e, units,
+ units_end,
+ //~ std::use_facet<std::ctype<CharT> >(loc),
+ err);
+
+ std::size_t index = (k - units) / pfs;
+ delete []units;
+ switch ( index )
+ {
+ case 0:
+ rt = detail::rt_ratio(atto());
+ break;
+ case 1:
+ rt = detail::rt_ratio(femto());
+ break;
+ case 2:
+ rt = detail::rt_ratio(pico());
+ break;
+ case 3:
+ rt = detail::rt_ratio(nano());
+ break;
+ case 4:
+ rt = detail::rt_ratio(micro());
+ break;
+ case 5:
+ rt = detail::rt_ratio(milli());
+ break;
+ case 6:
+ rt = detail::rt_ratio(centi());
+ break;
+ case 7:
+ rt = detail::rt_ratio(deci());
+ break;
+ case 8:
+ rt = detail::rt_ratio(deca());
+ break;
+ case 9:
+ rt = detail::rt_ratio(hecto());
+ break;
+ case 10:
+ rt = detail::rt_ratio(kilo());
+ break;
+ case 11:
+ rt = detail::rt_ratio(mega());
+ break;
+ case 12:
+ rt = detail::rt_ratio(giga());
+ break;
+ case 13:
+ rt = detail::rt_ratio(tera());
+ break;
+ case 14:
+ rt = detail::rt_ratio(peta());
+ break;
+ case 15:
+ rt = detail::rt_ratio(exa());
+ break;
+ case 16:
+ rt = detail::rt_ratio(ratio<1>());
+ break;
+ case 17:
+ rt = detail::rt_ratio(ratio<60>());
+ break;
+ case 18:
+ rt = detail::rt_ratio(ratio<3600>());
+ break;
+ default:
+ err = std::ios_base::failbit;
+ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
+ return i;
+ }
+
+ }
+ //template <typename Rep>
+ iter_type get_unit(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err,
+ detail::rt_ratio &rt) const
+ {
+ duration_units<CharT> const &facet = duration_units<CharT>::imbue_if_has_not(is);
+
+ if (*i == '[')
+ {
+ // parse [N/D]s or [N/D]seconds format
+ ++i;
+ i=std::use_facet<std::num_get<CharT, iter_type> >(is.getloc()).get(i, e, is, err, rt.num);
+ if ((err & std::ios_base::failbit) != 0)
+ {
+ return i;
+ }
+
+ if (i==e)
+ {
+ err |= std::ios_base::failbit;
+ return i;
+ }
+ CharT x = *i++;
+ if (x != '/')
+ {
+ err |= std::ios_base::failbit;
+ return i;
+ }
+ i=std::use_facet<std::num_get<CharT, iter_type> >(is.getloc()).get(i, e, is, err, rt.den);
+ if ((err & std::ios_base::failbit) != 0)
+ {
+ return i;
+ }
+ if (i==e)
+ {
+ err |= std::ios_base::failbit;
+ return i;
+ }
+ if (*i != ']')
+ {
+ err |= std::ios_base::failbit;
+ return i;
+ }
+ ++i;
+ if (i==e)
+ {
+ err |= std::ios_base::failbit;
+ return i;
+ }
+ const string_type units[] =
+ {
+ facet.template get_plural_form<ratio<1> >(duration_style::prefix, 1),
+ facet.template get_plural_form<ratio<1> >(duration_style::prefix, 0),
+ facet.template get_plural_form<ratio<1> >(duration_style::symbol, 0)
+ };
+ // FIXME is this necessary?????
+ err = std::ios_base::goodbit;
+ const string_type* k = chrono_detail::scan_keyword(i, e, units,
+ units + sizeof (units) / sizeof (units[0]),
+ //~ std::use_facet<std::ctype<CharT> >(loc),
+ err);
+ switch ( (k - units) / 3)
+ {
+ case 0:
+ break;
+ default:
+ err |= std::ios_base::failbit;
+ return i;
+ }
+ }
+ else
+ {
+ return do_get_prefix_unit(i, e, is, err, rt);
+ }
+ // unit is num/den
+
+ return i;
+ }
+
+ /**
+ * Unique identifier for this type of facet.
+ */
+ static std::locale::id id;
+
+ /**
+ * @Effects Destroy the facet
+ */
+ ~duration_get()
+ {
+ }
+ };
+
+ /**
+ * Unique identifier for this type of facet.
+ */
+ template <class CharT, class InputIterator>
+ std::locale::id duration_get<CharT, InputIterator>::id;
+
+ } // chrono
+}
+// boost
+
+#endif // BOOST_CHRONO_CHRONO_IO_HPP
+
+
+
+////////////////////////////////
+1-1-1
+real 1m23.072s
+user 1m10.769s
+sys 0m10.921s
+
+real 1m21.565s
+user 1m9.964s
+sys 0m10.792s
+
+2-1-1
+real 1m25.853s
+user 1m10.232s
+sys 0m10.905s
+
+real 1m21.732s
+user 1m10.101s
+sys 0m10.744s
+
+2-1-2
+real 1m23.478s
+user 1m10.949s
+sys 0m10.972s
+
+
+3-1-1
+real 1m22.610s
+user 1m10.893s
+sys 0m10.971s
+
+
+3-1-3
+real 1m21.687s
+user 1m10.086s
+sys 0m10.824s
+
+
+3-3-3
+real 1m21.520s
+user 1m9.906s
+sys 0m10.823s
+
+real 1m23.354s
+user 1m9.983s
+sys 0m10.753s
+
+
+#ifdef CCCCCC
+Howard Hinnant
+====================================
+ Autres options 23 aožt, 20:26
+On Aug 23, 2011, at 2:15 PM, Nevin Liber wrote:
+
+> On 23 August 2011 12:34, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+>> If someone wants to go to the trouble to set up a real mailing list, knock yourself out! :-)
+
+> I'm setting up kona-date-lib_at_googlegroups.com. Invites going out shortly.
+> --
+> Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+Thanks Nevin, I've joined.
+
+Howard
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 23 aožt, 21:56
+On Aug 23, 2011, at 3:38 PM, j..._at_[hidden] wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I'm probably not a good person to answer this question (too much bias). There are attendees here who can answer much better.
+
+I got the impression that few (maybe one) liked the library. But I also got the impression that different people disliked or liked different parts. For example I know that John L. really disliked the storage of meta-data in the date class to influence the behavior of year and month arithmetic, while the same data did not influence the behavior of date comparison. Others found the use of forward slash for date construction "too cute", and yet others didn't seem to mind it. I recall one comment that the library should support the forth ordering supported by time_get: ydm. But I also got the impression that others believe we need only support ymd.
+
+There was significant talk that the library conflated the ideas of a date with a calendar. Or something like that. I'm not currently qualified to address that issue. Though I believe Alan has some ideas in this area.
+
+Bottom line: if you were to lock me away in solitary confinement for the next 5 months and ask me to rewrite that proposal based on the feedback from Bloomington, I seriously doubt I could improve it much. Thus the purpose of this group. I think as a collective we have a much better chance. And I think we should start, at least at first, with pretty much a clean sheet, as opposed to build upon my proposal.
+
+I encourage others to help me answer Jeff's question.
+
+Howard
+
+PS: Hopefully we'll get the google group problems ironed out soon. For now my plan is to double-post.
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 23 aožt, 22:24
+On 23 August 2011 22:56, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+> I got the impression that few (maybe one) liked the library. But I also got the impression that different people disliked or liked different parts. For example I know that John L. really disliked the storage of meta-data in the date class to influence the behavior of year and month arithmetic, while the same data did not influence the behavior of date comparison. Others found the use of forward slash for date construction "too cute", and yet others didn't seem to mind it. I recall one comment that the library should support the forth ordering supported by time_get: ydm. But I also got the impression that others believe we need only support ymd.
+
+The construction gave me pause, and I do think it's
+
+1) too cute
+2) counterintuitive for my locale (we use dot, others use dash)
+3) dangerous if I happen to pass such date types to unconstrained
+generic code that uses operator/,
+as such code may compile fine but do weird things.
+
+I'd prefer sticking to yyyy followed by mm followed by dd, or
+otherwise not forcing any order. I don't like
+that it can recognize raw numbers as the third component magically if
+two components are specified.
+
+Providing just a gregorian calendar seems fine, as the proposal
+indicates that adding other calendar types
+on top of it should be easy.
+
+I feel unease about add_month and such, and the fact that they throw
+an exception if the result is invalid.
+I don't have a clear idea of a better approach, though. I suppose many
+users will like such functions.
+
+Regarding what John W said, I'd prefer standardizing the bare
+essentials and providing ranges and such
+separately.
+
+Just my 0.02.
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 23 aožt, 22:32
+2011/8/23 Ville Voutilainen <ville.voutilai..._at_[hidden]>:
+
+> On 23 August 2011 22:56, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+>> I got the impression that few (maybe one) liked the library. But I also got the impression that different people disliked or liked different parts. For example I know that John L. really disliked the storage of meta-data in the date class to influence the behavior of year and month arithmetic, while the same data did not influence the behavior of date comparison. Others found the use of forward slash for date construction "too cute", and yet others didn't seem to mind it. I recall one comment that the library should support the forth ordering supported by time_get: ydm. But I also got the impression that others believe we need only support ymd.
+
+> The construction gave me pause, and I do think it's
+
+> 1) too cute
+> 2) counterintuitive for my locale (we use dot, others use dash)
+
+Actually I found the approach rather natural, similar to the choice
+of operator/ in the file system proposal, even though this is not
+the correct separator for each system.
+
+> 3) dangerous if I happen to pass such date types to unconstrained
+> generic code that uses operator/,
+> as such code may compile fine but do weird things.
+
+The same argument would apply for the file system proposal
+and I have never heard of problems of users among my
+colleagues with this decision.
+
+> I'd prefer sticking to yyyy followed by mm followed by dd, or
+> otherwise not forcing any order. I don't like
+> that it can recognize raw numbers as the third component magically if
+> two components are specified.
+
+I'm neutral on this one, but I found Howard's approach so type-safe,
+that I didn't have problems with the possible diversity.
+
+> Providing just a gregorian calendar seems fine, as the proposal
+> indicates that adding other calendar types
+> on top of it should be easy.
+
+I agree.
+
+> I feel unease about add_month and such, and the fact that they throw
+> an exception if the result is invalid.
+> I don't have a clear idea of a better approach, though. I suppose many
+> users will like such functions.
+
+Maybe we could use an approach that allows both choices via
+system errors (See also file system library).
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Jeff Garland
+====================================
+ Autres options 23 aožt, 23:02
+
+ > Could you elaborate on the concerns expressed by the lwg to help us
+
+> > understand what they liked and what they didn't?
+
+> I'm probably not a good person to answer this question (too much bias).
+> There are attendees here who can answer much better.
+
+> Sure, it's always subjective, but if there's some clear objection to a
+
+particular element then that can be addressed directly.
+
+> I got the impression that few (maybe one) liked the library. But I also
+> got the impression that different people disliked or liked different parts.
+> For example I know that John L. really disliked the storage of meta-data
+> in the date class to influence the behavior of year and month arithmetic,
+> while the same data did not influence the behavior of date comparison.
+> Others found the use of forward slash for date construction "too cute", and
+> yet others didn't seem to mind it. I recall one comment that the library
+> should support the forth ordering supported by time_get: ydm. But I also
+> got the impression that others believe we need only support ymd.
+
+Ok.
+
+> There was significant talk that the library conflated the ideas of a date
+> with a calendar. Or something like that. I'm not currently qualified to
+> address that issue. Though I believe Alan has some ideas in this area.
+
+Sure. There's date-time libraries that isolate the details of a calendar
+representation explicitly into a single class while maintaining a 'universal
+internal representation'. If you read Calendrical Calculations or look at a
+Java library like Joda you'll see this design. In boost date time v1 it's
+separate in the implementation with the intent that new calendar types could
+be plugged in with minimal effort -- frankly I never got more than a handful
+of requests for other calendars over a ten year period so there wasn't much
+motivation. The typical tradeoff here is a '2 object construction' -- where
+you need a calendar to construct a date -- in sacrifices usability in my
+view.
+
+BTW, some people on the list may not be aware of the previous papers I've
+presented to the committee -- the first N1900 is a scope outline and
+discussion --
+
+http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1900.pdf --
+concepts and basic library outline
+http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2058.html -- first
+cut at real wording -- after working the thread stuff I realize how
+inadequate it is...
+
+Honestly, I think there's much of the motivation / need documented in these.
+Needless to say, these will be the starting point for my effort. Note that
+the "huge" problem I see in what's represented there is the complexity of
+the proposal -- it's going to be hard for the lwg to swallow -- again, this
+opinion coming from seeing how hard it was to get agreement on the chrono
+api. Still I'm inclined to shoot higher than Howard's date proposal....
+
+> Bottom line: if you were to lock me away in solitary confinement for the
+> next 5 months and ask me to rewrite that proposal based on the feedback from
+> Bloomington, I seriously doubt I could improve it much. Thus the purpose of
+> this group. I think as a collective we have a much better chance. And I
+> think we should start, at least at first, with pretty much a clean sheet, as
+> opposed to build upon my proposal.
+
+> I encourage others to help me answer Jeff's question.
+
+Please do.
+
+> Howard
+
+> PS: Hopefully we'll get the google group problems ironed out soon. For
+> now my plan is to double-post.
+
+Seems to be working for me now.
+
+Jeff
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 23 aožt, 23:19
+On 23 August 2011 23:32, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+> Actually I found the approach rather natural, similar to the choice
+> of operator/ in the file system proposal, even though this is not
+> the correct separator for each system.
+> The same argument would apply for the file system proposal
+> and I have never heard of problems of users among my
+> colleagues with this decision.
+
+I'll go shoot down the filesystem proposal separately, then. :) In
+this discussion,
+I'm planning to stick to the date proposal.
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 24 aožt, 20:18
+2011/8/24 JOHN LAKOS, BLOOMBERG/ 731 LEXIN <jla..._at_[hidden]>:
+
+> Hi All,
+
+> Based on what I have seen so far, I would like to state what I see are
+> essential requirements for any standardized (reusable) date type. Note that I have omitted 'constexpr' and 'noexcept'; they shall be added where appropriate.
+
+> 1. The date type is *value* *semantic*:
+> + its *salient* *attributes* are 'year', 'month', 'day' -- nothing else!
+
+OK.
+
+> 2. An invariant of a date object is that it represents a valid date value.
+> + Note that Not-A-Date is better represented externally (e.g., boost
+> 'optional', or our 'Nullable') so as not to force checking on each use.
+> + Also, nans in doubles are a problem when it comes to value semantics as
+> operator== is no longer a post condition of copy construction. (I would
+> not want to use 'double' as a model for other types.)
+
+I can accept this pov, even though NaD is often useful itself, but I'm not
+strongly asking for it.
+
+> 3. There is a way to set a date's value without validating it.
+
+Yes.
+
+> 4. There is a way to validate a date value, without creating a date object.
+
+Fine.
+
+> 5. The date class is *not* a template class (it doesn't take an allocator).
+
+I don't see need for an allocator, but I would not at this point in the design
+phase exclude a template. Underlying representation can be one useful
+choice. If we combine the duration library with the date library, this
+might naturally follow (but I'm not trying to enforce this now. I was fine
+with Howard's initial suggestion w/o this feature).
+
+> 6. The date class assumes a simple standard calendar (e.g., Proleptic
+> Gregorian, as in Howard's proposal).
+> + Conversions to/from dates in other calendars are higher-level utilities.
+> + (See 10. Below.)
+
+Yes.
+
+> 7. There is no mention of 'epoch', only a valid range of supported dates.
+
+OK.
+
+> 8. The class is maximally fast (otherwise it is not generally usable):
+> + Creating an invalid date is undefined behavior (not an exception).
+> + Exceeding the valid range is undefined behavior (not an exception).
+> + Note that the imp is "allowed" to check and throw, but not required to.
+> + (Will discuss more in the context of a new proposed assert facility).
+
+It is very easy to make input error in dates. I would strongly object for not
+having at least a chance for a portable, checked construction that
+would through.
+As an alternative suggestion to the above I would suggest the combination of
+
+a) Exception per default
+
+b) If you provide an error_code object as argument, no exception will be
+thrown, but an error value will be set.
+
+> 9. There are essentially no non-primitive operations.
+> + Non-instance method: bool isValidYearMonthDay(int, int, int);
+
+This looks like an error-prone approach, if you need to write
+
+if (isValidYearMonthDay(1993, 09, 31))
+ throw ...
+
+date d(1993, 08, 31);
+ ^^
+
+Strongly opposed.
+
+> + Default ctor, copy ctor & assign, trivial dtor.
+> + Value ctors that takes 'year', 'month', and 'day' (w/without tag types).
+
+> + Manipulator to set 'year', 'month', 'day' at once that returns 'void'.
+> * e.g., void setYearMonthDay(int year, int month, int day);
+> * The behavior is UNDEFINED if these do not represent a valid date.
+> + Manipulator to set 'year', 'month', 'day' at once that returns 'bool'.
+> * e.g., bool setYearMonthDayifValid(int year, int month, int day);
+> * The operation returns 'true' if valid, and 'false' (with no effect)
+> otherwise.
+
+Concerning error handling see above. Why isn't month an enum, too?
+
+> + Accessors to get 'year', 'month', 'day' separately.
+> + An accessor to get 'year', 'month', 'day' all at once.
+> + An accessor to get the day-of-week (as an enum 0-6).
+
+OK.
+
+> + The following operators:
+> // member
+> * date& operator+=(int days); // add days to this date
+> * date& operator-=(int days); // subtract days from date
+> // free
+> * ostream& operator<<(ostream&, const date&)// human-readable format
+> * istream& operator>>(istream&, date&); // (optional, not necessary)
+
+What about: We may want to separate IO into a different header?
+
+- Afficher le texte des messages prŽcŽdents -
+
+I haven't thought about this hierarchy yet, but will do.
+
+> I am sure that we will have lot's of interesting discussions about all this stuff. Let's get going...
+
+I agree.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 24 aožt, 21:48
+[Note: we are down to one person who has not yet accepted the invite
+to be on the mailing list]
+
+On 24 August 2011 12:45, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+
+<jla..._at_[hidden]> wrote:
+> 2. An invariant of a date object is that it represents a valid date value.
+
+I agree.
+
+> + Note that Not-A-Date is better represented externally (e.g., boost
+> 'optional', or our 'Nullable') so as not to force checking on each use.
+
+I'm still on the fence on this one.
+
+> + Also, nans in doubles are a problem when it comes to value semantics as
+> operator== is no longer a post condition of copy construction. (I would
+> not want to use 'double' as a model for other types.)
+
+I agree for so many reasons. Dates should have a SWO (doubles don't
+because of nans so they can't be used as keys in ordered containers),
+sortable, etc.
+
+> 5. The date class is *not* a template class (it doesn't take an allocator).
+
+Is it because you want to rule out allocators (heap allocations which
+imply exceptions) or just because it makes the class harder to use? I
+agree that there shouldn't be heap allocations (we want this class to
+be fast), but on the fence on ruling out templates (not that I see a
+use for them yet; we obviously shouldn't put them in just because we
+can).
+
+> 8. The class is maximally fast (otherwise it is not generally usable):
+> + Creating an invalid date is undefined behavior (not an exception).
+> + Exceeding the valid range is undefined behavior (not an exception).
+> + Note that the imp is "allowed" to check and throw, but not required to.
+> + (Will discuss more in the context of a new proposed assert facility).
+
+Not sure that I agree with the viewpoint that not meeting class
+invariants should always result in undefined behavior instead of
+exceptions being thrown. That discussion is probably better when you
+present your assert facility (I think that decision is mostly
+orthogonal to defining the rest of the interface).
+
+> 9. There are essentially no non-primitive operations.
+> + Non-instance method: bool isValidYearMonthDay(int, int, int);
+
+I don't want to see any interface taking multiple ints; way too error
+prone. Get things into the type system as quickly as possible. I'd
+like to see primitive types for Year, Month and Day. I'd rather see:
+
+bool isValidDate(Year, Month, Day)
+
+Note: I have no strong opinion on whether to support all permutations
+(isValidDate(Month, Day, Year), isValidDate(Day, Month, Year), etc.)
+or not, nor on whether the parameters should be passed in by value vs.
+const reference.
+
+(Similar comment for other interfaces.)
+
+> + The following operators:
+> // member
+> * date& operator+=(int days); // add days to this date
+> * date& operator-=(int days); // subtract days from date
+
+Shouldn't take ints; should take a Days type which represents a
+duration and is different from Day.
+
+Still digesting the higher level utilities...
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 24 aožt, 22:06
+Hey Daniel,
+
+I must say I am both pleased and a bit surprised with the amount of agreement, and/or lack of disagreement that you seemed to have with this initial cut
+at date type requrements. I will wait to hear what other think for most of this doc, but I do want to respond to your "strong opposition" to a small part of "point 9." now, so that perhaps I can clarify what I am getting at:
+
+>> 9. There are essentially no non-primitive operations.
+>> + Non-instance method: bool isValidYearMonthDay(int, int, int);
+
+>This looks like an error-prone approach, if you need to write
+
+>if (isValidYearMonthDay(1993, 09, 31))
+> throw ...
+
+>date d(1993, 08, 31);
+> ^^
+
+>Strongly opposed.
+
+Daniel, There are a number of important issues to address here.
+
+First of all, you (or at least I) would never write code like this. Note that there was a manipulator in point 9...
+
+ bool setYearMonthDateIfValid(int year, int month, int day).
+ // Set this date to the indicated value and return 'true' if the
+ // specified 'year', 'month', and 'day' represent a valid date
+ // value; othrwise return 'false' with no effect.
+
+that avoids your having repeate the literal date value:
+
+ date d;
+ if (!d.setYearMonthDayIfValid(1993, 09, 31)) throw 'logic_error';
+ // ...
+
+Except that I would not throw here either. The problem is that some inputs
+are known to be good, and some are not. For those inputs that are known to
+be good, the extra if to check to see if the date is valid is not viable in
+many important practical contexts. In finacial calculations in particular,
+the cost of the 'if' could make or break the system. That said, there are other
+situations in which checking is exacatly the right answer! But we can't have
+it both ways! Or can we? As a matter of fact we can!
+
+By specifying that constructing or setting a date to an invalid value is UNDEFINED BEHAVIOR, we allow for the possibility of a robust implemenation to detect the error in a CHECKED BUILD MODE. This new, very general proposed approach to "defensive programming done right" (paper in Kona) will allow the applciation developer to:
+
+ (1) specify with some granularity how much checking should be done at
+ runtime: (a) none, (b) some, (c) lots, (d) go for it!, and
+
+ (2) excatly what should happen if a pre-condition violation is detected:
+ (a) abort, (b) throw, (c) spin, (d) <your desired behavior here>.
+
+But if we don't know that the date coming into a system is valid, we will
+not want to construct a date within a try block, because that is absurdly
+inneficent and clunky. Instead I would always address both the 'if' and 'else'
+directly.
+
+ void processRawDateValue(int year, int month, int day)
+ {
+ Date d;
+ if (d.setYearMonthDay(year, month, day) { // if valid value
+ // ...
+ }
+ else { // else invalid value
+ // ...
+ }
+ }
+
+But if we "know" the date is valid, we get two benefits:
+
+(1) We don't have to check it ourselves (and we get the efficiency), and
+(2) in the appropriate build mode, it will be checked automatically for us.
+
+ Date d(1993, 9, 31); // caught in SAFE mode
+ d.setYearMonthDay(1993, 9, 31); // caught in SAFE mode
+
+On the other hand, if we put checking directly into the contract then we check all the time -- whether we need to or not. (I'm strongly opposed to that.)
+
+If we were to make 'setYearMonthDay' return status like 'setYearMonthDayIfValid', then we would have a *wide* contract, and would not
+be able to detect the bug in ANY build mode.
+
+So to sumerize, some people want there pre-conditions checked (sometimes), and some don't. This date facility is a general purpose library that will be used by all sorts of folks. By not putting checking (let alone throwing) into the contract, we widen the applicability of this date type to accommodate EVERY CONCEVABLE APPLICATION.
+
+Note that the notion of having a *narrow* contract that admits this kind of defensive programming is MUCH bigger than the date class, and was the basis
+for our decision in Madrid NOT to decorate ANY narrow contracts with noexcept.
+
+I would be very interested to know if this explaination makes you feel any differently about the non-instance 'isValid' method (which you need never use).
+
+Cheers, John L.
+
+- Afficher le texte des messages prŽcŽdents -
+
+...
+
+plus de dŽtails È
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 24 aožt, 22:32
+2011/8/24 JOHN LAKOS, BLOOMBERG/ 731 LEXIN <jla..._at_[hidden]>:
+
+- Afficher le texte des messages prŽcŽdents -
+
+This would be a rather unique approach in the standard library
+and of little robustness when used.
+
+I would find the approach using an error_code object much more
+appealing for your use case. First, the object in the call is immediately
+alerting the user that this is a narrow contract function. Second, I
+believe that the runtime cost of such a call with an error_code object
+should be basically the same as your suggestion without. Third, the
+information content in case of an error could drastically exceed
+the bare correct-not correct reply of a boolean test.
+
+> that avoids your having repeate the literal date value:
+
+> date d;
+> if (!d.setYearMonthDayIfValid(1993, 09, 31)) throw 'logic_error';
+> // ...
+
+> Except that I would not throw here either. The problem is that some inputs
+> are known to be good, and some are not. For those inputs that are known to
+> be good, the extra if to check to see if the date is valid is not viable in
+> many important practical contexts. In finacial calculations in particular,
+> the cost of the 'if' could make or break the system.
+
+Why? If you have designed the function this way, there must already be
+an implied if() branch *within* setYearMonthDayIfValid, otherwise the function
+could not return the correct result. If the function would either just throw
+instead of returning a "success/failure" result, the overhead should be the
+same. If we add an overload with an error_code object, the user can ignore
+the evaluation of that, or could put the evaluation within a maskable assert
+to have the test conditionally active.
+
+> That said, there are other
+> situations in which checking is exacatly the right answer! But we can't have
+> it both ways! Or can we? As a matter of fact we can!
+
+> By specifying that constructing or setting a date to an invalid value is UNDEFINED BEHAVIOR, we allow for the possibility of a robust implemenation to detect the error in a CHECKED BUILD MODE. This new, very general proposed approach to "defensive programming done right" (paper in Kona) will allow the applciation developer to:
+
+A date class looks like a wrong place for undefined behaviour to me,
+especially because the construction or assignment will perform
+the check internally anyway. Your suggestion simply prevents
+the user to have robust code, because most people won't expect
+the bool result and its meaning. This looks so much like non-C++
+code to me, that I cannot accept it. I understand that user must
+expect undefined behaviour in situations, where the test overhead
+could much exceed the non-failure operation overhead (or is
+impossible), but have not much sympathy for this strategy in case
+of this date example.
+
+> (1) specify with some granularity how much checking should be done at
+> runtime: (a) none, (b) some, (c) lots, (d) go for it!, and
+
+> (2) excatly what should happen if a pre-condition violation is detected:
+> (a) abort, (b) throw, (c) spin, (d) <your desired behavior here>.
+
+> But if we don't know that the date coming into a system is valid, we will
+> not want to construct a date within a try block, because that is absurdly
+> inneficent and clunky.
+
+I have described an approach that would not require a try block.
+
+- Afficher le texte des messages prŽcŽdents -
+
+Exactly, so use an error_code object and ignore it or don't.
+
+This date facility is a general purpose library that will be used by
+all sorts of folks. By not putting checking (let alone throwing) into
+the contract, we widen the applicability of this date type to
+accommodate EVERY CONCEVABLE APPLICATION.
+
+> Note that the notion of having a *narrow* contract that admits this kind of defensive programming is MUCH bigger than the date class, and was the basis
+> for our decision in Madrid NOT to decorate ANY narrow contracts with noexcept.
+
+> I would be very interested to know if this explaination makes you feel any differently about the non-instance 'isValid' method (which you need never use).
+
+Unfortunately not, as I described above.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 25 aožt, 08:17
+
+Il giorno 24/ago/2011, alle ore 22:06, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+
+> By specifying that constructing or setting a date to an invalid value is UNDEFINED BEHAVIOR, we allow for the possibility of a robust implemenation to detect the error in a CHECKED BUILD MODE. This new, very general proposed approach to "defensive programming done right" (paper in Kona) will allow the applciation developer to:
+
+> (1) specify with some granularity how much checking should be done at
+> runtime: (a) none, (b) some, (c) lots, (d) go for it!, and
+
+> (2) excatly what should happen if a pre-condition violation is detected:
+> (a) abort, (b) throw, (c) spin, (d) <your desired behavior here>.
+
+I'm not convinced that going for undefined behaviour is good. It might occur that I need a specific behaviour in a piece of code and a different one in a separate TU of the same program. In large multi-developers projects you will eventually find two programmers that have different programming styles. I'd rather fully specify a few error policies to allow the user select them, for example like this:
+
+----
+struct no_check_t {};
+struct validity_check_t {};
+struct assert_if_invalid_t {};
+struct throw_if_invalid_t {};
+
+class date
+{
+ //...
+
+ // notice: I have the same concerns as Nevin about the signature taking three ints,
+ // but I keep it here for the time being for the sake of discussion
+
+ bool setYearMonthDay(int, int, int, no_check_t); // always returns true
+ bool setYearMonthDay(int, int, int, validity_check_t);
+ bool setYearMonthDay(int, int, int, assert_if_invalid_t);
+ bool setYearMonthDay(int, int, int, throw_if_invalid_t); // always returns true
+
+ // any one of the above, in implementation-defined way (possibly according to a config macro)
+ bool setYearMonthDay(int, int, int);
+
+ // non-throwing, sets error code on error
+ bool setYearMonthDay(int, int, int, std::error_code& ec);
+};
+
+----
+
+Or even allow user-defined policies:
+
+----
+class date
+{
+ //...
+
+ template <class Policy = DEFAULT_POLICY>
+ bool setYearMonthDay(int, int, int, Policy = Policy{});
+
+ template <> bool setYearMonthDay(int, int, int, no_check_t);
+ template <> bool setYearMonthDay(int, int, int, validity_check_t);
+ template <> bool setYearMonthDay(int, int, int, assert_if_invalid_t);
+ template <> bool setYearMonthDay(int, int, int, throw_if_invalid_t);
+ template <> bool setYearMonthDay(int, int, int, std::error_code& ec);
+};
+
+----
+
+Just a thought. Not that I specifically endorse this approach.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Pablo Halpern
+====================================
+ Autres options 25 aožt, 16:25
+On 8/24/2011 4:32 PM, Daniel KrŸgler wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I think this makes sense. Let me reprhase and see if I understand
+correctly. You are suggesting something
+like:
+
+ set year_month_day(int year, int month, int day);
+ set year_month_day(int year, int month, int day, error_code& ec);
+
+The second form is guaranteed error-checked. The first is not.
+
+If this is what you are saying, then you and John (and I) are
+essentially in agreement. The difference
+is basically stylistic and if you think that the style above is more
+consistent with the style of the
+standard, then that's fine.
+
+[...]
+
+> A date class looks like a wrong place for undefined behaviour to me,
+> especially because the construction or assignment will perform
+> the check internally anyway. Your suggestion simply prevents
+> the user to have robust code, because most people won't expect
+> the bool result and its meaning. This looks so much like non-C++
+> code to me, that I cannot accept it. I understand that user must
+> expect undefined behaviour in situations, where the test overhead
+> could much exceed the non-failure operation overhead (or is
+> impossible), but have not much sympathy for this strategy in case
+> of this date example.
+
+Your argument is not convincing. If an implementation chooses not to do
+an inexpensive check, then that is a QOI issue. The point is that, as a
+general matter of principle, we should writing precondition checks into
+the interface because:
+
+1. The way to avoid undefined behavior is to SANITIZE YOUR INPUT. That
+goes for making sure that the date entered by a user is valid and that a
+string entered by the user does not overflow your buffer. The
+validating constructor or is_valid call is there for exactly this
+purpose. Once a date is validated IT NEVER NEEDS TO BE VALIDATED
+AGAIN. Forced validation violates the "you pay for only what you use" rule.
+
+2. A wide contract (one that includes precondition checks and a
+guaranteed action in case the precondition fails) is difficult to change
+in the future. If, in the future, we want to ascribe a new meaning to a
+specific invalid date (say, January 0, 0000), we would break the
+contract, which says that we will THROW in this case.
+
+3. The way to avoid undefined behavior is not to replace it with an
+exception. I have not seen in my career reasonable code that catches
+exceptions as a generalized and robust way to handle bad input. The
+best I have seen is catching exceptions and shutting down gracefully.
+For that to work well in general requires a general facility like the
+kind that John will propose.
+
+Even if precondition checks are cheap for date (because the conditionals
+are already there), that is not sufficient reason to abandon the
+principle. As a matter of fact, however, you can write an unchecked
+date constructor with NO CONDITIONALS AT ALL, as Bloomberg has demonstrated.
+
+[...]
+
+>> Note that the notion of having a *narrow* contract that admits this kind of defensive programming is MUCH bigger than the date class, and was the basis
+>> for our decision in Madrid NOT to decorate ANY narrow contracts with noexcept.
+
+>> I would be very interested to know if this explaination makes you feel any differently about the non-instance 'isValid' method (which you need never use).
+
+> Unfortunately not, as I described above.
+
+Actually, I think you two are converging. The disagreement is on the
+style of specifying the guaranteed-validating vs.
+not-guaranteed-to-validate manipulator. That is a disagreement on
+style, not principle, and I'm sure that can be resolved.
+
+-Pablo
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 25 aožt, 16:32
+2011/8/25 Pablo Halpern <phalp..._at_[hidden]>:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I'm not saying that. I'm suggesting that the first form would throw an
+exception is case of input error, but the second form would not, instead
+it would set the error code value. Whether you evaluate the error_code
+or not, is your business.
+
+>> A date class looks like a wrong place for undefined behaviour to me,
+>> especially because the construction or assignment will perform
+>> the check internally anyway. Your suggestion simply prevents
+>> the user to have robust code, because most people won't expect
+>> the bool result and its meaning. This looks so much like non-C++
+>> code to me, that I cannot accept it. I understand that user must
+>> expect undefined behaviour in situations, where the test overhead
+>> could much exceed the non-failure operation overhead (or is
+>> impossible), but have not much sympathy for this strategy in case
+>> of this date example.
+
+> Your argument is not convincing. If an implementation chooses not to do an
+> inexpensive check, then that is a QOI issue. The point is that, as a
+> general matter of principle, we should writing precondition checks into the
+> interface because:
+
+I don't get your concept of validation. If John's function has to
+return true/false, this is also validation. I'm suggesting to provide
+an overload with the error_code object. John could use this
+and ignore the value of the error_code.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Pablo Halpern
+====================================
+ Autres options 25 aožt, 18:21
+On 8/25/2011 10:32 AM, Daniel KrŸgler wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+But you then don't leave an option to not pay the cost of the check.
+The precondition check
+is in the interface in both cases. That is an unacceptable cost for
+checking for a condition
+that a bug-free program will never see.
+>>> A date class looks like a wrong place for undefined behaviour to me,
+>>> especially because the construction or assignment will perform
+>>> the check internally anyway. Your suggestion simply prevents
+>>> the user to have robust code, because most people won't expect
+>>> the bool result and its meaning. This looks so much like non-C++
+>>> code to me, that I cannot accept it. I understand that user must
+>>> expect undefined behaviour in situations, where the test overhead
+>>> could much exceed the non-failure operation overhead (or is
+>>> impossible), but have not much sympathy for this strategy in case
+>>> of this date example.
+>> Your argument is not convincing. If an implementation chooses not to do an
+>> inexpensive check, then that is a QOI issue. The point is that, as a
+>> general matter of principle, we should writing precondition checks into the
+
+I meant we should *not* be writing precondition checks into the interface.
+>> interface because:
+> I don't get your concept of validation. If John's function has to
+> return true/false, this is also validation. I'm suggesting to provide
+> an overload with the error_code object. John could use this
+> and ignore the value of the error_code.
+
+Because John supplies both a checked and unchecked variant. If you call
+the unchecked variant, you don't pay the cost of the check. I am happy
+to have an overload with an error_code object, but only if it is the
+*only* checked version. The other version should not have precondition
+checking in its interface. It's just too expensive. The C++ standard
+is not about trying to do something "reasonable" in a buggy program. If
+you call the unchecked function, then you'd better be sure that the
+preconditions hold. Often, this is entirely possible, but when it's
+not, you can use the checked version and look at the error code.
+
+-Pablo
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 25 aožt, 19:50
+On Aug 25, 2011, at 12:21 PM, Pablo Halpern wrote:
+
+> The precondition check
+> is in the interface in both cases. That is an unacceptable cost for checking for a condition
+> that a bug-free program will never see.
+
+Perhaps it is time to quantify this cost? 2%? 20%? 200%?
+
+Howard
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 25 aožt, 20:26
+On 25 August 2011 20:50, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+>> The precondition check
+>> is in the interface in both cases. That is an unacceptable cost for checking for a condition
+>> that a bug-free program will never see.
+> Perhaps it is time to quantify this cost? 2%? 20%? 200%?
+
+It makes quite some sense to me to have a separate means of checking validity
+and an interface that doesn't check, and the latter I can use without paying
+a performance penalty. Reminds me of vector::at() vs. vector::operator[]().
+I would very much prefer having that distinction, and go for undefined behavior
+if you pass invalid data without checking. That combination seems to cater
+for a wide variety of needs.
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 25 aožt, 20:32
+On 8/25/2011 2:26 PM, Ville Voutilainen wrote:
+
+> On 25 August 2011 20:50, Howard Hinnant<howard.hinn..._at_[hidden]> wrote:
+>>> The precondition check
+>>> is in the interface in both cases. That is an unacceptable cost for checking for a condition
+>>> that a bug-free program will never see.
+>> Perhaps it is time to quantify this cost? 2%? 20%? 200%?
+> It makes quite some sense to me to have a separate means of checking validity
+> and an interface that doesn't check, and the latter I can use without paying
+> a performance penalty. Reminds me of vector::at() vs. vector::operator[]().
+> I would very much prefer having that distinction, and go for undefined behavior
+> if you pass invalid data without checking. That combination seems to cater
+> for a wide variety of needs.
+
+*If* you provide a way of separating validation and construction, please
+make sure that the checked interface is the notationally easier to use.
+Having the checked interface (at()) uglier and less conventional than
+the unchecked interface ([]) for vector was the result of for concerns
+about generic programming and performance that I don't see for dates.
+For *most* lines of code a 10% overhead is unnoticeable and I suspect
+that most uses of dates are in this category.
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 25 aožt, 20:36
+On 25 August 2011 21:32, bs <b..._at_[hidden]> wrote:
+
+> generic programming and performance that I don't see for dates. For *most*
+> lines of code a 10% overhead is unnoticeable and I suspect that most uses of
+> dates are in this category.
+
+I have had to do heavy processing of dates while interfacing with
+databases. I can also
+imagine the implementation of databases needing to do that in some cases. Having
+a 10% overhead, if unavoidable, is downright shocking and frankly
+unacceptable in
+many cases.
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 25 aožt, 20:38
+On 8/25/2011 2:36 PM, Ville Voutilainen wrote:
+
+> On 25 August 2011 21:32, bs<b..._at_[hidden]> wrote:
+>> generic programming and performance that I don't see for dates. For *most*
+>> lines of code a 10% overhead is unnoticeable and I suspect that most uses of
+>> dates are in this category.
+> I have had to do heavy processing of dates while interfacing with
+> databases. I can also
+> imagine the implementation of databases needing to do that in some cases. Having
+> a 10% overhead, if unavoidable, is downright shocking and frankly
+> unacceptable in
+> many cases.
+
+I don't doubt that and I know that "most" is always hard to quantify,
+but it most certainly doesn't mean "all".
+
+I picked that "10%" out of a hat. Howart's question is still unanswered.
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 25 aožt, 20:40
+On 25 August 2011 21:38, bs <b..._at_[hidden]> wrote:
+
+> I picked that "10%" out of a hat. Howart's question is still unanswered.
+
+I'm not opposed to measuring it. I just wanted to point out why it's
+desirable to
+have the undefined behavior aka a non-checking interface, there are good reasons
+to strive for such.
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 25 aožt, 20:46
+On 8/25/2011 2:40 PM, Ville Voutilainen wrote:
+
+> On 25 August 2011 21:38, bs<b..._at_[hidden]> wrote:
+>> I picked that "10%" out of a hat. Howart's question is still unanswered.
+> I'm not opposed to measuring it. I just wanted to point out why it's
+> desirable to
+> have the undefined behavior aka a non-checking interface, there are good reasons
+> to strive for such.
+
+If we have unchecked construction, we also need a (non-throwing)
+validation function (is_date() is what I usually call it).
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 25 aožt, 20:48
+[Still waiting for Nico to join the list...]
+
+On 25 August 2011 13:26, Ville Voutilainen <ville.voutilai..._at_[hidden]> wrote:
+
+> It makes quite some sense to me to have a separate means of checking validity
+> and an interface that doesn't check, and the latter I can use without paying
+> a performance penalty.
+
+I agree with that.
+
+> Reminds me of vector::at() vs. vector::operator[]().
+> I would very much prefer having that distinction, and go for undefined behavior
+> if you pass invalid data without checking. That combination seems to cater
+> for a wide variety of needs.
+
+Actually, I think the check in vector::at is almost useless, as most
+indexing errors are due to programming bugs (so should be asserts),
+and the few that aren't are quite easily to check for externally with
+i < v.size(). We need a way to check for validity, although I'm not
+sure if that should be an external function returning a bool or
+another constructor that throws on failure (or both).
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 25 aožt, 21:14
+On 25 August 2011 13:48, Nevin Liber <ne..._at_[hidden]> wrote:
+We need a way to check for validity, although I'm not
+
+> sure if that should be an external function returning a bool or
+> another constructor that throws on failure (or both).
+
+Another alternative: a pair of free functions:
+
+bool is_valid_date(year y, month m, day d); // returns true if and
+only if y-m-d represents a valid date
+date make_valid_date(year y, month m, day d); // throws if and only if
+is_valid_date(y, m, d) would return false
+
+For completeness (I'm not advocating this), we could also have two
+date classes; one checked and one unchecked and conversions between
+them.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 25 aožt, 21:15
+Hi all,
+
+I want to let you know that I met with my team today, and we will be
+incorporating the "cost of checking" into the benchmarks we will be doing
+on Howards and our date classes. I do want to point out that making checking
+part of the contract will absolutely imply additional cost and/or dictate
+which implementation we choose. For example, if the imp were just three fields
+
+ unsigned short d_year;
+ unsigned char d_month;
+ unsigned char d_day;
+
+then the cost of checking would *completely* *dominate* the set and get operations.
+
+In response to various other comments so far...
+
+I am completely opposed to *any* sort of test to see if a date holds a valid
+value. A date always holds a valid value (invariant of the class); this
+invariant is guarded by preconditions (and not necessarily code). Otherwise
+we would be re-checking a date for validity before each use (BAD). By keeping
+our contracts narrow, a single date class can be used effectively by everyone,
+which is important for interoperability.
+
+C++ has as one of its central goals not to make people pay for something they
+don't need/want. Imposing checking on all users of date would violate this
+principle. Some languages favor safety over speed. C++ does not. The C++
+language is full of undefined behaivors; attempting to write a "safe but slow" library is simply wrong minded for C++.
+
+Adopting a more general solution (which allows for a checked build mode, and
+what to do if a logic error is encountered -- TBD in Kona) will help us in forming the interfaces to the apparently large set of new value-semantic classes we are now about to consider. And arguments like "most people won't care about the performance" are not compelling for most values of "most" :-@)
+
+We need to make sure that this important vocabulary type is used ubiquitously to avoid compromising interoperability. Again, this is why we were careful
+*NEVER* to decorate narrow contracts with 'noexcept' in Madrid!
+
+ -John L.
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 25 aožt, 21:31
+Nevin,
+
+Two date classes is simply out of the question! We need a common vocabulary type here. I realize you did not advocate it, but I hope you
+appreciate the tremendous downside to having to convert between date types all over the place. In fact, we at Bloomberg have gone out of our way to make sure to have just one date type, rather than both "year-month-day" and "serial-date" implementations, and we achieve the best of both using a 64k bidirectional static lookup table between the two representations.
+
+Separately, I still don't understand this obsession with exceptions, when an optional return status get's the job done.
+
+ class Date {
+ // ...
+ public:
+ // ...
+ void setYearMonthDay(int year, int month, int day);
+ // Undefined if not a valid date value.
+
+ bool setYearMonthDayIfValid(int year, int month, int day);
+ // Returns 'true' on success, and 'false' with no effect otherwise.
+
+ // Addid Just for Nevin...
+ void setyearMonthDay(Year year, Month month, Day day);
+ // Undefined if not a valid date value.
+
+ bool setYearMonthDayIfValid(Year year, Month month, Day day);
+ // Returns 'true' on success, and 'false' with no effect otherwise.
+ };
+
+BTW, we will be benchmarking a variety of approaches over the coming weeks...
+
+ Cheers, John L.
+
+- Masquer le texte des messages prŽcŽdents -
+
+----- Original Message -----
+From: kona-date-lib_at_[hidden]
+To: kona-date-lib_at_[hidden], n..._at_[hidden]
+
+At: 8/25 15:15:14
+
+On 25 August 2011 13:48, Nevin Liber <ne..._at_[hidden]> wrote:
+We need a way to check for validity, although I'm not
+> sure if that should be an external function returning a bool or
+> another constructor that throws on failure (or both).
+
+Another alternative: a pair of free functions:
+
+bool is_valid_date(year y, month m, day d); // returns true if and
+only if y-m-d represents a valid date
+date make_valid_date(year y, month m, day d); // throws if and only if
+is_valid_date(y, m, d) would return false
+
+For completeness (I'm not advocating this), we could also have two
+date classes; one checked and one unchecked and conversions between
+them.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+--
+You received this message because you are subscribed to the Google Groups "Kona-date-lib" group.
+To post to this group, send email to kona-date-lib_at_googlegroups.com.
+To unsubscribe from this group, send email to kona-date-lib+unsubscribe_at_googlegroups.com.
+For more options, visit this group at http://groups.google.com/group/kona-date-lib?hl=en.
+
+
+Nevin Liber
+====================================
+ Autres options 25 aožt, 21:40
+On 25 August 2011 14:15, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+
+<jla..._at_[hidden]> wrote:
+> I am completely opposed to *any* sort of test to see if a date holds a valid
+> value.
+
+What we need is a way to validate the inputs to creating a date
+*before* it gets constructed. You are not opposed to that, correct?
+
+> Adopting a more general solution (which allows for a checked build mode, and
+> what to do if a logic error is encountered
+
+It isn't about logic errors. Dates come from a variety of sources
+that are not under programmer control (users, networks, etc.) and we
+need a way to know those inputs won't violate the class invariants.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 25 aožt, 21:42
+On 25 August 2011 22:40, Nevin Liber <ne..._at_[hidden]> wrote:
+
+> What we need is a way to validate the inputs to creating a date
+> *before* it gets constructed. You are not opposed to that, correct?
+
+See the first mail/post by John.
+
++ Non-instance method: bool isValidYearMonthDay(int, int, int);
+
+====================================
+====================================
+
+
+
+Nevin Liber
+Afficher le profil
+ Autres options 25 aožt, 21:47
+On 25 August 2011 14:31, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+
+<jla..._at_[hidden]> wrote:
+> class Date {
+> // ...
+> public:
+> // ...
+> void setYearMonthDay(int year, int month, int day);
+> // Undefined if not a valid date value.
+
+Is there a default constructor? If so, it must create a valid date,
+or we are already off in undefined behavior land, and too late to call
+member functions on it.
+
+Of course, people are going to use that date as the epoch (which you
+didn't want mentioned).
+
+> bool setYearMonthDayIfValid(Year year, Month month, Day day);
+> // Returns 'true' on success, and 'false' with no effect otherwise.
+
+I want a way to validate before construction, not a more expensive
+construct a dummy, validate and set. I much prefer to use
+construction and assignment instead of setters.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 25 aožt, 22:00
+Nevin,
+
+>On 25 August 2011 14:15, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+><jla..._at_[hidden]> wrote:
+>> I am completely opposed to *any* sort of test to see if a date holds a valid
+>> value.
+
+>What we need is a way to validate the inputs to creating a date
+>*before* it gets constructed. You are not opposed to that, correct?
+
+I am absolutely fine with that; having a non-instance method
+
+ static bool isValidYearMonthDay(int year, int month, int day);
+
+is what we have. If you want to avoid specifying the arguments
+twice (and also doing the calculations twice) you set a pre-existing
+date (which can be reused):
+
+ Date d;
+ if (d.setYearMonthDay(year, month, day)) {
+ // good
+ }
+ else {
+ // bad
+ }
+
+but if you know the date is good, just say
+
+ d.setYearMonthDay(year, month, day); // bad date value caught in checked
+ // build, else undefined behavior.
+or
+
+ Date dd(year, month, day); // bad date vallue caught in checked build, el
+ // else undefined behavior.
+
+>> Adopting a more general solution (which allows for a checked build mode, and
+>> what to do if a logic error is encountered
+
+>It isn't about logic errors. Dates come from a variety of sources
+>that are not under programmer control (users, networks, etc.) and we
+>need a way to know those inputs won't violate the class invariants.
+
+I completely agree that we need to validate raw data before creating objects with preconditions protecting invariants. Once I know I have a valid date,
+I don't (or sometimes may not) want to pay to check it each time. This is
+not what C++ is about; it truly is a language for people who want to squeeze
+every drop of speed out of the platform. But it's not just speed. As Pablo
+said, narrow contracts allow for new behaviors to be added if appropriate,
+whereas wide ones do not. IMO, a good design here is to allow narrow contracts
+with preconditions that guard invariants checked in a "SAFE" build mode.
+ -John L.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 25 aožt, 22:22
+On Aug 25, 2011, at 3:15 PM, JOHN LAKOS, BLOOMBERG/ 731 LEXIN wrote:
+
+> I do want to point out that making checking
+> part of the contract will absolutely imply additional cost and/or dictate
+> which implementation we choose. For example, if the imp were just three fields
+
+> unsigned short d_year;
+> unsigned char d_month;
+> unsigned char d_day;
+
+> then the cost of checking would *completely* *dominate* the set and get operations.
+
+I'm lacking John's 64Kb lookup table. But I'm really anxious to get people hacking instead of yacking. :-) Here's my engine, simplified down, with and without checking. Everyone can run it by copy/pasting into their own environment (you might have to hack a substitute timer if you don't have a <chrono> yet). My table is only 104 bytes, so this is probably 64000/104 times slower than John's. :-) (actually the harder part is going from count back to ydm)
+
+#include <cstdint>
+#include <cassert>
+
+class date
+{
+ std::uint32_t x_;
+public:
+ date(int year, int month, int day);
+
+ std::uint32_t count() const {return x_;}
+
+};
+
+static
+const int
+db[2][13] = {{-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364},
+ {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}};
+
+static
+inline
+bool
+is_leap(int y) noexcept
+{
+ return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
+
+}
+
+date::date(int y, int m, int d)
+{
+ assert(-32768 <= y && y <= 32767);
+ assert(1 <= m && m <= 12);
+ const int* year_data = db[is_leap(y)];
+ assert(1 <= d && d <= year_data[m] - year_data[m-1]);
+ std::int32_t by = y + 32799;
+ x_ = by*365 + by/4 - by/100 + by/400 + year_data[m-1] + d;
+
+}
+
+#include <chrono>
+#include <iostream>
+
+int main()
+{
+ typedef std::chrono::high_resolution_clock Clock;
+ typedef std::chrono::duration<double> sec;
+ Clock::time_point t0 = Clock::now();
+ std::uint64_t x = 0;
+ std::uint64_t n = 0;
+ std::error_code ec;
+ for (int y = -8000; y <= 10000; ++y)
+ {
+ for (int m = 1; m <= 12; ++m)
+ {
+ for (int d = 1; d <= 28; ++d)
+ {
+ date dt(y, m, d);
+ x += dt.count();
+ ++n;
+ }
+ }
+ }
+ Clock::time_point t1 = Clock::now();
+ std::cout << n/sec(t1-t0).count() << " date constructions / second\n";
+ return x;
+
+}
+
+This simply constructs a date from ymd (int specified) and transforms that triplet into a 32 bit day counter. I put a count() member function on the date only because the optimizer kept optimizing away what I was trying to measure!
+
+The most bogus part of this test is that it is *only* timing construction (with and without testing depending on -DNDEBUG). Imho a better test would include representative date manipulation. It does little good just to construct a date if you aren't going to do anything with it. But anyway, I throw this out in the hopes that someone might take it and turn it into a better test. See http://home.roadrunner.com/~hinnant/bloomington/date.cpp if you want my code for turning count back into ymd. Or maybe you can show your engine is faster! :-)
+
+As it stands this outputs for me:
+
+9.24503e+08 date constructions / second
+(-DNDEBUG)
+
+and
+
+1.28118e+08 date constructions / second
+
+Both are median of 3 and compiled using clang++ -O3. These numbers indicate construction is a little over 7 times more expensive when checked.
+
+These numbers will obviously vary with many decisions, including storage (as John said), and the ymd/count conversion algorithm.
+
+I also note that sometimes date components will be known at compile time and thus can be checked at compile time (or be known to not need checking). For example there is no need to range-check the month in date(2011, aug, 25). And I am unclear if and how constexpr might help here.
+
+But as it stands above, I find 7x sufficiently motivating for a non-checked interface (in addition to a checked interface).
+
+Straw-man:
+
+date unchecked(2011, aug, 25);
+date checked = year(2011)/aug/25;
+
+?
+
+:-)
+
+Howard
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 26 aožt, 08:26
+
+Il giorno 25/ago/2011, alle ore 21:31, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I still haven't received any feedback about my proposal of having custom validators, which would solve the above problem nicely, IMHO, providing even more flexibility without duplicating the signatures . Here's an updated version of it:
+
+template <class T>
+struct date_validator_traits;
+
+struct no_check_t {} const no_check;
+struct check_validity_t {} const check_validity;
+struct throw_if_invalid_t {} const throw_if_invalid;
+
+class date
+{
+public:
+ template <class Validator = DEFAULT_VALIDATOR_TYPE>
+ bool set_ymd(int year, int month, int day, Validator& v = DEFAULT_VALIDATOR)
+ {
+ if (date_validator_traits<Validator>::validate(year, month, day, v))
+ {
+ // actually set ymd here
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+};
+
+by suitably specializing date_validator_traits we can have all behaviors we want as well as providing an extension point for the user. For example:
+
+template <>
+struct date_validator_traits<const no_check_t>
+{
+ static bool validate(int year, int month, int day, const no_check_t& v)
+ {
+ return true;
+ }
+
+};
+
+template <>
+struct date_validator_traits<const check_validity_t >
+{
+ static bool validate(int year, int month, int day, const check_validity_t& v)
+ {
+ return is_valid_ymd(year, month, day);
+ }
+
+};
+
+template <>
+struct date_validator_traits<const throw_if_invalid_t >
+{
+ static bool validate(int year, int month, int day, const throw_if_invalid_t& v)
+ {
+ if (!is_valid_ymd(year, month, day))
+ throw std::invalid_argument("not a date");
+ return true;
+ }
+
+};
+
+template <>
+struct date_validator_traits<std::error_code>
+{
+ static bool validate(int year, int month, int day, std::error_code& ec)
+ {
+ if (!is_valid_ymd(year, month, day))
+ {
+ // set error code in ec;
+ return false;
+ }
+ return true;
+ }
+
+};
+
+int main()
+{
+ date dt;
+
+ dt.set_ymd(2011, 8, 26); // uses default validator, whatever that is
+
+ dt.set_ymd(2011, 8, 26, throw_if_invalid); // no need to check the result
+
+ if (not dt.set_ymd(2011, 8, 26, check_validity))
+ {
+ // date is invalid
+ }
+
+ std::error_code ec;
+ if (!dt.set_ymd(2011, 8, 26, ec))
+ {
+ // date is invalid and ec contains suitable error code
+ }
+
+}
+
+---
+
+This approach might seem to introduce a little overhead in the no_check case, but a reasonably optimizing compiler is able to remove all tests and inline all calls (Clang is able to do that, for example) making such overhead negligible if not even null.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 29 aožt, 01:28
+
+On Aug 26, 2011, at 2:26 AM, Alberto Ganesh Barbati wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I've been experimenting with a subset of Ganesh's proposal, but in a more-fine grained way than he intended. The subset I'm experimenting with is just no_check. I'm only playing with no_check because it is faster to play with just this subset. It could easily be expanded to his other tags if this pans out. The more-fine grained part is due to an observation that I'm often forming a new day from a ymd spec where I know only that one or two of year, month or day need not be checked.
+
+For example if I know that my month is in range, but can't prove my year and day are in range I might:
+
+ date d(year(y), month(m, no_check), day(d));
+
+I've been going over the algorithms in my proposal and am finding this fine-grained no_check placement useful. For example when I add a month to a date:
+
+date&
+date::operator+=(months mn)
+{
+ Int32_t y = y_;
+ Int32_t m = m_;
+ m += mn.x_;
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ }
+ else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ *this = date(chrono::year(y), chrono::month(m, no_check),
+ chrono::day(d_, n_, dow_));
+ return *this;
+
+}
+
+I can visually inspect the code and prove to myself that on the last line where I assign this date a new date that m will always be in the range [1, 12]. And so I tag the chrono::month constructor with no_check which bypasses (at compile time) all range checking for the month. But I have no such assurances for the year (which may have wandered outside of [-32768, 32767]), or day, (which though it hasn't been changed, may now be invalid for the new month and year).
+
+<aside>
+My proposal still has things people really don't like, such as month addition as an operator+= of date. Please ignore this for now. I'm experimenting with what I have handy. I'm not stubbornly pushing what a majority has made clear it doesn't like. Imagine this is a namespace scope function instead of a member of date, and doesn't encode nth day-of-week into day.
+</aside>
+
+Year and month can be range checked in isolation. Day can not. So the day can not be range checked except in the date constructor. Here is how I'm prototyping checking only the day, but not the year and month:
+
+ date d(year(y), month(m), day(d), no_check);
+
+And here is my current prototype for not checking anything:
+
+ date d(year(y, no_check), month(m, no_check), day(d), no_check);
+
+Quite verbose! But again, this follows from the fact that when you say year(y), or month(m), you can check y and m at that point. And then you never need to check copies of those objects again. Including if you copy them out of another date:
+
+ date d2(d.year(), d.month(), day(d.day()+1)); // year and month are not checked, only day is
+
+This is not a fully thought out proposal! This is an exploration of Ganesh's interesting suggestion - complete with prototyping which includes illustrative uses of no_check. Perhaps it will inspire yet another evolution from someone else?
+
+Howard
+
+ date
+25K Afficher TŽlŽcharger
+
+ date.cpp
+16K Afficher TŽlŽcharger
+
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 29 aožt, 03:00
+
+On 8/28/2011 6:28 PM, Howard Hinnant wrote:
+
+I like the idea, provided
+ (1) the default is "validated" (throwing) and
+ (2) "validated" and "no checking" is specializations so that we
+don't have overhead in those cases
+
+What would be a user-provided case? (i.e., ar ewe overabstracting by
+providing a general argument?)
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 29 aožt, 03:39
+On Aug 28, 2011, at 9:00 PM, bs wrote:
+
+> On 8/28/2011 6:28 PM, Howard Hinnant wrote:
+
+> I like the idea, provided
+> (1) the default is "validated" (throwing) and
+> (2) "validated" and "no checking" is specializations so that we don't have overhead in those cases
+
+In my prototype I am throwing when not no_check and input is invalid. If we generalized the tag, other options could be provided (e.g. assert).
+
+As it turns out "validated" and "no checking" are overloads. For example:
+
+class month
+{
+ UInt8_t m_;
+public:
+ explicit month(int m)
+ : m_(m)
+ {
+ if (!(1 <= m && m <= 12))
+ throw bad_date("month " + std::to_string(m) + " is out of range");
+ }
+
+ month(int m, no_check_t)
+ : m_(m) {}
+// ...
+
+};
+
+but the effect is the same: no overhead when you ask for no_check.
+
+> What would be a user-provided case? (i.e., ar ewe overabstracting by providing a general argument?)
+
+I'm not understanding the question. Could you elaborate?
+
+Thanks,
+Howard
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 29 aožt, 04:13
+On 8/28/2011 8:39 PM, Howard Hinnant wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I can think of three cases:
+ (1) validate and throw
+ (2) validate and set invalid flag (for people who can't use exceptions)
+ (3) don't validate
+Can anyone think of a fourth case? (I can, of course, but I'm not sure
+the alternatives are real)
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 29 aožt, 04:18
+On 28Aug, 2011, at 10:13 PM, bs wrote:
+
+> I can think of three cases:
+> (1) validate and throw
+> (2) validate and set invalid flag (for people who can't use exceptions)
+> (3) don't validate
+> Can anyone think of a fourth case? (I can, of course, but I'm not sure the alternatives are real)
+
+Do you picture asserting as a form of validation in this picture, assumed under the "no validation" heading, or is that a 4th?
+
+AlisdairM
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 29 aožt, 04:26
+On Aug 28, 2011, at 10:13 PM, bs wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+If I'm understanding correctly, such choices could be provided by more overloads, e.g:
+
+class month
+{
+ UInt8_t m_;
+public:
+ explicit month(int m)
+ : m_(m)
+ {
+ if (!is_valid())
+ throw bad_date("month " + std::to_string(m) + " is out of range");
+ }
+
+ month(int m, no_check_t)
+ : m_(m) {}
+
+ month(int m, assert_t)
+ : m_(m)
+ {
+ assert(is_valid());
+ }
+
+ bool is_valid() const {return 1 <= m_ && m_ <= 12;}
+
+ // ...
+
+};
+
+Howard
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 29 aožt, 07:06
+2011/8/29 bs <b..._at_[hidden]>:
+
+> On 8/28/2011 8:39 PM, Howard Hinnant wrote:
+
+>> On Aug 28, 2011, at 9:00 PM, bs wrote:
+
+>>> On 8/28/2011 6:28 PM, Howard Hinnant wrote:
+
+>>> I like the idea, provided
+>>> (1) the default is "validated" (throwing) and
+>>> (2) "validated" and "no checking" is specializations so that we don't
+>>> have overhead in those cases
+
+I agree, but I don't think that you need specializations to realize what
+(2) intends to realize.
+
+- Afficher le texte des messages prŽcŽdents -
+
+Yes, that makes sense to me.
+
+>>> What would be a user-provided case? (i.e., ar ewe overabstracting by
+>>> providing a general argument?)
+
+>> I'm not understanding the question. Could you elaborate?
+
+> I can think of three cases:
+> (1) validate and throw
+> (2) validate and set invalid flag (for people who can't use exceptions)
+> (3) don't validate
+> Can anyone think of a fourth case? (I can, of course, but I'm not sure the
+> alternatives are real)
+
+IMO the three choices are good enough, especially since we have already
+a nice new error diagnostic parallel to exceptions.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 29 aožt, 08:33
+Hi all,
+
+There is something *much* bigger here than allowing each individual programmer to control what happens when he/she makes a coding error and calls a library function *out* *of* *contract*. That is a logic error -- i.e., a coding bug.
+
+The immediate client of a library facility should be empowered with suitable tools for the job at hand -- i.e., checking and non-checking forms of the
+date setter methods, and also a non-instance method to pre-check the valididity
+of a date value, before an object is created. The checking versions are essential when the value is not "known" to be valid, e.g., because it is raw input. (Note that an existing date can be used to prevent supplying the
+date fields twice.)
+
+BUT!!!! When the value is "known" to be valid, the setter method of choice is
+absolutly the one where *no* *checking* is performed as part of the contract, and the function returns void; in a "SAFE" build, however, it does WHATEVER the owner of main wants it to do if it turns out not to be valid.
+
+Making this approach work is much, much bigger than just 'Date', and we are proposing to introduce a general assertion facility that allows for "defensive programming done right" in C++, including "course levels of runtime checking" and an "Oh Darn" handler that does whatever should be done (according to the applciation owner) if a logic error occurs anywhere within the program.
+
+This facility is beyond the scope of individual contracts for components,
+and becomes a library-wide understanding of how much checking is to be
+done at runtime (without being specific in each component contract) and what should happen -- abort, throw, spin, or something else, if a pre-condition violation is detected.
+
+In order for this approach to work, however, we need to allow some functions
+to have less then fully specified (i.e., undefined) behavior -- also known
+as a *narrow* contract. As much as some will not like me for saying it, Undefined Behavior is the right choice for some conctracts: It keeps our options open now (depending on build mode), and in the future (when we know better).
+
+Conclusion: We need exactly two kinds of setter method: (1) unchecked (returning void), which is checked in a "Safe" build, and does what the owner of main said to do on a logic error, and (2) a check method (with a name that makes it clear we are returning a status) that returns status and on failure has no effect.
+
+Again, this fully baked "defensive programming" approach is part of a much bigger picture that would apply across the board, and that we plan to present in detail in Kona.
+
+Note that it has the decided advantage of being all things to all people
+in that the application owner configures (1) how much runtime to spend
+checking for logic erros, and (2) exactly what to do if such a logic error
+is encounered. It just doesn't get better than that!
+
+ -John L.
+
+p.s., I'm late and it's tired, so please forgive spelling, and other typo's ;-)
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 09:32
+On 29 August 2011 01:33, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+
+<jla..._at_[hidden]> wrote:
+> In order for this approach to work, however, we need to allow some functions
+> to have less then fully specified (i.e., undefined) behavior -- also known
+> as a *narrow* contract. As much as some will not like me for saying it, Undefined Behavior is the right choice for some conctracts: It keeps our options open now (depending on build mode), and in the future (when we know better).
+
+I agree with this. To add perspective from a user point of view, UB
+means "don't go there"; fully specifying behavior in many situations
+leads to software that is much more difficult to reason about (since
+we've granted a license for users to go there even though we really
+don't want them to).
+
+> Conclusion: We need exactly two kinds of setter method: (1) unchecked (returning void), which is checked in a "Safe" build, and does what the owner of main said to do on a logic error, and (2) a check method (with a name that makes it clear we are returning a status) that returns status and on failure has no effect.
+
+While I really do agree with the general gist of this, I really don't
+like the whole setter method paradigm (which I believe is orthogonal
+to the idea behind wide and narrow contracts). Construction and
+assignment are the fundamental building blocks of C++ objects. I find
+it very clunky to create a dummy object and then set its value. And
+if I want to reset a value, assignment is a perfectly good way of
+writing that.
+
+I see three cases:
+
+1. Create an object quickly because I the programmer "know" the
+parameters are valid
+2. Check the parameters before creation of the object
+3. Check the parameters during creation of the object
+
+(and one more case not applicable to Date; namely, what to do if
+object creation fails for an external reason, such as out of memory.)
+
+I agree that I would use a non-instance function for (2), but there
+are many different ways to write (3) depending on the circumstances
+(different constructor, non-instance function returning a fully
+constructed object, setter method, etc.).
+
+> Again, this fully baked "defensive programming" approach is part of a much bigger picture that would apply across the board, and that we plan to present in detail in Kona.
+
+But we are designing a date library here, not a date library that
+meets the interface of some as yet unseen let alone unadopted
+assertion facility. The insights regarding narrow vs. wide contracts,
+UB, etc., are appropriate (and very valuable) input to the design. I
+find these syntactic considerations far less so.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 09:33
+
+Il giorno 29/ago/2011, alle ore 07:06, Daniel KrŸgler ha scritto:
+
+> 2011/8/29 bs <b..._at_[hidden]>:
+>> On 8/28/2011 8:39 PM, Howard Hinnant wrote:
+
+>>> On Aug 28, 2011, at 9:00 PM, bs wrote:
+
+>>>> On 8/28/2011 6:28 PM, Howard Hinnant wrote:
+
+>>>> I like the idea, provided
+>>>> (1) the default is "validated" (throwing) and
+>>>> (2) "validated" and "no checking" is specializations so that we don't
+>>>> have overhead in those cases
+
+> I agree, but I don't think that you need specializations to realize what
+> (2) intends to realize.
+
+My experiments with Clang shows that you don't need to use specialization to avoid overhead. However, I am not opposed to specializations. Having specializations have the advantage that you can have the no_check_t version return void. (In my proposal all functions return a bool). However, having them all return a bool can useful in generic code:
+
+template <class Validator>
+void accept_date(Validator v)
+{
+ int y, m, d;
+ read_from_user(y, m, d);
+ date dt;
+ if (dt.set_ymd(y, m, d, v))
+ {
+ // date is good or assumed to be good
+ }
+ else
+ {
+ // date is bad
+ }
+
+}
+
+If set_ymd always returns a bool, this code work even if Validator is no_check_t (in that case, it is the programmer responsibility to ensure that read_from_user returns validated input). Whether we want to support this use-case or not is open to discussion.
+
+>>>> What would be a user-provided case? (i.e., ar ewe overabstracting by
+>>>> providing a general argument?)
+
+>>> I'm not understanding the question. Could you elaborate?
+
+I believe Bjarne was referring to my statement about having user-defined validators. I was thinking about allowing the programmer to have validators such has "a valid date in the future" or "a valid date in a range". By packaging such validators in a function object you could use them in generic code as in the example above. However, I agree that this might be over-engineering: it's probably easier to convert ymd to a valid date first and then use the date facilities to implement more advanced checking.
+
+Another user-validator scenario is to allow the user to include custom assertion code. This scenario might be covered as soon as we have a comprehensive assertion infrastructure as suggested by John.
+
+>> I can think of three cases:
+>> (1) validate and throw
+>> (2) validate and set invalid flag (for people who can't use exceptions)
+>> (3) don't validate
+>> Can anyone think of a fourth case? (I can, of course, but I'm not sure the
+>> alternatives are real)
+
+> IMO the three choices are good enough, especially since we have already
+> a nice new error diagnostic parallel to exceptions.
+
+I'd like to have a debug validator also that would perform an assert in debug builds and a no-check in release builds. Of course, this could also be made the default behaviour of the no-check validator.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 09:57
+
+Il giorno 29/ago/2011, alle ore 09:32, Nevin Liber ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I definitely agree with Nevin. However, the main problem is that constructors can't return failure without either throwing or introducing a not-a-date valid. John (please correct me if I interpreted you wrongly) has expressed distaste for both these approaches. However, I believe implementing a not-a-date value has several advantages without introducing unwanted overhead. Consider this internal structure, suggested by Nevin:
+
+union DateImpl
+{
+ struct
+ {
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ };
+ uint32_t fast_comparisons;
+
+};
+
+and have a constructor like:
+
+date(int y, int m, int d, no_throw_validate_t)
+{
+ if (is_valid_ymd(y, m, d))
+ {
+ impl.year = y; imp.month = m; impl.day = d;
+ }
+ else
+ {
+ fast_comparison = 0;
+ }
+
+}
+
+and a contextual conversion to bool:
+
+explicit operator bool() const
+{
+ return fast_comparison;
+
+}
+
+then you could write:
+
+if (date d = date(y, m, d, no_throw_validate))
+{
+ // date d is constructed and valid
+}
+
+else
+{
+ // date is invalid
+
+}
+
+The no-overhead guarantee can be achieved by stating that any other use of a not-a-date valid except the contextual conversion to bool and assignment-to are UB. We might even decide to have the default constructor leave the date uninitialized for performance reasons.
+
+> I see three cases:
+
+> 1. Create an object quickly because I the programmer "know" the
+> parameters are valid
+
+Ok. This could be
+
+ date d(y, m, d, no_check);
+
+> 2. Check the parameters before creation of the object
+> 3. Check the parameters during creation of the object
+
+I wish we could avoid 2, as I believe we could have validated creation as cheap as validate params+creation. Once I have checked the parameters and found them to be valid, I will probably need to create a date object right away, but if checking the parameters in advance has no benefit we would make things simpler.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 29 aožt, 10:06
+On 29 August 2011 10:57, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+
+> I definitely agree with Nevin. However, the main problem is that constructors can't return failure without either throwing or introducing a not-a-date valid.
+
+Well, for constructors it would seem natural to me that you get either
+UB or an exception. If you want to check whether a date
+can be constructed from whatever bits (ints, Day/Month/Year), I'd
+expect us to need a non-constructor for that. Trying to
+get non-throwing/non-UB constructor doesn't seem worth the trouble.
+And if we have non-constructor validation, we don't
+need not-a-date. That also allows the implementation of Date to not
+care about checking not-a-date everywhere, which
+seems rather fundamental.
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 13:12
+Il 8/29/2011 10:06 AM, Ville Voutilainen ha scritto:
+> On 29 August 2011 10:57, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+>> I definitely agree with Nevin. However, the main problem is that constructors can't return failure without either throwing or introducing a not-a-date valid.
+> Well, for constructors it would seem natural to me that you get either
+> UB or an exception. If you want to check whether a date
+> can be constructed from whatever bits (ints, Day/Month/Year), I'd
+> expect us to need a non-constructor for that. Trying to
+> get non-throwing/non-UB constructor doesn't seem worth the trouble.
+
+I don't see what "trouble" your are talking about. Could you please
+elaborate?
+> And if we have non-constructor validation, we don't
+> need not-a-date.
+
+How would you write such non-constructor? How would it return a failure?
+> That also allows the implementation of Date to not
+> care about checking not-a-date everywhere, which
+> seems rather fundamental.
+
+As I said, *no* member function except the contextual conversion to bool
+needs to check a not-a-date value. Accessing a not-a-date is UB.
+
+It is somehow incorrect to say that a non-throwing validating
+constructor is non-UB. See it this way: UB is deferred to the first use
+of the constructed object and you get the chance to detect invalidity
+before UB is triggered.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 29 aožt, 13:30
+
+On 29 Aug 2011, at 07:12, Alberto Ganesh Barbati wrote:
+
+> As I said, *no* member function except the contextual conversion to bool
+> needs to check a not-a-date value. Accessing a not-a-date is UB.
+
+> It is somehow incorrect to say that a non-throwing validating
+> constructor is non-UB. See it this way: UB is deferred to the first use
+> of the constructed object and you get the chance to detect invalidity
+> before UB is triggered.
+
+What can I do with your proposed "not a date" value, if it is undefined behavior to access it?
+
+Is it defined behavior to copy a Not-a-Date value, e.g. if a function takes arguments by value?
+
+My big concern is that by deferring the UB past the point of date-object construction, you are deferring it past the point where it is most easily checked.
+
+We now have a 'valid' object running through our system, with pre-conditions on most of its members that it not hold the not-a-date value. Many functions taking dates must document the requirement that they are not passed the 'not a date' value, or must widen their contracts to check for this, and then define some error handling policy (which must be tested for, increasing the state-space that calling functions must be aware of, increasing the complexity of the whole program).
+
+Deferring UB past the point of construction is a bad way to introduce UB into library contracts - and still forces the potentially expensive checking onto the constructor as well. This appears to be a "worst of both worlds" solution - we gain the cost of checking, and pay an additional price for pushing UB deeper into the system.
+
+AlisdairM
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 13:51
+
+Il giorno 29/ago/2011, alle ore 13:30, Alisdair Meredith ha scritto:
+
+> On 29 Aug 2011, at 07:12, Alberto Ganesh Barbati wrote:
+
+>> As I said, *no* member function except the contextual conversion to bool
+>> needs to check a not-a-date value. Accessing a not-a-date is UB.
+
+>> It is somehow incorrect to say that a non-throwing validating
+>> constructor is non-UB. See it this way: UB is deferred to the first use
+>> of the constructed object and you get the chance to detect invalidity
+>> before UB is triggered.
+
+> What can I do with your proposed "not a date" value, if it is undefined behavior to access it?
+
+You can check the presence of a not-a-date using the contextual conversion to bool or possibly a member function.
+
+> Is it defined behavior to copy a Not-a-Date value, e.g. if a function takes arguments by value?
+
+Copying a NAD could be UB. Makes sense.
+
+> My big concern is that by deferring the UB past the point of date-object construction, you are deferring it past the point where it is most easily checked.
+
+> We now have a 'valid' object running through our system, with pre-conditions on most of its members that it not hold the not-a-date value. Many functions taking dates must document the requirement that they are not passed the 'not a date' value, or must widen their contracts to check for this, and then define some error handling policy (which must be tested for, increasing the state-space that calling functions must be aware of, increasing the complexity of the whole program).
+
+> Deferring UB past the point of construction is a bad way to introduce UB into library contracts - and still forces the potentially expensive checking onto the constructor as well. This appears to be a "worst of both worlds" solution - we gain the cost of checking, and pay an additional price for pushing UB deeper into the system.
+
+As I wrote in one of my previous posts, the idea is to allow the following idiom:
+
+if (date d(y, m, d, nothrow_validate))
+{
+ // valid date
+}
+
+else
+{
+ // invalid date
+
+}
+
+which is less clumsy, IMHO, than:
+
+date d;
+if (d.set_ymd(y, m, d))
+{
+ // valid date
+}
+
+else
+{
+ // invalid date
+
+}
+
+This approach, by the way, doesn't specify what is the value of d before the call to set_ymd(). So even the validating-setter approach requires the construction of uninitialized values, accessing which is UB. What is the difference?
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 29 aožt, 13:57
+2011/8/29 Alberto Ganesh Barbati <gan..._at_[hidden]>:
+
+> Il giorno 29/ago/2011, alle ore 13:30, Alisdair Meredith ha scritto:
+
+>> What can I do with your proposed "not a date" value, if it is undefined behavior to access it?
+
+> You can check the presence of a not-a-date using the contextual conversion to bool or possibly a member function.
+
+>> Is it defined behavior to copy a Not-a-Date value, e.g. if a function takes arguments by value?
+
+> Copying a NAD could be UB. Makes sense.
+
+I like the idea, which is also very much similar to the valid flag of
+future and shared_future.
+
+- Afficher le texte des messages prŽcŽdents -
+
+I would prefer the "valid state" idiom. We have
+comparable examples in the library for that as
+well. I currently tend to not provide explicit
+operator bool(), because that could be misinterpreted
+as a null-like value, IMO quering valid is fine enough.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 29 aožt, 14:07
+On 29 August 2011 14:57, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+>> You can check the presence of a not-a-date using the contextual conversion to bool or possibly a member function.
+>>> Is it defined behavior to copy a Not-a-Date value, e.g. if a function takes arguments by value?
+>> Copying a NAD could be UB. Makes sense.
+> I like the idea, which is also very much similar to the valid flag of
+> future and shared_future.
+
+I very much prefer invalid dates never existing. Then I can reason
+about my systems, and don't
+have to worry about operations past construction causing UB. My
+assumption here is
+that
+
+1) a throwing constructor, if provided, obviously prevents an object's
+lifetime starting
+2) a non-throwing constructor causing UB causes reasonable-enough-UB
+in debug builds
+that I can correct my logic errors before shipping
+
+Checking a Not-a-date with a member or with a conversion all over the
+place doesn't sound like a good idea
+at all, design-wise. If the date class can avoid such checks, I'll
+have to do them myself, so "it just needs
+to check in the bool-operator" doesn't help me at all.
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 29 aožt, 14:48
+
+Ganesh wrote:
+>I definitely agree with Nevin. However, the main problem is that constructors >can't return failure without either throwing or introducing a not-a-date >valid. John (please correct me if I interpreted you wrongly) has expressed >distaste for both these approaches. However, I believe implementing a >not-a-date value has several advantages without introducing unwanted overhead. >Consider this internal structure, suggested by Nevin:
+
+To clarify what I am advocating:
+
+1. An invariant of the object is that it holds a valid date value. Period.
+
+2. Copy construction and assignment are always valid
+
+3. (choose your name but) void setYearMonthDay(...) AND
+ bool setYearMonthDayIfValid(...) are both supported in some form.
+
+4. (could be free but) static bool isValid(...) is supported in some form.
+
+5. The default constructed date is inititalized, valid, and *isn't* "today" for
+ many reasons -- e.g., dependency, security, testing (by our clients).
+
+6. It sounds to me like we may be allowing objective engineering to be
+ influenced too greately by subjective aesthetics. "Clunkey" or not, testing
+ the date first OR setting the date with a validating setter of some form is
+ what we *need* to do to in order to avoid fully defining the ctor behavior
+ to throw (BAD IDEA) or allowing for not-a-date value (WORSE IDEA).
+
+7. Note that the performance cost of seting the date to a default value is a
+ single 'int' assignment. As much as I love AS FAST AS POSSIBLE, default
+ initializing the date to a valid value is a sound trade-off in ALL cases: If we are talking about 1 date, then it cannot be a performance issue, and
+ if we are talking about many dates, we can reuse the one dummy, and again
+ it is not an issue.
+
+ Cheers, John Lakis
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 15:00
+
+Il giorno 29/ago/2011, alle ore 14:07, Ville Voutilainen ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Please consider that I suggest to have all three kind of constructors (throwing, non-throwing/non-validating, non-throwing/validating), with throwing being the default. If you don't want to be bother with NAD values, just do not call the non-throwing/validating constructor.
+
+Ganesh
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 15:11
+
+Il giorno 29/ago/2011, alle ore 14:48, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+
+> Ganesh wrote:
+>> I definitely agree with Nevin. However, the main problem is that constructors >can't return failure without either throwing or introducing a not-a-date >valid. John (please correct me if I interpreted you wrongly) has expressed >distaste for both these approaches. However, I believe implementing a >not-a-date value has several advantages without introducing unwanted overhead. >Consider this internal structure, suggested by Nevin:
+
+> To clarify what I am advocating:
+
+> 1. An invariant of the object is that it holds a valid date value. Period.
+
+> <snip>
+> 6. It sounds to me like we may be allowing objective engineering to be
+> influenced too greately by subjective aesthetics. "Clunkey" or not, testing
+> the date first OR setting the date with a validating setter of some form is
+> what we *need* to do to in order to avoid fully defining the ctor behavior
+> to throw (BAD IDEA) or allowing for not-a-date value (WORSE IDEA).
+
+I'm sorry, but I don't see how you could guarantee an invariant which doesn't include NAD values and yet require construction to be non-throwing. What would be the expected behaviour of:
+
+ date d(0, 0, 0);
+
+?
+
+Or are you suggesting that we must always use two-phase construction?
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 29 aožt, 15:13
+On 29 Aug 2011, at 09:00, Alberto Ganesh Barbati wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Once the not-a-date semantic enters the library, I am not able to ignore it when writing my own libraries. At a minimum I must add a precondition to each contract in my library taking dates that it is not passed a not-a-date value.
+
+Trickier is specifying the contracts for my generic code. I want to have the notion of a simple value-semantic type that I can use specifying generic interfaces. Do I need to add the notion of 'not-a-value' to my idea of value-semantic, so my contracts can explicitly always exclude generic not-a-values from defined behavior? Or can date simply not satisfy my type requirements due to the presence of this one additional state?
+
+I would much rather that state not exist, as it has too much of a ripple effect through all the rest of my code.
+
+I am quite happy to entertain something like a not-a-value in a higher level abstraction, such as boost::optional<date>, where an empty optional is equivalent to the not-a-value. If you need both empty and not-a-value, then you can compose further with optional<optional<date>>.
+
+AlisdairM
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 29 aožt, 15:21
+On 29 August 2011 16:00, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+
+> Please consider that I suggest to have all three kind of constructors (throwing, non-throwing/non-validating, non-throwing/validating), with throwing being the default.
+
+That's almost ok. The assumption is that an UB-constructor will not
+allow further code to continue executing.
+But, I still don't think a NAD-constructed date is a good idea. Hence
+I'd prefer having only two variants
+of constructors, one throwing and one causing UB. Same goes for
+setting values, two variants, one
+causing UB and one validating+throwing, _and_ a separate validation
+function that doesn't construct
+or modify a date. I think I'm in 100% agreement with John there.
+
+>If you don't want to be bother with NAD values, just do not call the non-throwing/validating constructor.
+
+Practically the construction and use of such date objects can be so
+far apart that this creates
+a big problem, reasoning-wise and verification-wise. A never-invalid
+date doesn't suffer from such
+a problem.
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 15:22
+On 29 August 2011 06:57, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+> 2011/8/29 Alberto Ganesh Barbati <gan..._at_[hidden]>:
+>> Copying a NAD could be UB. Makes sense.
+
+> I like the idea, which is also very much similar to the valid flag of
+> future and shared_future.
+
+That means you can't use a date as a key in an ordered container. I
+would be against this. Date needs to be copyable, assignable and have
+a SWO.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 29 aožt, 15:23
+
+On 29 Aug 2011, at 09:11, Alberto Ganesh Barbati wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+You are not allowing for undefined behavior. Such a constructor might assert, which in turn may throw depending on how the assertion library is configured - undefined behavior can do anything. It also implies this this is a narrow contract that should not be marked 'noexcept' (at least in the library specification - implementers can 'noexcept' if they know their build mode cannot throw e.g. assertions are disabled).
+
+(and yes, date(0,0,0) can make its best guess and come up with some other nonsense value as undefined behavior too.)
+
+AlisdairM
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 15:24
+
+Il giorno 29/ago/2011, alle ore 15:13, Alisdair Meredith ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I'm still not convinced, but what about using a simple wrapper:
+
+struct tentative_date
+{
+ date value;
+ bool is_valid;
+
+ tentative_date(int y, int m, int d)
+ : is_valid(is_valid_ymd(y, m, d))
+ {
+ if (is_valid)
+ value.set_ymd(y, m, d);
+ }
+
+ explicit operator bool() const
+ {
+ return value.is_valid();
+ }
+
+};
+
+or even
+
+struct tentative_date
+{
+ date value;
+
+ tentative_date(int y, int m, int d)
+ : value(y, m, d, no_check)
+ {}
+
+ explicit operator bool() const
+ {
+ return value._internal_is_valid_date();
+ }
+
+};
+
+In this case date either contains a valid value or UB, but tentative_date might contain a NAD. Would that be address your concerns?
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Robert Douglas
+====================================
+ Autres options 29 aožt, 15:25
+
+On Mon, Aug 29, 2011 at 8:11 AM, Alberto Ganesh Barbati
+<gan..._at_[hidden]>wrote:
+
+> I'm sorry, but I don't see how you could guarantee an invariant which
+> doesn't include NAD values and yet require construction to be non-throwing.
+> What would be the expected behaviour of:
+
+> date d(0, 0, 0);
+
+I would suggest, then, an interface in which all values passed are valid
+ones:
+date d = years(2011) + months(13) + days(32);
+yields February 1st, 2012
+
+Internal representation of day count gives no invalid bit patterns. Added
+bonus, comparison, addition, and subtraction are all trivial to the class,
+allowing for very simple use in ordered containers and databases.
+
+The cost of converting back to year/month/day would be larger, but I cannot
+think of many use cases where this wouldn't either precede or follow system
+IO.
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 29 aožt, 15:27
+2011/8/29 Nevin Liber <ne..._at_[hidden]>:
+
+> On 29 August 2011 06:57, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+>> 2011/8/29 Alberto Ganesh Barbati <gan..._at_[hidden]>:
+>>> Copying a NAD could be UB. Makes sense.
+
+>> I like the idea, which is also very much similar to the valid flag of
+>> future and shared_future.
+
+> That means you can't use a date as a key in an ordered container. I
+> would be against this. Date needs to be copyable, assignable and have
+> a SWO.
+
+I don't see the point. All operations of an invalid date except the destructor,
+assignment, and valid call would invoke undefined behaviour,
+I haven't seen any other proposal yet, unless you make Not-a-Date a fullfledged
+value. But I understood that this was not part of John's design. This means
+that you can perfectly define order and equality of dates without need
+to consider Not-a-Date.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 15:36
+
+Il giorno 29/ago/2011, alle ore 15:24, Alberto Ganesh Barbati ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Or even:
+
+class unchecked_date
+{
+ // only non-throwing non-validating ctors
+ // allows Not-a-date values
+ // has validation members that "promote" to date
+
+};
+
+class date : public unchecked_date
+{
+ // only throwing validating ctors
+ // date values are guaranteed to be valid
+
+};
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 29 aožt, 15:44
+On 29 August 2011 16:27, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+> I don't see the point. All operations of an invalid date except the destructor,
+> assignment, and valid call would invoke undefined behaviour,
+> I haven't seen any other proposal yet, unless you make Not-a-Date a fullfledged
+> value. But I understood that this was not part of John's design. This means
+> that you can perfectly define order and equality of dates without need
+> to consider Not-a-Date.
+
+I got the impression that in John's design the constructor and setter can
+invoke UB. Nothing else can. Is that correct?
+
+I very much see the point of using Date as a map key.
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 15:47
+On 29 August 2011 08:25, Robert Douglas <rwdou..._at_[hidden]> wrote:
+
+>> I'm sorry, but I don't see how you could guarantee an invariant which
+>> doesn't include NAD values and yet require construction to be non-throwing.
+>> What would be the expected behaviour of:
+
+>> date d(0, 0, 0);
+
+> I would suggest, then, an interface in which all values passed are valid
+> ones:
+> date d = years(2011) + months(13) + days(32);
+> yields February 1st, 2012
+
+Guaranteed? I'm not sure you can, because at some point you hit the
+range of the primitive types you use to create the objects, and that
+is implementation-specified behavior (how many bytes in a short,
+etc.).
+
+Adding components together is a bad idea. Dates are not durations,
+and we start running into issues with commutativity and associativity
+when defining the meaning behind:
+
+date d1 = years(2012) + years(1);
+date d2 = years(2012) + months(2) + days(28) + years(1);
+date d3 = years(2012) + months(3) + days(1) + years(1);
+date d4 = years(2012) + months(2) + days(28) + days(2) + years(1) - days(2);
+date d5 = years(2012) + months(2) + days(29) + years(1) - years(1);
+
+Maybe as a separate interface built on top of the primitives, but
+construction of a date needs to come from a fixed year, month and day.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 29 aožt, 15:49
+2011/8/29 Ville Voutilainen <ville.voutilai..._at_[hidden]>:
+
+> On 29 August 2011 16:27, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+>> I don't see the point. All operations of an invalid date except the destructor,
+>> assignment, and valid call would invoke undefined behaviour,
+>> I haven't seen any other proposal yet, unless you make Not-a-Date a fullfledged
+>> value. But I understood that this was not part of John's design. This means
+>> that you can perfectly define order and equality of dates without need
+>> to consider Not-a-Date.
+
+> I got the impression that in John's design the constructor and setter can
+> invoke UB. Nothing else can. Is that correct?
+
+If you construct or set an invalid date value you are invoking UB.
+But unless there are no further words what the properties
+are of such a "constructed" invalid value are, any usage of
+this value must also invoke UB. Anything else does not
+make sense.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 29 aožt, 15:56
+On 29 August 2011 16:49, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+>> I got the impression that in John's design the constructor and setter can
+>> invoke UB. Nothing else can. Is that correct?
+> If you construct or set an invalid date value you are invoking UB.
+> But unless there are no further words what the properties
+> are of such a "constructed" invalid value are, any usage of
+> this value must also invoke UB. Anything else does not
+> make sense.
+
+This seems to indicate that a not-a-date doesn't buy me anything at all.
+If it's UB to access a not-a-date (beyond checking validity), and it's
+similarly
+UB to access a date which has been set with an invalid value, I'd rather live
+without a not-a-date concept.
+
+I can write a validating wrapper on top of a date class. A library can
+provide such a
+wrapper for me. But for that, the _fundamental vocabulary type_ must be FAST!
+I'm more and more gravitating towards an approach where the
+constructors/setters
+should just be UB, fair and square. Provide a bare-bones date, and if
+we can get a
+_separate_ design right for a "safe" date, provide that as well.
+Perhaps it's a bad idea to try and mix the two.
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 15:57
+On 29 August 2011 08:27, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+>> That means you can't use a date as a key in an ordered container. I
+>> would be against this. Date needs to be copyable, assignable and have
+>> a SWO.
+
+> I don't see the point. All operations of an invalid date except the destructor,
+> assignment, and valid call would invoke undefined behaviour,
+
+If Date is not Copyable (which is a property of the type, not its
+value), how can you store it in a container? I suppose we could say
+that Date is only Moveable, but that would be surprising to most
+people.
+
+> I haven't seen any other proposal yet, unless you make Not-a-Date a fullfledged
+> value.
+
+Or don't allow it. Default construction (which I believe is necessary
+to keep this as a useful class) could create a valid but unspecified
+value.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 29 aožt, 15:58
+Clarification:
+
+I agree that the opertor< should be defined on date (and it is at Bloomberg).
+Almost nothing else is UB unless you move a date off its valid range --
+e.g., date += 10000000; // days
+
+ -John Lakos
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 16:10
+
+Il giorno 29/ago/2011, alle ore 15:56, Ville Voutilainen ha scritto:
+
+> On 29 August 2011 16:49, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+>>> I got the impression that in John's design the constructor and setter can
+>>> invoke UB. Nothing else can. Is that correct?
+>> If you construct or set an invalid date value you are invoking UB.
+>> But unless there are no further words what the properties
+>> are of such a "constructed" invalid value are, any usage of
+>> this value must also invoke UB. Anything else does not
+>> make sense.
+
+> This seems to indicate that a not-a-date doesn't buy me anything at all.
+> If it's UB to access a not-a-date (beyond checking validity), and it's
+> similarly
+> UB to access a date which has been set with an invalid value, I'd rather live
+> without a not-a-date concept.
+
+As you said, having a not-a-date allows you to check validity. This is not "anything at all". It's quite much, in fact.
+
+> I can write a validating wrapper on top of a date class. A library can
+> provide such a
+> wrapper for me. But for that, the _fundamental vocabulary type_ must be FAST!
+> I'm more and more gravitating towards an approach where the
+> constructors/setters
+> should just be UB, fair and square. Provide a bare-bones date, and if
+> we can get a
+> _separate_ design right for a "safe" date, provide that as well.
+> Perhaps it's a bad idea to try and mix the two.
+
+Sounds like the unchecked_date/date approach that I just posted, except that the focus is different: unchecked_date is bare-bone and allows not-a-dates, while date is fully validated and therefore guaranteed valid/copiable/hashable, etc. Users are expected to normally use date, while the use of unchecked_date should be limited and transitory, as a mean to construct a valid date. It seems to me that this approach is superior to a date/safe_date approach, precisely because we can have not-a-dates without having them spill all around.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Robert Douglas
+====================================
+ Autres options 29 aožt, 16:24
+
+- Afficher le texte des messages prŽcŽdents -
+
+But my point is that for any resulting set of bits, the date object is
+valid. You can force overflow for any numerical type.
+
+Adding components together is a bad idea. Dates are not durations,
+> and we start running into issues with commutativity and associativity
+> when defining the meaning behind:
+
+I disagree. Dates represent a duration of time since some arguably arbitrary
+beginning.
+As for associativity and commutativity, it seems like an issue of operator
+choice, not an issue as to the merits of initialization based the
+combination of parts. Surely, we could do the same thing with a constructor
+taking the 3 components, ymd, but that yields all the drawbacks seen above,
+when the user believes that they are only adding in a number of months 1-12,
+and a number of days based on the month and year number, but may actually be
+passing in higher (or lower) values.
+
+> date d1 = years(2012) + years(1);
+> date d2 = years(2012) + months(2) + days(28) + years(1);
+> date d3 = years(2012) + months(3) + days(1) + years(1);
+> date d4 = years(2012) + months(2) + days(28) + days(2) + years(1) -
+> days(2);
+> date d5 = years(2012) + months(2) + days(29) + years(1) - years(1);
+
+None of these are actually problems, when a forced left-to-right execution
+is performed. Thus, perhaps a different operator? operator*? Addition seems
+natural to me, but I can see that problems arise since the length of a month
+is dependent on the year, and the length of a year is dependent on how many
+precede it.
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 16:32
+On 29 August 2011 08:57, Nevin Liber <ne..._at_[hidden]> wrote:
+
+> If Date is not Copyable (which is a property of the type, not its
+> value), how can you store it in a container?
+
+To clarify, ithis precludes storing it in *any* container, even
+something as simple as vector<Date>.
+
+> Default construction (which I believe is necessary
+> to keep this as a useful class) could create a valid but unspecified
+> value.
+
+And even other properties, such as:
+
+date d1;
+date d2;
+
+assert(d1 == d2);
+
+could be kept unspecified.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 29 aožt, 16:46
+On 29 August 2011 17:10, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+
+>> This seems to indicate that a not-a-date doesn't buy me anything at all.
+>> If it's UB to access a not-a-date (beyond checking validity), and it's
+>> similarly
+>> UB to access a date which has been set with an invalid value, I'd rather live
+>> without a not-a-date concept.
+> As you said, having a not-a-date allows you to check validity. This is not "anything at all". It's quite much, in fact.
+
+I expect any debug-mode UB to allow me to quickly and easily notice misuses
+of constructors and setters. I don't want non-debug-mode constructors and
+setters waste time on validation. I expect debug-mode UB to bomb so hard
+that I never cause further UB by accessing an object after an operation causing
+UB. I don't want to worry about having to check for validity after
+construction/setting/whatever when using the date type.
+
+I also want to be able to store dates into containers and I want to be
+able to use
+them as associative container keys.
+
+So far it seems to me that having a not-a-date hurts more than it
+helps. Hence the
+comment "doesn't seem to buy me anything". It' not "not anything" in
+the very sense
+of the words, but it doesn't buy me anything I want. :)
+
+Regardless of how we solve all those problems, the "raw" setter
+doesn't seem to fit
+into the picture. It allows the invariants to break by setting a not-a-date or
+an undefined date.
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 29 aožt, 16:55
+All,
+
+We do not want a Date and a CheckedDate (derived from it). The problem would
+come from slicing the CheckedDate when passed into an interface. The better
+approach is to have a single date that has two types of methods: those
+that check, and those that don't. In a safe build, even the ones that
+don't check do, and do what the app developer says (and not what the person who
+violated the preconditions wants). In our experience, having two build modes and two methods achieves our goals better than having two classes.
+
+ -John Lakos
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 29 aožt, 16:59
+On 29 August 2011 17:55, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+
+<jla..._at_[hidden]> wrote:
+> We do not want a Date and a CheckedDate (derived from it). The problem would
+> come from slicing the CheckedDate when passed into an interface. The better
+
+If we would end up having two dates, I wouldn't expect either to
+publicly derive from the other.
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 17:02
+
+Il giorno 29/ago/2011, alle ore 16:55, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+
+> All,
+
+> We do not want a Date and a CheckedDate (derived from it).
+
+Neither do I. I suggested to have date derived from unchecked_date.
+
+> The problem would
+> come from slicing the CheckedDate when passed into an interface.
+
+Slicing is no problem if unchecked_date is a base.
+
+> The better
+> approach is to have a single date that has two types of methods: those
+> that check, and those that don't. In a safe build, even the ones that
+> don't check do, and do what the app developer says (and not what the person who
+> violated the preconditions wants). In our experience, having two build modes and two methods achieves our goals better than having two classes.
+
+I am pretty sure that your approach is good. Whether it's "better" is your opinion. I am evaluating alternative designs. As Howard put it in the opening email, it's ok if we come up with more than one design. We don't need to necessarily agree.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 29 aožt, 17:19
+Ganesh,
+
+First, I am -- of course -- just giving my opinion when I say one class is better than two, and you -- of course -- don't necessarily have to agree.
+We are having an open discussion, and I feel that we are all contributing.
+
+Second,
+
+ date checked_date
+ | == |
+ v v
+ unchecked_date date
+
+These two structures are the same, have the same methods, but have different
+names for humans. This is like a change of variables in math. :-)
+The slicing problem is the same. What am I missing?
+
+ -John L.
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 17:35
+
+Il giorno 29/ago/2011, alle ore 17:19, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+
+> Ganesh,
+
+> First, I am -- of course -- just giving my opinion when I say one class is better than two, and you -- of course -- don't necessarily have to agree.
+> We are having an open discussion, and I feel that we are all contributing.
+
+> Second,
+
+> date checked_date
+> | == |
+> v v
+> unchecked_date date
+
+> These two structures are the same, have the same methods, but have different
+> names for humans. This is like a change of variables in math. :-)
+> The slicing problem is the same. What am I missing?
+
+The focus changes. You are expected to generally use _date_ objects. By giving the "other" class a uglier name we implicitly say "use the ugly-named one only when needed". By having date/checked_date you are promoting the wrong usage pattern: that checking is to be done "only when needed", while it's the opposite view that I would like to promote.
+
+What is the problem if a date (that has already been checked and validated) is sliced as an unchecked_date? Simply that information (about the validity of the date) is lost. So what? It's a performance issue, it doesn't introduce instability or incorrectness in the program. The ugly name should be enough deterrent to avoid people to write functions taking an unchecked_date& parameter and unchecked_date usage is to be restricted to those limited pieces of code that deal with date validation. I do not expect slicing to occur in the typical usage scenario.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 29 aožt, 18:07
+Ganesh,
+
+But the problem is that we cannot use an unchecked_date where a date is needed!
+
+There will be a vocabulary problem. I do not agree (in this specific case) that checking should be the default. I think an unknown date value MUST ALWAYS be checked, and a known good one should not be checked (unless in a safe build mode). The one true date allows for both cases as needed.
+
+-John L.
+
+- Masquer le texte des messages prŽcŽdents -
+
+----- Original Message -----
+From: kona-date-lib_at_[hidden]
+To: kona-date-lib_at_[hidden]
+
+At: 8/29 11:35:22
+
+Il giorno 29/ago/2011, alle ore 17:19, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+
+> Ganesh,
+
+> First, I am -- of course -- just giving my opinion when I say one class is better than two, and you -- of course -- don't necessarily have to agree.
+> We are having an open discussion, and I feel that we are all contributing.
+
+> Second,
+
+> date checked_date
+> | == |
+> v v
+> unchecked_date date
+
+> These two structures are the same, have the same methods, but have different
+> names for humans. This is like a change of variables in math. :-)
+> The slicing problem is the same. What am I missing?
+
+The focus changes. You are expected to generally use _date_ objects. By giving the "other" class a uglier name we implicitly say "use the ugly-named one only when needed". By having date/checked_date you are promoting the wrong usage pattern: that checking is to be done "only when needed", while it's the opposite view that I would like to promote.
+
+What is the problem if a date (that has already been checked and validated) is sliced as an unchecked_date? Simply that information (about the validity of the date) is lost. So what? It's a performance issue, it doesn't introduce instability or incorrectness in the program. The ugly name should be enough deterrent to avoid people to write functions taking an unchecked_date& parameter and unchecked_date usage is to be restricted to those limited pieces of code that deal with date validation. I do not expect slicing to occur in the typical usage scenario.
+
+Ganesh
+
+--
+You received this message because you are subscribed to the Google Groups "Kona-date-lib" group.
+To post to this group, send email to kona-date-lib_at_googlegroups.com.
+To unsubscribe from this group, send email to kona-date-lib+unsubscribe_at_googlegroups.com.
+For more options, visit this group at http://groups.google.com/group/kona-date-lib?hl=en.
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 19:17
+On 29 August 2011 10:02, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+
+> Il giorno 29/ago/2011, alle ore 16:55, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+>> We do not want a Date and a CheckedDate (derived from it).
+
+> Neither do I. I suggested to have date derived from unchecked_date.
+
+I'm not seeing any conceptual difference between these; only a
+difference in the spelling of the types.
+
+When discussing the concepts and relationships between the types,
+could we use the names unchecked_date and checked_date, and break off
+into a separate discussion which one of those (if any) we spell
+"date"?
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 19:54
+On 29 August 2011 07:48, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+
+<jla..._at_[hidden]> wrote:
+> Ganesh wrote:
+> 6. It sounds to me like we may be allowing objective engineering to be
+> influenced too greately by subjective aesthetics. "Clunkey" or not, testing
+> the date first OR setting the date with a validating setter of some form is
+> what we *need* to do to in order to avoid fully defining the ctor behavior
+> to throw (BAD IDEA) or allowing for not-a-date value (WORSE IDEA).
+
+Users need ways to:
+
+1. Create an object w/o validating its parameters. This may invoke
+undefined behavior.
+2. Create an object after validating its parameters. Undefined
+behavior must be avoidable, but object creation may fail. (This may
+be broken into multiple statements on the part of the user to make it
+happen.)
+
+Having thought about why it is clunky (and good for calling me on it),
+it is because exceptions, not return codes, give me functions that are
+composible (and function composition is an objective, not subjective
+criterion).
+
+Now, maybe a checking version has to be written as:
+
+make_valid_date(make_valid_year(2012), make_valid_month(2), make_valid_day(32));
+
+(in an implementation where (1) constructors create non-validated
+objects and (2) make_valid_* are non-instance functions that throw on
+invalid input and return a valid object otherwise) while the non
+checked version is written
+
+date(year(2012), month(2), day(32));
+
+But that seems more error-prone to me, as some people are going to write:
+
+make_valid_date(year(2012), month(2), day(32));
+
+which subtly invokes undefined behavior. (And no, I'm not giving up
+on strong typing for the parameters to the date creation functions
+just to get around this problem.)
+
+As long as there is a creation method which doesn't throw (which I
+agree we need), are you okay if there are other constructors that do
+throw?
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 29 aožt, 20:06
+2011/8/29 Nevin Liber <ne..._at_[hidden]>:
+
+> On 29 August 2011 07:48, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+> <jla..._at_[hidden]> wrote:
+>> Ganesh wrote:
+>> 6. It sounds to me like we may be allowing objective engineering to be
+>> influenced too greately by subjective aesthetics. "Clunkey" or not, testing
+>> the date first OR setting the date with a validating setter of some form is
+>> what we *need* to do to in order to avoid fully defining the ctor behavior
+>> to throw (BAD IDEA) or allowing for not-a-date value (WORSE IDEA).
+
+> Users need ways to:
+
+> 1. Create an object w/o validating its parameters. This may invoke
+> undefined behavior.
+
+I'm fine with that.
+
+> 2. Create an object after validating its parameters. Undefined
+> behavior must be avoidable, but object creation may fail. (This may
+> be broken into multiple statements on the part of the user to make it
+> happen.)
+
+> Having thought about why it is clunky (and good for calling me on it),
+> it is because exceptions, not return codes, give me functions that are
+> composible (and function composition is an objective, not subjective
+> criterion).
+
+> Now, maybe a checking version has to be written as:
+
+> make_valid_date(make_valid_year(2012), make_valid_month(2), make_valid_day(32));
+
+First, I strongly object that using a checked creation
+should require complicated code as shown above. IMO
+the intuitive simple construction should be checked. If
+you want an unchecked form, make that clear, e.g. by
+requiring a tag like "unchecked".
+
+Second, I'm not sure why there are such a lot of functions
+involved. Having an individually checked year, an individually
+checked month, and an individually checked day does not
+help against the date 2011-02-29, for example.
+
+And this is may main concern, why I prefer to have
+a simple way for checked constructions/assignment,
+because we have a multi-parameter interaction here, and
+the probability increases with each parameter that the
+combination could be invalid.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 20:42
+On 29 August 2011 13:06, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+> Second, I'm not sure why there are such a lot of functions
+> involved. Having an individually checked year, an individually
+> checked month, and an individually checked day does not
+> help against the date 2011-02-29, for example.
+
+Strong type checking is a good thing. People are going to get the
+order of parameters wrong, and I strongly feel that be a compile time
+error than either UB or deferred to run time (if detectable at all).
+
+What is the "natural" order of parameters anyway? C mostly (if not
+all) has destination specified before source. C++, which is supposed
+to be a superset, inverted that for its own algorithms. Worse, some
+parameter orders require a C++ expert to understand, because the
+"natural" order was discarded to avoid such issues as ambiguous
+overloading. And then there are functions like memset, where almost no
+one can remember the order of the last two parameters.
+
+> And this is may main concern, why I prefer to have
+> a simple way for checked constructions/assignment,
+> because we have a multi-parameter interaction here, and
+> the probability increases with each parameter that the
+> combination could be invalid.
+
+This is certainly a valid concern that I have also. But there are so
+many tensions between the tradeoffs that I am unsure this is the
+biggest concern.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 29 aožt, 21:15
+
+Il giorno 29/ago/2011, alle ore 19:17, Nevin Liber ha scritto:
+
+> On 29 August 2011 10:02, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+>> Il giorno 29/ago/2011, alle ore 16:55, JOHN LAKOS, BLOOMBERG/ 731 LEXIN ha scritto:
+>>> We do not want a Date and a CheckedDate (derived from it).
+
+>> Neither do I. I suggested to have date derived from unchecked_date.
+
+> I'm not seeing any conceptual difference between these; only a
+> difference in the spelling of the types.
+
+> When discussing the concepts and relationships between the types,
+> could we use the names unchecked_date and checked_date, and break off
+> into a separate discussion which one of those (if any) we spell
+> "date"?
+
+As I said in another post, there is a difference in focus which *is* relevant. Anyway, I whipped out some code and I am no longer sure the double date hierarchy achieves what I have in mind. The approach of having a single date class and a totally unrelated tentative_date class which acts as an optimized version of boost::optional<date> looks more promising.
+
+Thus, there are three construction scenarios:
+
+1) I have ymd values that represents a valid date (trust me!), I want maximal performance:
+
+ date d(y, m, d, no_check);
+
+if it happens that ymd do no represent a valid date, we have UB.
+
+2) I have ymd values that may not represent a valid date, I want the library to validate them for me, getting an exception is fine:
+
+ date d(y, m, d);
+
+3) I have ymd values that may not represent a valid date, I want the library to validate them for me, I don't like exceptions:
+
+ if (tentative_date td(y, m d))
+ {
+ date d = td.date(); // good date
+ }
+ else
+ {
+ // bad date
+ }
+
+calling td.date() if bool(td) == false is UB.
+
+Obvious alternatives that don't require a separate tentative_date class and address this scenario are:
+
+Alternative A:
+
+ if (date::is_valid_ymd(y, m, d))
+ {
+ date dt(y, m, d, no_check);
+ // good date
+ }
+ else
+ {
+ // bad date
+ }
+
+slightly more verbose, may require additional local variables if y, m, d are complex expressions to avoid re-evaluation of them. The user might forget the no_check and have the date validated twice.
+
+Alternative B:
+
+ date dt;
+ if (dt.set_ymd_if_valid(y, m, d))
+ {
+ // good date
+ }
+ else
+ {
+ // bad date
+ }
+
+the main problem with this approach is that d is in scope after the if statement as well as in the false-branch. As there is some consensus that a default-initialized date is a *valid* albeit unspecified date, neither the compiler nor runtime assertion facilities will help spot an incorrect use of d if the set_ymd_if_valid() function fails.
+
+Another added bonus of the tentative_date class is that it might have handy member functions to be used in the false-branch to provide extended information about _what_ did not validate (the year? the month? the day?).
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 29 aožt, 21:28
+2011/8/29 Alberto Ganesh Barbati <gan..._at_[hidden]>:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I like this construction.
+
+> 2) I have ymd values that may not represent a valid date, I want the library to validate them for me, getting an exception is fine:
+
+> date d(y, m, d);
+
+I like this as well.
+
+> 3) I have ymd values that may not represent a valid date, I want the library to validate them for me, I don't like exceptions:
+
+> if (tentative_date td(y, m d))
+> {
+> date d = td.date(); // good date
+> }
+> else
+> {
+> // bad date
+> }
+
+> calling td.date() if bool(td) == false is UB.
+
+tentative_date doesn't convince me much: It seems to be quite complicated
+and very special date-specific but has actually not much use expect for
+validation. If we had optional, we could use this instead and it could be
+reused for other types as well (I'm not suggesting to invent optional
+just because of date, though).
+
+I need a bit more time for the non-exceptional checked construction.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 29 aožt, 21:59
+On 8/29/2011 12:54 PM, Nevin Liber wrote:
+
+> On 29 August 2011 07:48, JOHN LAKOS, BLOO
+> Now, maybe a checking version has to be written as:
+
+> make_valid_date(make_valid_year(2012), make_valid_month(2), make_valid_day(32));
+
+NO! That's too ugly for words. For the default, average, and novice user
+the checked construction should look very much like this
+
+ date d{2012,month{12},30};
+
+IMO, the unchecked version (which might lead to undefined behavior),
+should look like this
+
+ date d{2012,month{12},30,unchecked};
+
+This is longer because it is the version for experts.
+
+If you can't afford to have construction throw, you write something very
+much like
+
+ if (!date::valid(2012,month{12},30,unchecked) { /* deal with it */ }
+ date d{2012,month{12},30,unchecked};
+
+and hope you don't mess up. I could live with the alternative
+
+ date d{2012,month{12},30,unchecked};
+ if (!d::valid()) { /* deal with it */ }
+
+My main concern is whether and how to get
+
+ date d{2012,month{12},30,asserted};
+
+which is the debug version on unchecked.
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 29 aožt, 22:13
+On 29 August 2011 14:59, bs <b..._at_[hidden]> wrote:
+
+> NO! That's too ugly for words. For the default, average, and novice user the
+> checked construction should look very much like this
+
+> date d{2012,month{12},30};
+
+> IMO, the unchecked version (which might lead to undefined behavior), should
+> look like this
+
+> date d{2012,month{12},30,unchecked};
+
+To make this work, month must both not check its parameter AND you can
+pass any value whatsoever to month's constructor w/o invoking
+undefined behavior. Is this as intended?
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 29 aožt, 22:56
+On 8/29/2011 3:13 PM, Nevin Liber wrote:
+
+> On 29 August 2011 14:59, bs<b..._at_[hidden]> wrote:
+>> NO! That's too ugly for words. For the default, average, and novice user the
+>> checked construction should look very much like this
+
+>> date d{2012,month{12},30};
+
+>> IMO, the unchecked version (which might lead to undefined behavior), should
+>> look like this
+
+>> date d{2012,month{12},30,unchecked};
+> To make this work, month must both not check its parameter AND you can
+> pass any value whatsoever to month's constructor w/o invoking
+> undefined behavior. Is this as intended?
+
+Yes. (at least that's what I do)
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 30 aožt, 00:54
+On 29 August 2011 15:56, bs <b..._at_[hidden]> wrote:
+
+>> To make this work, month must both not check its parameter AND you can
+>> pass any value whatsoever to month's constructor w/o invoking
+>> undefined behavior. Is this as intended?
+
+> Yes. (at least that's what I do)
+
+Let me also suggest that we pick a signed type for the parameter to
+the month constructor, as I'd rather we have undefined behavior if the
+conversion to that type overflows or underflows instead of being able
+to wrap back to a legitimate value by using an unsigned type.
+
+(I'm only mentioning this in case someone is tempted to suggest using
+a char as the parameter, since the range of possible months will
+obviously fit in it.)
+
+I'm actually liking this solution...
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 30 aožt, 00:57
+On 8/29/2011 5:54 PM, Nevin Liber wrote:
+
+> On 29 August 2011 15:56, bs<b..._at_[hidden]> wrote:
+>>> To make this work, month must both not check its parameter AND you can
+>>> pass any value whatsoever to month's constructor w/o invoking
+>>> undefined behavior. Is this as intended?
+>> Yes. (at least that's what I do)
+> Let me also suggest that we pick a signed type for the parameter to
+> the month constructor, as I'd rather we have undefined behavior if the
+> conversion to that type overflows or underflows instead of being able
+> to wrap back to a legitimate value by using an unsigned type.
+
+> (I'm only mentioning this in case someone is tempted to suggest using
+> a char as the parameter, since the range of possible months will
+> obviously fit in it.)
+
+> I'm actually liking this solution...
+
+I'm tempted to use an enum class.
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 30 aožt, 09:57
+
+Nevin wrote:
+> As long as there is a creation method which doesn't throw (which I
+> agree we need), are you okay if there are other constructors that do
+> throw?
+
+Honestly, when you talked about utility functions on top of (and separate from) the date Class (component) to do the extra checking and throw, you hit the nail on the head! That way, we can build more complex functionality out of simpler functionality, without imposing it on everyone. This is excatly how I think
+we should structure our libraries (and how we do it at Bloomberg today).
+
+I do think we need the "built-in" pair of member functions:
+
+void set_year_month_day(y, m, d); // choice of types for y, m, d
+bool set_year_month_day_if_valid(y, m, d); // is kept separate here
+
+As for having an extra constructor that is checked... (like the 'at' in
+vector)... I would never use it, but it doesn't hurt me either, provided
+it's NOT the default (like in vector).
+
+I do understand why Bjarna does not agree with making the unchecked ctor
+the default, and making it harder (more ugly, time consuming) to do the "raw" (more dangerous) unchecked constructor. I am used to narrow contracts for
+value types, and clearly I may be in the minority. The subtle cost of
+having checking be the default for all value semantic types all the time
+is a tax on performance ALL THE TIME, not just in development. This is
+my largest objection. I would not say "over my dead body" though; it would
+would be another choice I would have to teach professional programmers to
+avoid in the standard (and in our implemenation, it would be checked anyway
+in safe mode, AND THE APP DEVELOPER, AND NOT THE PROGRAMMER WHO MADE THE
+MISTAKE BY CALLING DATE OUT OF CONTRACT) would have the say of both (1) roughly how much time to spend looking, and what to do if a logic error is detected..
+
+Nevin Wrote:
+> Let me also suggest that we pick a signed type for the parameter to
+> the month constructor, as I'd rather we have undefined behavior if t
+> conversion to that type overflows or underflows instead of being abl
+> to wrap back to a legitimate value by using an unsigned type.
+
+I totally agree with this. In fact, unless there is a need for an unsinged
+type that is tied specifically to the platform -- e.g., for memory allocation,
+indexing into a vector -- in which case we must use std::size_t or std::ptr_diff_t, we should use int (or int_64), e.g., for things
+like day, age, shoe-size.
+
+> (I'm only mentioning this in case someone is tempted to suggest usin
+> a char as the parameter, since the range of possible months will
+> obviously fit in it.)
+
+For reasons of a comon vocabulary, we should always pass int, not short or char, long, etc.. Also note that the char and short will be extened to int,
+passed through, and then truncated back -- there is no advantage in performance (it may even be more expensive) and it's not intuitive.
+
+Bjarne wrote:
+> I'm tempted to use an enum class.
+
+I wouldn't die if we had an overload that took an enum for literals; however, I would not want to have to cast an int to an enum as the only way to get a valid
+date into my date class without checking.
+
+ -John Lakos
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 30 aožt, 18:34
+On 29 August 2011 14:59, bs <b..._at_[hidden]> wrote:
+
+> date d{2012,month{12},30};
+
+One minor (I hope!) point: Based on the observation stated in
+<http://home.roadrunner.com/~hinnant/bloomington/date.html> that the
+only three orderings in use are:
+
+YMD
+MDY
+DMY
+
+I feel that month should go first (and still be typed), as in:
+
+date d(month(12), 30, 2012);
+
+as it is the only one that is unambiguous with respect to how dates
+are actually written. The other way to do this would be to create a
+type for day instead of month (which has the advantage that you can
+write all three constructors if we decide that is the way to go), and
+that type would need the same properties (constructor takes a signed
+primitive type, no undefined behavior and parameter is unchecked).
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 30 aožt, 18:53
+2011/8/30 Nevin Liber <ne..._at_[hidden]>:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I consider this reasoning as a bit too weak as a base to decide for a
+single canonical order. If we want to single canonical order (I'm fine
+with that) please lets use an established standard order.
+
+I would argue that ISO 8601 defines a reasonable order as YMD
+and there are easy ways to deduce this order, should one have
+forgotten about it.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 30 aožt, 19:09
+
+Daniel wrote:
+> I would argue that ISO 8601 defines a reasonable order as YMD
+> and there are easy ways to deduce this order, should one have
+> forgotten about it.
+
+I'm affraid I have to agrree with Daniel: Having MDY as a universal standard is (and always has been), in my experience, a bad idea.
+
+On a separate note, and being really practical here...
+
+If were to have just one order...
+
+How is
+
+ date.set(Year(1959), Month(3), Day(8));
+
+so much less dangerous and/or less readable than
+
+ date.setYearMonthDay(1959, 3, 8);
+
+I mean really.
+
+And I can tell you that the first is a bunch harder for me to type ;-)
+
+ -John L.
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 30 aožt, 20:02
+On 30 August 2011 12:09, JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+
+<jla..._at_[hidden]> wrote:
+> How is
+
+> date.set(Year(1959), Month(3), Day(8));
+
+> so much less dangerous and/or less readable than
+
+> date.setYearMonthDay(1959, 3, 8);
+
+> I mean really.
+
+> And I can tell you that the first is a bunch harder for me to type ;-)
+
+You are advocating to use a mnemonic rather than the type system. In
+other words, C++ has a type system that is hard to use.
+
+In my experience, there have been so many bugs that either would have
+been caught at compile time, test time or been trivial to fix had
+people created and used types instead of falling back on the
+fundamental types.
+
+Yes, it is tedious to define and use types, but I find that far less
+painful than debugging.
+
+Ease of use vs. reliability: a classic tradeoff...
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 30 aožt, 20:20
+On 30 August 2011 21:02, Nevin Liber <ne..._at_[hidden]> wrote:
+
+>> How is
+>> date.set(Year(1959), Month(3), Day(8));
+>> so much less dangerous and/or less readable than
+>> date.setYearMonthDay(1959, 3, 8);
+
+It isn't. What validators and human readers can work with is having day and
+month on different sides of year (which differs from the two by having
+more digits), then we can do
+
+date.set(Day(6), 1959, 6); and we know which is which, or
+date.set(Month(6), 1959, 6); and we know which is which.
+
+date.setYMD(1959, 6, 6); is not particularly safe, but neither is
+date.setYMD(Year(1959), Month(6), Day(6));
+
+Note that it's still rather unsafe to say
+
+date.setYMD(yearvar, monthvar, dayvar); or even
+date.setYMD(yearvar, Month(monthvar), Day(dayvar);
+
+it's impossible to make it truly idiot-safe for all possible cases.
+We have probably all tried to use some sort of integral wrappers
+or even enum classes to disambiguate raw-ish numbers, but
+as long as the different types, if any, need to be ultimately
+constructed from ints, we're not achieving much because it's
+still possible to mess it up by messing up the order.
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 30 aožt, 20:20
+
+Nevin wrote:
+> You are advocating to use a mnemonic rather than the type system.
+
+I tend to agree with you about trading off ease of writing for ease of
+reading/maintaining. However, I think that getting the date set using
+a function with a name like setYearMonthDay followed by 3 ordered integers
+is just as "type safe" and just as mnemonic as 'set' followed by three name/type values.
+
+Remember, I could write
+
+ d.set(year(3), Month(8), Day(2011))
+
+and this is not a going to produce any error unless each of the individual field types do bounds checking (which they cannot do fully) or the overall set method does the check -- either way at signficant runtime overhead (as Howard demonstrated).
+
+I think it's really the same thing when you get down to it:
+
+ d.setYearMonthDay(1959, 3, 8);
+or
+ d.set(Year(1959), Month(3), Day(8));
+Obviously
+ d.set(1959, 3, 8)
+
+is needlessly non-mnemonic ("non-typesafe"), but that would be a straw man.
+
+ -John L.
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 30 aožt, 20:38
+On Aug 30, 2011, at 2:20 PM, Ville Voutilainen wrote:
+
+> date.set(Month(6), 1959, 6); and we know which is which.
+
+I think it would be a good thing to support Jun as a synonym for Month(6). Jun has the advantage that it doesn't need range checking and is type-safe (if we design the API right). Month(m) has the advantage that m can be specified at run time. It seems like both Jun and Month(6) are very useful.
+
+Howard
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 30 aožt, 20:39
+2011/8/30 Howard Hinnant <howard.hinn..._at_[hidden]>:
+
+> On Aug 30, 2011, at 2:20 PM, Ville Voutilainen wrote:
+
+>> date.set(Month(6), 1959, 6); and we know which is which.
+
+> I think it would be a good thing to support Jun as a synonym for Month(6). Jun has the advantage that it doesn't need range checking and is type-safe (if we design the API right). Month(m) has the advantage that m can be specified at run time. It seems like both Jun and Month(6) are very useful.
+
+I wholeheartedly agree with that suggestion.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 30 aožt, 21:33
+On 30 August 2011 21:39, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+> 2011/8/30 Howard Hinnant <howard.hinn..._at_[hidden]>:
+>> I think it would be a good thing to support Jun as a synonym for Month(6). Jun has the advantage that it doesn't need range checking and is type-safe (if we design the API right). Month(m) has the advantage that m can be specified at run time. It seems like both Jun and Month(6) are very useful.
+> I wholeheartedly agree with that suggestion.
+
+Yes, using such an enumeration value is useful in many cases. Even
+that doesn't protect us from argument
+ordering problems. We can take some precautions to make mistakes less
+common, but ultimately
+we can't escape them all, especially when generic code (and especially
+variadic templates) enters the picture.
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 30 aožt, 21:46
+On 8/30/2011 2:33 PM, Ville Voutilainen wrote:
+
+> On 30 August 2011 21:39, Daniel Kr gler<daniel.krueg..._at_[hidden]> wrote:
+>> 2011/8/30 Howard Hinnant<howard.hinn..._at_[hidden]>:
+>>> I think it would be a good thing to support Jun as a synonym for Month(6). Jun has the advantage that it doesn't need range checking and is type-safe (if we design the API right). Month(m) has the advantage that m can be specified at run time. It seems like both Jun and Month(6) are very useful.
+>> I wholeheartedly agree with that suggestion.
+> Yes, using such an enumeration value is useful in many cases. Even
+> that doesn't protect us from argument
+> ordering problems.
+
+It protects us from *some* argument ordering problems: Use an enum class.
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 30 aožt, 21:52
+On 30 August 2011 13:38, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+> I think it would be a good thing to support Jun as a synonym for Month(6). Jun has the advantage that it doesn't need range checking and is type-safe (if we design the API right). Month(m) has the advantage that m can be specified at run time. It seems like both Jun and Month(6) are very useful.
+
+Are we going to (ultimately) follow the naming convention of using
+lower case? I'm just thinking about ADL and streams and oct and
+dec...
+
+Other than that, I like it.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 30 aožt, 21:53
+On 30 August 2011 22:46, bs <b..._at_[hidden]> wrote:
+
+>> Yes, using such an enumeration value is useful in many cases. Even
+>> that doesn't protect us from argument
+>> ordering problems.
+> It protects us from *some* argument ordering problems: Use an enum class.
+
+Well, even an enum class won't protect us in cases where you explicitly convert
+an int to a value of enum class type, aka construct your enum class from a value
+that we got from ui/network/user-some-other-way. You can still have ordering
+problems even with enum classes if you can construct both an enum class Day
+and an enum class Month from values between 1-12.
+
+But, that pointing-out aside, yes, it helps with some ordering cases. It doesn't
+ultimately save us from all of them. And then there's things like
+int I_accidentally_the_whole_month = get_day_from_where_ever();
+int I_also_accidentally_the_whole_day = get_month_from_where_ever();
+// now construct a date from these in the 'naming' order and voila
+
+Stuff like that can't be protected against, reasonably, so what I'm trying to
+say here is that we need to think how far we want to protect users who don't
+make sure that they use the ints in the right order, because ultimately they
+have to make sure that they do, or hell breaks loose.
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 30 aožt, 21:58
+On Aug 30, 2011, at 3:52 PM, Nevin Liber wrote:
+
+> On 30 August 2011 13:38, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+>> I think it would be a good thing to support Jun as a synonym for Month(6). Jun has the advantage that it doesn't need range checking and is type-safe (if we design the API right). Month(m) has the advantage that m can be specified at run time. It seems like both Jun and Month(6) are very useful.
+
+> Are we going to (ultimately) follow the naming convention of using
+> lower case? I'm just thinking about ADL and streams and oct and
+> dec...
+
+> Other than that, I like it.
+
+I'm not opposed to upper case, but had assumed to date lower case because of the existing std::lib convention. I'm aware of the oct and dec conflicts and had imagined this library was destined for namespace std::chrono along with the other time-keeping components.
+
+Howard
+
+Howard Hinnant
+====================================
+ Autres options 30 aožt, 22:03
+On Aug 30, 2011, at 3:53 PM, Ville Voutilainen wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Making use of constexpr objects appears to get all of the benefits of [class] enums with none of the disadvantages:
+
+class month
+{
+public:
+ explicit month(int m) constexpr;
+ // ...
+
+};
+
+constexpr month jun(6);
+
+// ...
+
+class date
+{
+public:
+ date(year y, month d, day d);
+ // overload this constructor to taste
+ // ...
+
+};
+
+<Disclaimer> I'm still learning constexpr and don't have a compiler to test this against. But I've subbed in const with good success.
+
+Howard
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 30 aožt, 22:06
+On 30 August 2011 23:03, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+>> Well, even an enum class won't protect us in cases where you explicitly convert
+>> an int to a value of enum class type, aka construct your enum class from a value
+> Making use of constexpr objects appears to get all of the benefits of [class] enums with none of the disadvantages:
+
+Well, it protects you when you do things at compile-time. When the int
+comes in at runtime,
+constexpr won't help you. ;)
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 30 aožt, 22:06
+On 30 August 2011 14:58, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+> I'm aware of the oct and dec conflicts
+
+We can always add an overload...
+
+Just kidding,
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 30 aožt, 22:11
+2011/8/30 Ville Voutilainen <ville.voutilai..._at_[hidden]>:
+
+> On 30 August 2011 23:03, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+>>> Well, even an enum class won't protect us in cases where you explicitly convert
+>>> an int to a value of enum class type, aka construct your enum class from a value
+>> Making use of constexpr objects appears to get all of the benefits of [class] enums with none of the disadvantages:
+
+> Well, it protects you when you do things at compile-time. When the int
+> comes in at runtime,
+> constexpr won't help you. ;)
+
+I don't understand the problem: During runtime you could rely
+on the (runtime) checked form. It is possible to make the checked
+form constexpr, so no further overloads are required, to have
+both advantages in one place.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 30 aožt, 22:36
+On 30 August 2011 23:11, Daniel KrŸgler <daniel.krueg..._at_[hidden]> wrote:
+
+> I don't understand the problem: During runtime you could rely
+> on the (runtime) checked form. It is possible to make the checked
+> form constexpr, so no further overloads are required, to have
+> both advantages in one place.
+
+I don't understand how any kind of checking protects against logic errors.
+Integral values between 1-12 can be either days or months, and we can't know
+that no matter how much checking we add. We can add some sanity,
+but as mentioned, there are cases where no amount of checking we
+(try to) do in our date class protects against such problems.
+
+I guess that's a problem with a "vocabulary type". It can't provide for
+all possible vocabularies, nor can it provide for all kinds of domain-specific
+designs. It can provide a very useful building block, and it can even provide
+a bunch of very useful default facilities that can cover a wide swath of
+vocabularies/domains/designs, however you want to call it, but there will
+be limitations that need to be overcome by building things on top of it.
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 30 aožt, 22:39
+On 30 August 2011 23:36, Ville Voutilainen <ville.voutilai..._at_[hidden]> wrote:
+
+> I don't understand how any kind of checking protects against logic errors.
+> Integral values between 1-12 can be either days or months, and we can't know
+
+Not to mention that they can be years, too. :)
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 30 aožt, 22:44
+
+Why just enumerate the months?
+
+enum class DaysOfYear {
+
+ Jan01 = 1,
+
+ Jan02,
+
+ Jan03,
+
+ Jan04,
+
+ /* ... */
+
+ Dec29,
+
+ Dec30,
+
+ Dec31
+
+};
+
+class date
+
+{
+
+public:
+
+ date(int year, DaysOfYear md);
+
+ date(int year, int month, int day);
+
+ /* ... */
+
+};
+
+On Tue, Aug 30, 2011 at 4:36 PM, Ville Voutilainen <
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 30 aožt, 23:05
+
+On 8/30/2011 3:44 PM, Robert Klarer wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I'm not sure if I like it, but it is the first really new idea I have
+seen in this thread :-)
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 30 aožt, 23:14
+On Aug 30, 2011, at 5:05 PM, bs wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I'm having trouble prototyping it (or any use of class enums). How do you convert Feb03 to the two ints 2 and 3 in the date constructor? I know how to do it for enum DaysOfYear, but not for enum *class* DaysOfYear. I'm having the same trouble with the use of enum class Month previously suggested.
+
+Howard
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 30 aožt, 23:16
+On 8/30/2011 4:14 PM, Howard Hinnant wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+How do you handle Feb29?
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 30 aožt, 23:23
+On Aug 30, 2011, at 5:16 PM, bs wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+This is just prototype/throw-away code (and it doesn't compile, but I mean for it to):
+
+enum DaysOfYear {
+ Jan01 = 1, Jan02, Jan03, Jan04, Jan05, Jan06, Jan07,
+ Jan08, Jan09, Jan10, Jan11, Jan12, Jan13, Jan14,
+ Jan15, Jan16, Jan17, Jan18, Jan19, Jan20, Jan21,
+ Jan22, Jan23, Jan24, Jan25, Jan26, Jan27, Jan28,
+ Jan29, Jan30, Jan31,
+ Feb01, Feb02, Feb03, Feb04, Feb05, Feb06, Feb07,
+ Feb08, Feb09, Feb10, Feb11, Feb12, Feb13, Feb14,
+ Feb15, Feb16, Feb17, Feb18, Feb19, Feb20, Feb21,
+ Feb22, Feb23, Feb24, Feb25, Feb26, Feb27, Feb28,
+ Feb29,
+ Mar01, Mar02, Mar03, Mar04, Mar05, Mar06, Mar07,
+ Mar08, Mar09, Mar10, Mar11, Mar12, Mar13, Mar14,
+ Mar15, Mar16, Mar17, Mar18, Mar19, Mar20, Mar21,
+ Mar22, Mar23, Mar24, Mar25, Mar26, Mar27, Mar28,
+ Mar29, Mar30, Mar31,
+ Apr01, Apr02, Apr03, Apr04, Apr05, Apr06, Apr07,
+ Apr08, Apr09, Apr10, Apr11, Apr12, Apr13, Apr14,
+ Apr15, Apr16, Apr17, Apr18, Apr19, Apr20, Apr21,
+ Apr22, Apr23, Apr24, Apr25, Apr26, Apr27, Apr28,
+ Apr29, Apr30, Apr31,
+ // ...
+
+};
+
+static
+const int
+db[2][13] = {{-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364},
+ {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}};
+
+static
+const unsigned char
+mb[2][366] =
+{
+{
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12
+},
+
+{
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12
+
+}
+};
+
+static
+inline
+bool
+is_leap(int y) noexcept
+{
+ return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
+
+}
+
+struct date
+{
+ int year_;
+ int month_;
+ int day_;
+
+ date(int year, int month, int day)
+ : year_(year), month_(month), day_(day) {}
+
+ date(int year, DaysOfYear md)
+ : year_(year)
+ {
+ bool leap = is_leap(year_);
+ int doy(md);
+ if (leap)
+ {
+ month_ = mb[1][doy];
+ day_ = doy - db[1][month_-1];
+ }
+ else
+ {
+ if (doy == DaysOfYear::Feb29)
+ throw 1;
+ if (doy > DaysOfYear::Feb29)
+ --doy;
+ month_ = mb[0][doy];
+ day_ = doy - db[0][month_-1];
+ }
+ }
+
+};
+
+int main()
+{
+ date(2011, DaysOfYear::Jan04);
+
+}
+
+Howard
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 31 aožt, 02:02
+
+This compiles (using Apple LLVM):
+
+ date(int year, DaysOfYear md)
+
+ : year_(year)
+
+ {
+
+ bool leap = is_leap(year_);
+
+ int doy = int(md); // explicit conversion
+
+ if (leap)
+
+ {
+
+ month_ = mb[1][doy];
+
+ day_ = doy - db[1][month_-1];
+
+ }
+
+ else
+
+ {
+
+ if (md == DaysOfYear::Feb29) // avoid spurious conversion
+
+ throw 1;
+
+ if (md > DaysOfYear::Feb29) // avoid spurious conversion
+
+ --doy;
+
+ month_ = mb[0][doy];
+
+ day_ = doy - db[0][month_-1];
+
+ }
+
+ }
+
+On Tue, Aug 30, 2011 at 5:23 PM, Howard Hinnant <howard.hinn..._at_[hidden]>wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 31 aožt, 02:28
+On Aug 30, 2011, at 8:02 PM, Robert Klarer wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Interesting. Using :
+
+enum class DaysOfYear {
+ Jan01 = 1, Jan02, Jan03, Jan04, Jan05, Jan06, Jan07,
+...
+
+I'm getting:
+
+test.cpp:141:17: error: cannot initialize a variable of type 'int' with an lvalue of type 'DaysOfYear'
+ int doy(md);
+ ^ ~~
+1 error generated.
+
+But if I use:
+
+enum DaysOfYear {
+ Jan01 = 1, Jan02, Jan03, Jan04, Jan05, Jan06, Jan07,
+...
+
+then it works.
+
+Apple clang version 3.0 (tags/Apple/clang-211.10.1) (based on LLVM 3.0svn)
+Target: x86_64-apple-darwin11.1.0
+Thread model: posix
+
+I'm not a class enum expert, so I'm not positive what the correct behavior is supposed to be. [dcl.enum]/p9 says "no implicit conversion". I can't find where it says there /is/ an explicit conversion. Anyone here know for sure?
+
+Howard
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 31 aožt, 02:29
+
+Also, I think this version of the constructor is going to be cheaper than
+the one I just posted.
+
+ date(int year, DaysOfYear md)
+
+ : year_(year)
+
+ {
+
+ bool leap = false;
+
+ int doy = int(md);
+
+ if (md == DaysOfYear::Feb29)
+
+ {
+
+ if ((leap = is_leap(year_)))
+
+ {
+
+ throw 1;
+
+ }
+
+ }
+
+ month_ = mb[leap ? 0 : 1][doy];
+
+ day_ = doy - db[leap ? 0 : 1][month_-1];
+
+ }
+
+Verifying the date costs one integer equality comparison, but then you need
+to decompose the DaysOfYear value to a month and a day.
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 31 aožt, 02:52
+Why are we doing all these tests for Feb29 as runtime tests?
+
+If DayOfYear is a literal type, we can hoist that test to compile time (danger - silly template interfaces ahead)
+
+enum Feb29Policy { BeforeFeb29, IsFeb29, AfterFeb29 };
+
+template<Feb29Policy>
+struct DayOfYear;
+
+template<>
+struct DayOfYear<BeforeFeb29> {
+ constexpr explicit DayOfYear(int val) : m_day{val} {}
+
+ constexpr auto dayOfYear(int year) -> int { return m_day; }
+
+private:
+ int m_day;
+
+};
+
+template<>
+struct DayOfYear<IsFeb29> {
+ constexpr explicit DayOfYear(int val) : m_day{val} {}
+
+ constexpr auto dayOfYear(int year) -> int { return isLeapYear(year) ? throw bad_date{} : 60; }
+
+};
+
+template<>
+struct DayOfYear<BeforeFeb29> {
+ constexpr explicit DayOfYear(int val) : m_day{val} {}
+
+ constexpr auto dayOfYear(int year) -> int { return isLeapYear ? m_day-1 : m_day; }
+
+private:
+ int m_day;
+
+};
+
+Now we simply create the 366 literal values:
+
+constexpr DayOfYear<BeforeFeb29> Jan01{1};
+constexpr DayOfYear<BeforeFeb29> Jan02{2};
+...
+constexpr DayOfYear<BeforeFeb29> Feb28{59};
+constexpr DayOfYear<IsFeb29> Feb29{60};
+constexpr DayOfYear<AfterFeb29> Mar01{61};
+...
+constexpr DayOfYear<AfterFeb29> Dec31{366};
+
+Unfortunately, anything expecting to work with these literal values must be written as a function template on enum Feb29Policy, but we already have this issue with chrono times...
+
+(No, I'm not being serious, but if we are trying to optimize this approach, why hold back!)
+
+AlisdairM
+
+On 30 Aug 2011, at 20:29, Robert Klarer wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 31 aožt, 08:09
+2011/8/31 Howard Hinnant <howard.hinn..._at_[hidden]>:
+[..]
+
+- Afficher le texte des messages prŽcŽdents -
+
+The compiler is right to reject the attempt to direct-initialize
+an integral type with a scoped enum. The semantics of this
+initialization is defined in the bulleted list of 8.5 p16. Since there
+are no class types involved, we need to skip b6+7 and end in
+the last bullet:
+
+"Otherwise, the initial value of the object being initialized is the
+(possibly converted) value of the initializer
+expression. Standard conversions (Clause 4) will be used, if
+necessary, to convert the initializer
+expression to the cv-unqualified version of the destination type; no
+user-defined conversions are considered.
+If the conversion cannot be done, the initialization is ill-formed."
+
+And we find that there is no standard conversion from a *scoped* enum
+to int. So, direct-initialization is not sufficient here, you need an (explicit)
+static_cast.
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 31 aožt, 09:24
+
+Il giorno 31/ago/2011, alle ore 08:09, Daniel KrŸgler ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Correct. A static_cast is the correct way convert a scoped enum to an integral (see 5.2.9/9). This works as it should in Clang:
+
+ int doy = static_cast<int>(md);
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 1 sep, 02:55
+On Aug 31, 2011, at 3:24 AM, Alberto Ganesh Barbati wrote:
+
+> Correct. A static_cast is the correct way convert a scoped enum to an integral (see 5.2.9/9). This works as it should in Clang:
+
+> int doy = static_cast<int>(md);
+
+Thanks Daniel, Ganesh. Here's Robert's date constructor lightly tested:
+
+ date(int year, DaysOfYear md)
+ : year_(year)
+ {
+ int doy = static_cast<int>(md) - 1;
+ if (md == DaysOfYear::Feb29)
+ {
+ if (!is_leap(year_))
+ throw 1;
+ }
+ month_ = mb[1][doy];
+ day_ = doy - db[1][month_-1];
+ }
+
+Howard
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 1 sep, 10:51
+
+Il giorno 01/set/2011, alle ore 02:55, Howard Hinnant ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+That is very nice indeed. It might be favorite ctor for hard-coded date values. However, we still need a way to make a DaysOfYear value from separate month/day values, which is what is needed most often:
+
+ int y, m, d;
+ read_from_user(y, m, d);
+ date dt(y, ???);
+
+We could have a make_doy() function like this:
+
+ date d(2011, make_doy(m, d));
+
+but we are still facing the same issue regarding the order of parameters (too easy to write make_doy(d, m) incorrectly). We could have another enum class for months and have a make_month helper function, like this:
+
+ date d(2011, make_doy(make_month(m), d));
+
+which, alas, isn't any prettier than where we started from, that is:
+
+ date d(year(2011), month(m), day(d));
+
+in my humble opinion. Do we have alternatives to make_doy/make_month?
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 1 sep, 11:00
+On 1 September 2011 11:51, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+
+> but we are still facing the same issue regarding the order of parameters (too easy to write make_doy(d, m) incorrectly). We could have another enum class for months and have a make_month helper function, like this:
+> date d(2011, make_doy(make_month(m), d));
+
+I suppose it's just equally easy to write date d(2011,
+make_doy(make_month(d), m));
+
+and oopsy-daisy we go. :) I seriously doubt the success chance of such
+attempts at protective measures.
+As long as the date components need to be constructible from ints
+(which is just unavoidable), it's always
+possible to mix them up.
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 1 sep, 15:46
+On 1 September 2011 04:00, Ville Voutilainen
+<ville.voutilai..._at_[hidden]> wrote:
+
+I seriously doubt the success chance of such
+
+> attempts at protective measures.
+> As long as the date components need to be constructible from ints
+> (which is just unavoidable), it's always
+> possible to mix them up.
+
+So, you are saying that because we cannot prevent *all* possible
+errors, we should never try and prevent *any* possible errors. I
+disagree with that position.
+
+The least error prone is to have the name right next to the value, at
+the expense of being the most verbose. We value terseness as well as
+correctness, and hence are looking for the balance between the two.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 1 sep, 17:27
+
+> So, you are saying that because we cannot prevent *all* possible
+> errors, we should never try and prevent *any* possible errors. I
+> disagree with that position.
+
+I have no problems with the proposed enum
+overloads. I expect to find them very useful
+for cases where I know (some) of the values
+before runtime. For runtime cases, I don't
+see the benefit that the tedious syntax is
+supposed to bring. For such cases I have
+to get the order right anyway, so wrapping
+won't help much, if at all. Having such
+wrappers most likely brings a false sense
+of security to users.
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 1 sep, 18:21
+
+Has something like make_date (below) been discussed? There's still some
+extra typing, and it doesn't eliminate the potential for error, but it
+allows the programmer to record his or her intention, at least.
+
+Examples:
+
+auto today = make_date<ymd>(2011, 9, 1);
+
+auto yesterday = make_date<mdy>(8, 31, 2011);
+
+auto tomorrow = make_date<dmy>(2, 9, 2011);
+
+//auto never = make_date<dym>(2, 10, 2011); // static assertion
+
+Implementation:
+
+struct date
+
+{
+
+ int year_;
+
+ int month_;
+
+ int day_;
+
+ date(int year, int month, int day)
+
+ : year_(year), month_(month), day_(day) {}
+
+};
+
+enum DateFormat {
+
+ ymd,
+
+ mdy,
+
+ dmy,
+
+ invalid_DateFormat,
+
+ dym = invalid_DateFormat,
+
+ myd = invalid_DateFormat,
+
+ ydm = invalid_DateFormat
+
+};
+
+template <DateFormat fmt>
+
+inline
+
+date make_date(int, int, int)
+
+{
+
+ static_assert(fmt != invalid_DateFormat, "Invalid date format.");
+
+ return date(0, 0, 0);
+
+}
+
+template <>
+
+inline
+
+ date make_date<ymd>(int m, int d, int y) {return date(y, m, d); }
+
+template <>
+
+inline
+
+ date make_date<mdy>(int m, int d, int y) {return date(y, m, d); }
+
+template <>
+
+inline
+
+ date make_date<dmy>(int d, int m, int y) {return date(y, m, d); }
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 1 sep, 18:26
+
+> I have no problems with the proposed enum
+> overloads. I expect to find them very useful
+> for cases where I know (some) of the values
+> before runtime. For runtime cases, I don't
+> see the benefit that the tedious syntax is
+> supposed to bring. For such cases I have
+
+This actually means that I'd like to
+have a bare-int version, at the very
+least. If there are other overloads,
+I don't think I mind. Let's just not
+go overboard with it, ok? :)
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 2 sep, 00:30
+
+Il giorno 01/set/2011, alle ore 18:21, Robert Klarer ha scritto:
+
+> Has something like make_date (below) been discussed? There's still some extra typing, and it doesn't eliminate the potential for error, but it allows the programmer to record his or her intention, at least.
+
+> Examples:
+
+> auto today = make_date<ymd>(2011, 9, 1);
+> auto yesterday = make_date<mdy>(8, 31, 2011);
+> auto tomorrow = make_date<dmy>(2, 9, 2011);
+> //auto never = make_date<dym>(2, 10, 2011); // static assertion
+
+I don't find it much better than the simpler:
+
+auto today = make_date_ymd(2011, 9, 1);
+auto yesterday = make_date_mdy(8, 31, 2011);
+auto tomorrow = make_date_dmy(2, 9, 2011);
+
+Anyway, I believe we are making a big mistake by using simple examples like this as arguments. Dates will rarely be constructed from hard-coded literals. They will usually be constructed from variables that may have been read or computed. I understand that in the typical scenario where the values are used immediately, as in:
+
+ int y, m, d;
+ read_user_input(y, m, d);
+ // make date from y, m, d
+
+there's very little difference between:
+
+ date dt = make_date_ymd(y, m, d)
+
+and
+
+ date dt { year(y), month(m), day(d) };
+
+There's basically the same chance that the user gets it wrong in both cases. (Consider that the order of the parameters in read_user_input may also be wrong!) I can hardly say which one is better in such a limited scenario, so everyone is just biased by their personal preference. But we have a more significant difference in the case where the y, m and d variables are obtained in a part of the code and the actual date is constructed elsewhere. Having separate types for year, month, day can be useful to avoid inadvertent exchanges, comparison between the wrong variables, etc. like any physical dimensional analysis library does. We should not underestimate that.
+
+Just my opinion,
+
+Ganesh
+
+Robert Klarer
+====================================
+ Autres options 2 sep, 06:30
+
+On Tue, Aug 30, 2011 at 8:52 PM, Alisdair Meredith <w..._at_[hidden]>wrote:
+
+> Why are we doing all these tests for Feb29 as runtime tests?
+
+Good question! I'm hoping that something like this will work, but I don't
+have a compiler that does constexpr:
+
+enum class DaysOfYear {
+
+ Jan01 = 0x0101,
+
+ Jan02, Jan03, Jan04, Jan05, Jan06, Jan07, Jan08, Jan09, Jan10, Jan11,
+
+ Jan12, Jan13, Jan14, Jan15, Jan16, Jan17, Jan18, Jan19, Jan20, Jan21,
+
+ Jan22, Jan23, Jan24, Jan25, Jan26, Jan27, Jan28, Jan29, Jan30, Jan31,
+
+ Feb01 = 0x0201,
+
+ Feb02, Feb03, Feb04, Feb05, Feb06, Feb07, Feb08, Feb09, Feb10, Feb11,
+
+ Feb12, Feb13, Feb14, Feb15, Feb16, Feb17, Feb18, Feb19, Feb20, Feb21,
+
+ Feb22, Feb23, Feb24, Feb25, Feb26, Feb27, Feb28, Feb29,
+
+ Mar01 = 0x0301,
+
+ Mar02, Mar03, Mar04, Mar05, Mar06, Mar07, Mar08, Mar09, Mar10, Mar11,
+
+ Mar12, Mar13, Mar14, Mar15, Mar16, Mar17, Mar18, Mar19, Mar20, Mar21,
+
+ Mar22, Mar23, Mar24, Mar25, Mar26, Mar27, Mar28, Mar29, Mar30, Mar31,
+
+ Apr01 = 0x0401,
+
+ Apr02, Apr03, Apr04, Apr05, Apr06, Apr07, Apr08, Apr09, Apr10, Apr11,
+
+ Apr12, Apr13, Apr14, Apr15, Apr16, Apr17, Apr18, Apr19, Apr20, Apr21,
+
+ Apr22, Apr23, Apr24, Apr25, Apr26, Apr27, Apr28, Apr29, Apr30,
+
+ May01 = 0x0501,
+
+ May02, May03, May04, May05, May06, May07, May08, May09, May10, May11,
+
+ May12, May13, May14, May15, May16, May17, May18, May19, May20, May21,
+
+ May22, May23, May24, May25, May26, May27, May28, May29, May30, May31,
+
+ Jun01 = 0x0601,
+
+ Jun02, Jun03, Jun04, Jun05, Jun06, Jun07, Jun08, Jun09, Jun10, Jun11,
+
+ Jun12, Jun13, Jun14, Jun15, Jun16, Jun17, Jun18, Jun19, Jun20, Jun21,
+
+ Jun22, Jun23, Jun24, Jun25, Jun26, Jun27, Jun28, Jun29, Jun30,
+
+ Jul01 = 0x0701,
+
+ Jul02, Jul03, Jul04, Jul05, Jul06, Jul07, Jul08, Jul09, Jul10, Jul11,
+
+ Jul12, Jul13, Jul14, Jul15, Jul16, Jul17, Jul18, Jul19, Jul20, Jul21,
+
+ Jul22, Jul23, Jul24, Jul25, Jul26, Jul27, Jul28, Jul29, Jul30, Jul31,
+
+ Aug01 = 0x0801,
+
+ Aug02, Aug03, Aug04, Aug05, Aug06, Aug07, Aug08, Aug09, Aug10, Aug11,
+
+ Aug12, Aug13, Aug14, Aug15, Aug16, Aug17, Aug18, Aug19, Aug20, Aug21,
+
+ Aug22, Aug23, Aug24, Aug25, Aug26, Aug27, Aug28, Aug29, Aug30, Aug31,
+
+ Sep01 = 0x0901,
+
+ Sep02, Sep03, Sep04, Sep05, Sep06, Sep07, Sep08, Sep09, Sep10, Sep11,
+
+ Sep12, Sep13, Sep14, Sep15, Sep16, Sep17, Sep18, Sep19, Sep20, Sep21,
+
+ Sep22, Sep23, Sep24, Sep25, Sep26, Sep27, Sep28, Sep29, Sep30,
+
+ Oct01 = 0x0A01,
+
+ Oct02, Oct03, Oct04, Oct05, Oct06, Oct07, Oct08, Oct09, Oct10, Oct11,
+
+ Oct12, Oct13, Oct14, Oct15, Oct16, Oct17, Oct18, Oct19, Oct20, Oct21,
+
+ Oct22, Oct23, Oct24, Oct25, Oct26, Oct27, Oct28, Oct29, Oct30, Oct31,
+
+ Nov01 = 0x0B01,
+
+ Nov02, Nov03, Nov04, Nov05, Nov06, Nov07, Nov08, Nov09, Nov10, Nov11,
+
+ Nov12, Nov13, Nov14, Nov15, Nov16, Nov17, Nov18, Nov19, Nov20, Nov21,
+
+ Nov22, Nov23, Nov24, Nov25, Nov26, Nov27, Nov28, Nov29, Nov30,
+
+ Dec01 = 0x0C01,
+
+ Dec02, Dec03, Dec04, Dec05, Dec06, Dec07, Dec08, Dec09, Dec10, Dec11,
+
+ Dec12, Dec13, Dec14, Dec15, Dec16, Dec17, Dec18, Dec19, Dec20, Dec21,
+
+ Dec22, Dec23, Dec24, Dec25, Dec26, Dec27, Dec28, Dec29, Dec30, Dec31
+
+};
+
+inline
+
+constexpr bool is_leap(int y) { return y % 4 == 0 && (y % 100 != 0 || y %
+400 == 0); }
+
+inline
+
+constexpr int extract_month(DaysOfYear md) { return static_cast<int>(md) >>
+8; }
+
+inline
+
+constexpr int extract_day(DaysOfYear md) { return static_cast<int>(md) &
+0xFF; }
+
+struct date
+
+{
+
+ int year_;
+
+ int month_;
+
+ int day_;
+
+ constexpr date(int year, int month, int day)
+
+ : year_(year), month_(month), day_(day) {}
+
+};
+
+inline
+
+constexpr date make_date(DaysOfYear md, int y)
+
+{
+
+ static_assert(md != DaysOfYear::Feb29 || is_leap(y), "Bad date.");
+
+ return date(y, extract_month(md), extract_day(md));
+
+}
+
+Off-topic:
+
+A problem that I've noticed is that static_assert doesn't seem to work well
+with constexpr functions, even with the changes introduced through N3268 (
+http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3268.htm).
+
+The problem is that the arguments to make_date, above, may or may not be
+constant expressions, so the static_assertion may or may not be ill-formed.
+I don't think there's any way to say "check this assertion only if the
+function is computed statically."
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 2 sep, 06:44
+
+On Thu, Sep 1, 2011 at 6:30 PM, Alberto Ganesh Barbati
+<gan..._at_[hidden]>wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I see it this way: we need to be able to initialize a date with a triple of
+ints. I'd like to see a simple, straight-forward constructor that allows the
+date class to work as a literal type. We also need a better, safer, less
+error-prone interface for initializing dates. For these more complicated
+initializations, I'd like there to be a variety of make_date functions. Date
+validation, unit types (days, months, years), and support for alternative
+formats and argument orders (ymd, mdy, etc) belong in the make_date
+functions, IMO, not in the constructor(s).
+
+The people that really need to use the constructor directly can do so, but
+most programmers should be encouraged to use the make_date functions as a
+matter of good engineering.
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 2 sep, 16:38
+
+Sorry for replying to my own post, but I wanted to point out that the
+make_date approach has the added advantage of extensibility. For example, if
+a programmer wants to enumerate month names other than the English ones, a
+make_date-based interface would facilitate that.
+
+On Fri, Sep 2, 2011 at 12:44 AM, Robert Klarer <robert.kla..._at_[hidden]>wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 2 sep, 17:03
+
+Il giorno 02/set/2011, alle ore 16:38, Robert Klarer ha scritto:
+
+> Sorry for replying to my own post, but I wanted to point out that the make_date approach has the added advantage of extensibility. For example, if a programmer wants to enumerate month names other than the English ones, a make_date-based interface would facilitate that.
+
+What do you mean by "enumerate month names other than the English ones". While I agree that having factory functions can be a good thing to have (in addition to constructors), I don't believe localization should be handled in factory functions. And non-gregorian calendars should be managed by a totally different class. In fact, here's my proposed approach for a possible multi-calendar date library:
+
+namespace std
+{
+ namespace datelib
+ {
+ class days
+ {
+ // simple wrapper over int: a date duration in days is common to all calendars
+ };
+
+ // a basic date_time facility, templated on a date class and a TimeDuration
+ template <class DateType, class TimeDuration = std::chrono<int>>
+ class date_time_base
+ {
+ static_assert(TimeDuration::max() >= std::chrono<int>(60 * 60 * 24), "TimeDuration time must span at least one entire day");
+
+ DateType date;
+ TimeDuration time_of_day;
+
+ // ...
+ };
+
+ namespace gregorian
+ {
+ // a year/month/day gregorian date class
+ class date
+ {
+ //...
+
+ // date conversion facilities
+ days days_since_1970() const;
+ static date date_after_1970(days d);
+ };
+
+ // aliases for gregorian date_time classes
+ template <class TimeDuration>
+ using basic_date_time<TimeDuration> = date_time_base<date, TimeDuration>
+
+ using date_time = date_time_base<date>;
+ }
+
+ namespace chinese
+ {
+ // a chinese date class
+ class date
+ {
+ //...
+
+ // date conversion facilities
+ days days_since_1970() const;
+ static date date_after_1970(days d);
+ };
+
+ // aliases for chinese date_time classes
+ template <class TimeDuration>
+ using basic_date_time<TimeDuration> = date_time_base<date, TimeDuration>
+
+ using date_time = date_time_base<date>;
+ }
+
+ // cross-calendar conversion functions
+ template <class FromDate, class ToDate>
+ ToDate calendar_cast(const FromDate& from)
+ {
+ return ToDate::date_after_1970(from.days_since_1970());
+ }
+
+ template <class FromDateTime, class ToDateTime>
+ ToDateTime calendar_cast(const FromDateTime& from)
+ {
+ return ToDateTime::date_after_1970(from.days_since_1970(), from.time_of_day());
+ }
+ }
+
+}
+
+Sample of usage:
+
+int main()
+{
+ using namespace std::chrono;
+ using namespace std::datelib;
+ using namespace std::datelib::gregorian;
+
+ date gdt(year(2010), september, day(2));
+
+ // 1-second precision
+ date_time gdti(gdt, hours(10)); // 10 o'clock (uses std::chrono::hours)
+
+ // a more precise date_time class
+ basic_date_time<microseconds> precise(gdti);
+
+ // cross calendar conversions
+ chinese::date cdt = calendar_cast<chinese::date>(gdt);
+ chinese::date_time cdtm = calendar_cast<chinese::date>(gdti);
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Robert Klarer
+Afficher le profil
+ Autres options 2 sep, 17:34
+
+On Fri, Sep 2, 2011 at 11:03 AM, Alberto Ganesh Barbati
+<gan..._at_[hidden]>wrote:
+
+> Il giorno 02/set/2011, alle ore 16:38, Robert Klarer ha scritto:
+
+> Sorry for replying to my own post, but I wanted to point out that the
+> make_date approach has the added advantage of extensibility. For example, if
+> a programmer wants to enumerate month names other than the English ones, a
+> make_date-based interface would facilitate that.
+
+> What do you mean by "enumerate month names other than the English ones".
+> While I agree that having factory functions can be a good thing to have (in
+> addition to constructors), I don't believe localization should be handled in
+> factory functions. And non-gregorian calendars should be managed by a
+> totally different class.
+
+I don't mean localization. What I mean is that, if the standard date library
+contains a scoped enum like this:
+
+namespace chrono {
+ class enum MonthName { January, February, March /* ... */ }
+ date make_date(MonthName m, int d, int y);
+
+}
+
+then a programmer may wish to write something like this, for his or her own
+convenience:
+
+namespace User {
+ class enum MonthName_fr { Janvier, Fevrier, Mars /* ... */ }
+ chrono::date make_date(MonthName_fr m, int d, int y);
+
+}
+
+I don't want to get hung up on the details of my offhand (and weak, I admit)
+example. My main point is that make_date or some equivalent repertoire of
+factory functions allows for some user customization of the library. This
+point was being made in defence of the argument that chrono::date should
+have a small number of very basic (and potentially unsafe) constructors, and
+that the library should provide more sophisticated functionality at the
+make_date level. Users should be implored to use make_date rather than the
+constructor, unless they're sure they know what they're doing.
+
+====================================
+====================================
+
+
+
+Daniel KrŸgler
+====================================
+ Autres options 2 sep, 19:08
+2011/9/2 Robert Klarer <robert.kla..._at_[hidden]>:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Just for clarification, Robert: You are referring here to a similar
+mechanism as we have for make_error_code and make_error_condition,
+right?
+
+- Daniel
+
+====================================
+====================================
+
+
+
+Pablo Halpern
+====================================
+ Autres options 2 sep, 20:00
+
+On 09/01/2011 06:30 PM, Alberto Ganesh Barbati wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+This is almost exactly what I was about to propose. No need to
+introduce three new identifiers (ymd, mdy, dmy) plus a template
+function. Just create three functions. This mechanism is currently my
+favorite. The make_date_* functions could, alternatively, be written as
+static members:
+
+ class date
+ {
+ public:
+ static date make_ymd(int, int, int);
+ static date make_mdy(int, int, int);
+ static date make_dmy(int, int, int);
+ };
+
+and there could be checked and unchecked variants of each.
+
+- Afficher le texte des messages prŽcŽdents -
+
+Yes. However, my bias against the latter form is two-fold.
+
+ 1. It introduces extra classes for month, day, and year for very
+little gain and
+ 2. I am one of those people who prefers to use namespace-qualified
+name and avoids "using" directives. It's hard to imagine anything more
+cumbersome than:
+
+ std::chrono:date dt { std::chrono:year(y), std::chrono:month(m),
+std::chrono:day(d) };
+
+> But we have a more significant difference in the case where the y, m
+> and d variables are obtained in a part of the code and the actual date
+> is constructed elsewhere. Having separate types for year, month, day
+> can be useful to avoid inadvertent exchanges, comparison between the
+> wrong variables, etc. like any physical dimensional analysis library
+> does. We should not underestimate that.
+
+True. If we care to make months, days, and years into first-class
+concepts and not just a means to build a date, then I would be happy to
+entertain that concept. A millisecond, for example, is a useful type in
+and of itself, not just as a way to test a timed mutex. The fact that a
+millisecond is type-safe and distinct from a microsecond is useful. If
+we want to have month, day, and year be real types independent of date,
+then I would support having a date constructor or make_date() function
+that is overloaded using these types -- but I still would like the
+three-integer versions.
+
+-Pablo
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 2 sep, 20:42
+On 2 September 2011 21:00, Pablo Halpern
+
+<phalp..._at_[hidden]> wrote:
+> 2. I am one of those people who prefers to use namespace-qualified name
+> and avoids "using" directives. It's hard to imagine anything more
+> cumbersome than:
+> std::chrono:date dt { std::chrono:year(y), std::chrono:month(m),
+> std::chrono:day(d) };
+
+Won't ADL find them?
+
+====================================
+====================================
+
+
+
+Pablo Halpern
+====================================
+ Autres options 2 sep, 22:30
+On 09/02/2011 02:42 PM, Ville Voutilainen wrote:
+> On 2 September 2011 21:00, Pablo Halpern
+> <phalp..._at_[hidden]> wrote:
+>> 2. I am one of those people who prefers to use namespace-qualified name
+>> and avoids "using" directives. It's hard to imagine anything more
+>> cumbersome than:
+>> std::chrono:date dt { std::chrono:year(y), std::chrono:month(m),
+>> std::chrono:day(d) };
+> Won't ADL find them?
+
+I don't see how. If y is an int, now would ADL know to look in
+std::crono for the year function or the year class?
+
+-Pablo
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 2 sep, 22:47
+On 2 September 2011 23:30, Pablo Halpern
+
+<phalp..._at_[hidden]> wrote:
+>> Won't ADL find them?
+> I don't see how. If y is an int, now would ADL know to look in std::crono
+> for the year function or the year class?
+
+Right you are, ADL doesn't help.
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 3 sep, 09:09
+
+Il giorno 02/set/2011, alle ore 20:00, Pablo Halpern ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+Scary. To think that I just proposed the namespace to be spelled std::whatever::gregorian... :-|
+
+By the way, among the several proposed alternatives, we still haven't considered this:
+
+ date dt { ymd, 2010, 9, 3 };
+
+that is: just one mandatory tag followed by three ints. That is not much different from:
+
+ date dt = make_date_ymd(2010, 9, 3);
+
+except for programming style. The mandatory tag could be combined with the "check" tag:
+
+ date dt { ymd_unchecked, 2010, 9, 3 };
+
+if checked is to be the default, or
+
+ date dt { ymd_checked, 2010, 9, 3 };
+
+otherwise. Alternatively, we could not favor either, dropping the ymd and using only the checked/unchecked tags.
+
+>> But we have a more significant difference in the case where the y, m and d variables are obtained in a part of the code and the actual date is constructed elsewhere. Having separate types for year, month, day can be useful to avoid inadvertent exchanges, comparison between the wrong variables, etc. like any physical dimensional analysis library does. We should not underestimate that.
+> True. If we care to make months, days, and years into first-class concepts and not just a means to build a date, then I would be happy to entertain that concept. A millisecond, for example, is a useful type in and of itself, not just as a way to test a timed mutex. The fact that a millisecond is type-safe and distinct from a microsecond is useful. If we want to have month, day, and year be real types independent of date, then I would support having a date constructor or make_date() function that is overloaded using these types -- but I still would like the three-integer versions.
+
+There actually is an argument against type-tagging here... chrono::seconds, chrono::hours, etc. are really different unit of measures. They are not validated and you can write chrono::hours(10) + chrono::second(500), with a well defined meaning. However, if I write year(2010) or day(5) I really mean a *specific* year and a specific day (of the month). Writing day(1000) makes no sense and an implementation might be expected to assert. It doesn't make sense to write year(2010) + day(5). It's not a case that hours/seconds are plural while year/day are singular. On the other hand we will want to have a "date duration" type whose name could naturally be spelled "days" as in:
+
+ date dt2 { ymd, 2010, 9, 2 };
+ date dt3 { ymd, 2010, 9, 3 };
+ days diff = dt3 - dt2;
+
+and we might want to have date arithmetic like:
+
+ date dt5 = dt2 + days(3); // 2010-09-05
+
+or even
+
+ date dtx = dt2 + months(1); // 2010-10-02
+
+(of course, snapping becomes an issue here, but that's another story)
+
+Having types named both "day" and "days" could definitely be a source of confusion.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 3 sep, 16:19
+
+On 2011-09-03, at 3:09 AM, Alberto Ganesh Barbati <gan..._at_[hidden]>
+
+- Afficher le texte des messages prŽcŽdents -
+
+If the constructor needs to handle various ymd-style tags and perform validity checking, then it can't be a literal constructor. That's one of the reasons I've been advocating make_date. Let's keep the constructor simple and do the more complicated stuff at the make_date level.
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 3 sep, 16:26
+
+On 3 Sep 2011, at 10:19, Robert Klarer wrote:
+
+> If the constructor needs to handle various ymd-style tags and perform validity checking, then it can't be a literal constructor. That's one of the reasons I've been advocating make_date. Let's keep the constructor simple and do the more complicated stuff at the make_date level.
+
+Why would the presence of tags cause a problem for making literal values? I don't see that any of the validation we are expecting cannot be done in a constexpr function, and hence in a constexpr constructor (by calling a constexpr function from an initializer if necessary).
+
+I am having problems reconciling 'assert'-style validation with constexpr constructors, but that seems to be a broad enough language-design issue that I would want to throw it back over to Evolution.
+
+AlisdairM
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 3 sep, 17:37
+
+On Sat, Sep 3, 2011 at 10:26 AM, Alisdair Meredith <w..._at_[hidden]>wrote:
+
+> On 3 Sep 2011, at 10:19, Robert Klarer wrote:
+
+> > If the constructor needs to handle various ymd-style tags and perform
+> validity checking, then it can't be a literal constructor. That's one of the
+> reasons I've been advocating make_date. Let's keep the constructor simple
+> and do the more complicated stuff at the make_date level.
+
+> Why would the presence of tags cause a problem for making literal values?
+> I don't see that any of the validation we are expecting cannot be done in a
+> constexpr function, and hence in a constexpr constructor (by calling a
+> constexpr function from an initializer if necessary).'
+
+According to 7.1.5, constexpr constructors must have empty function bodies,
+apart from:
+- typedefs and aliases that don't define classes or enums
+- static_assertions
+- using declarations and using directives
+
+This means that you can't switch on ymd/mdy/dmy anywhere inside the curly
+braces, and you can't do any validity checking. It might be possible to
+contrive to do these things in the ctor-initializer list, but that's
+cheating, and it sets a bad example.
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 3 sep, 17:47
+
+Assuming that 'ymd' etc. Are all the same enum type, and not literals of distinct tag types - which was how I read the this.
+
+AlisdairM
+
+Sent from my iPad
+
+On 3 Sep 2011, at 11:37, Robert Klarer <robert.kla..._at_[hidden]> wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 3 sep, 20:08
+
+Alisdair is correct. ymd and ymd_checked are supposed to be (constexpr) values of distinct types.
+
+Ganesh
+
+Il giorno 03/set/2011, alle ore 17:47, Alisdair Meredith <w..._at_[hidden]> ha scritto:
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 3 sep, 20:42
+
+I see. Thanks.
+I still maintain that ymd_checked can't be implemented in a literal
+constructor, because the code to do the checking cannot be written in the
+ctor's function body.
+
+On Sat, Sep 3, 2011 at 2:08 PM, Alberto Ganesh Barbati
+<gan..._at_[hidden]>wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 3 sep, 22:25
+
+I should respond to myself (again, sorry) to clarify that I understand that
+your intention is that the "unchecked" variant would be a literal
+constructor and the "checked" variant would not, but I fear the result will
+be misleading:
+
+struct unchecked_t {} unchecked;
+struct checked_t {} checked;
+
+stuct date {
+int m_; int d_; int y_;
+constexpr date(unchecked_t, int m, int d, int y) : m_(m), d_(d), y_(y) {}
+date(checked_t, int m, int d, int y) : m_(m), d_(d), y_(y) { /* checking
+code here */ }
+
+};
+
+date a(unchecked, 12, 31, 2011); // literal
+date b(checked, 12, 31, 2011); // not literal
+
+It's not clear from the definition of b that it won't be a literal. The tags
+identify one important semantic difference between the two constructor
+invocations (i.e., that one is checked and the other is not), and that
+implies that there is no other semantic difference. Less misleading names
+might be
+
+date a(unchecked_and_potentially_literal, 12, 31, 2011); // literal
+date b(checked, 12, 31, 2011); // not literal
+
+Of course, that's absurd. An alternative is to introduce "literal" as a
+synonym for "unchecked":
+
+int m = 12; int d = 31; int y = 2011;
+
+date a(literal, 12, 31, 2011);
+date b(unchecked, m, d, y); // unchecked, but not a literal
+date c(checked, 12, 31, 2011); // checked and not a literal
+
+Unfortunately, the literal tag isn't enforced:
+date d(literal, m, d, y); // unchecked, not a literal
+
+I don't like tags.
+
+On Sat, Sep 3, 2011 at 2:42 PM, Robert Klarer <robert.kla..._at_[hidden]>wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 3 sep, 22:40
+
+On 3 Sep 2011, at 16:25, Robert Klarer wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I still don't understand why the checked form can't be a literal constructor:
+
+date::date(unchecked_tag, int year, int month, int day)
+ : date{ !is_valid_ymd(year, month, day) ? throw bad_date{} : unchecked, year, month, day)
+ {
+
+}
+
+constexpr bool is_valid_ymd(int year, int month, int day ) {
+ return year >= MIN_SUPPORTED_YEAR
+ && year <= MAX_SUPPORTED_YEAR
+ && month > 0
+ && month < 13
+ && day > 0
+ && day < days_in_month(year, month);
+)
+
+I'm leaving days_in_month(...) as an exercise for the reader as the point is simply to show that there is no fundamental reason that the checked constructor not be constexpr.
+
+You might not like the style of the implementation, but that's a different matter. Fundamentally, both checked and unchecked constructors may be defined as constexpr.
+
+The tricky part is adding assertions to the 'unchecked' constructor in 'defensive' build modes.
+
+AlisdairM
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 3 sep, 22:57
+
+On Sat, Sep 3, 2011 at 4:40 PM, Alisdair Meredith <w..._at_[hidden]>wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I agree that the standard allows what you've written, but I don't believe
+that it will work in practice. Maybe my understanding of literal classes is
+flawed, but I thought that the point of literals is that you can use them in
+contexts where compile-time constant values are needed. A throw statement is
+definitely not something that will be computed at compile time, so a
+constructor with a throw in it is not a literal constructor, regardless of
+the constexpr specifier.
+
+If 7.1.5 prohibits you from writing something in the literal constructor's
+function body, you should assume that you can't write it in the
+ctor-initializer list, either, regardless of what the standard seems to
+permit.
+
+Maybe core already has an issue open for this. I will check...
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 3 sep, 23:01
+On 3 September 2011 23:57, Robert Klarer <robert.kla..._at_[hidden]> wrote:
+
+> If 7.1.5 prohibits you from writing something in the literal constructor's
+> function body, you should assume that you can't write it in the
+> ctor-initializer list, either, regardless of what the standard seems to
+> permit.
+> Maybe core already has an issue open for this. I will check...
+
+If a ternary operator expression throws, it's not a constant expression. If it
+doesn't throw, it can be, and in this case is.
+
+====================================
+====================================
+
+
+
+Alisdair Meredith
+====================================
+ Autres options 3 sep, 23:05
+
+On 3Sep, 2011, at 4:57 PM, Robert Klarer wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+constexpr functions are perfectly allowed to throw exceptions. Remember a constexpr function is also a regular runtime function, and will have that runtime behavior if called with non-literal values.
+
+On the other hand, if you call a constexpr constructor in a context where it absolutely must be evaluated as a literal, e.g.:
+
+constexpr date bad{2011, 2, 30};
+
+The attempt to throw an exception at compile time is a diagnosable error, and the compiler must report the error to you.
+
+This interpretation was confirmed with experts from Core in Bloomington.
+
+AlisdairM
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 3 sep, 23:13
+Il giorno 03/set/2011, alle ore 22:40, Alisdair Meredith <w..._at_[hidden]> ha scritto:
+
+> The tricky part is adding assertions to the 'unchecked' constructor in 'defensive' build modes.
+
+Yup. Please notice that the issue isn't related with constructors and tags. Even if you define a factory function like make_date_ymd you will encounter the same difficulty in having it both constexpr and asserting.
+
+My point is that any make_date function can be made into a tagged constructor and vice-versa. In the standard, make_ functions are used when type deduction can help omitting some template argument. We do not have that need here, so I find it difficult to prefer them to constructors. Just my opinion.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Robert Klarer
+====================================
+ Autres options 3 sep, 23:21
+
+On Sat, Sep 3, 2011 at 5:13 PM, Alberto Ganesh Barbati <gan..._at_[hidden]>
+
+> My point is that any make_date function can be made into a tagged
+> constructor and vice-versa. In the standard, make_ functions are used when
+> type deduction can help omitting some template argument. We do not have that
+> need here, so I find it difficult to prefer them to constructors. Just my
+> opinion.
+
+> Ganesh
+
+Daniel has pointed out that make_error_code and make_error_condition do not
+exist for type deduction reasons.
+
+====================================
+====================================
+
+
+
+bs
+====================================
+ Autres options 3 sep, 23:22
+
+On 9/3/2011 4:13 PM, Alberto Ganesh Barbati wrote:
+
+> In the standard, make_ functions are used when type deduction can help omitting some template argument. We do not have that need here, so I find it difficult to prefer them to constructors. Just my opinion.
+
+I agree. Where constructors can be used they should be.
+
+Robert Klarer
+====================================
+ Autres options 3 sep, 23:36
+
+On Sat, Sep 3, 2011 at 5:05 PM, Alisdair Meredith <w..._at_[hidden]>wrote:
+
+On the other hand, if you call a constexpr constructor in a context where it
+
+> absolutely must be evaluated as a literal, e.g.:
+
+> constexpr date bad{2011, 2, 30};
+
+> The attempt to throw an exception at compile time is a diagnosable error,
+> and the compiler must report the error to you.
+
+> This interpretation was confirmed with experts from Core in Bloomington.
+
+Thanks. I didn't know that. I just figured the compiler would just crash in
+such cases.
+
+My insistence on make_date was based on the assumption that you couldn't do
+checking in a literal constructor, so I wanted to separate out the checking
+part into a different layer.
+
+Sorry for wasting everyone's time on this list. If someone had volunteered
+to sponsor my attendance at the meetings this all could have been avoided.
+:-)
+
+Off-topic:
+
+Is someone working on a proposal to enhance static_assert so that it does
+something benign if the conditional expression is not constant? I can't see
+a safe way to use them in constexpr functions otherwise.
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 3 sep, 23:52
+On Sep 3, 2011, at 5:36 PM, Robert Klarer wrote:
+
+> Sorry for wasting everyone's time on this list. If someone had volunteered to sponsor my attendance at the meetings this all could have been avoided. :-)
+
+Wish I could. :-) Nevertheless, I haven't detected any wasted time here.
+
+Question, if I may:
+
+Setting aside (only temporarily) all the wonderful ways we might construct a date, let's assume for a moment said date d is constructed.
+
+Now what? What do we want to be able to do with date d?
+
+I ask now because I'm leery of designing the "perfect" constructor without ever considering any of the use cases for date. I think it would be a good idea to not design /any/ aspect of date in complete isolation from all other aspects. A little iteration among the several aspects of date would be a good thing.
+
+Howard
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 4 sep, 00:52
+On 4 September 2011 00:52, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+> Question, if I may:
+> Setting aside (only temporarily) all the wonderful ways we might construct a date, let's assume for a moment said date d is constructed.
+> Now what? What do we want to be able to do with date d?
+> I ask now because I'm leery of designing the "perfect" constructor without ever considering any of the use cases for date. I think it would be a good idea to not design /any/ aspect of date in complete isolation from all other aspects. A little iteration among the several aspects of date would be a good thing.
+
+Well, I expect to be able to less-than (and/or equal) compare dates
+and add (or subtract) days to (from) a date object.
+I have stumbled upon two very important use cases where an easy-to-use
+date facility would be useful:
+
+1) is date(today) greater or equal than a date(launch_missiles)
+2) is date(today) greater or equal than a date(base_date +
+launch_missiles_offset)
+(the offset is n days)
+
+These use cases aren't theoretical, although you may replace
+"launch_missiles" with "delete stuff
+from database". And I've seen what the mistakes, or not having an easy
+way to do those operations,
+cost - they cost reports like "your data is now in a better place,
+don't be sad". :)
+
+I'm hesitant to talk about calendar-ish operations(*), I don't know
+whether those are closely related to
+date or whether they should be something kept separate or built on top
+of a date. Any clues are
+welcome.
+
+(*) "From a starting date, give me every weekday for a timespan of 6
+months", or "every sunday for
+12 weeks" and such. There's a whole host of dvr-ish stuff that could
+use such facilities for
+scheduled recordings...
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 4 sep, 01:49
+On Sep 3, 2011, at 6:52 PM, Ville Voutilainen wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+My opinion: We should target gregorian and only gregorian. As soon as we add constructors in terms of gregorian year, month and day, we are putting ourselves firmly in the gregorian calendar territory. That means we have to answer questions like what does it mean to add a month or year, and what is the day of the week. And how many days are there in a month? In a year?
+
+Being able to easily specify, recognize and test against common holidays (including weekends) is important in many applications (many businesses don't function on holidays and must account for that). Exception: I'm happy to ignore the specification of Easter and other holidays that require extraordinary effort and/or special casing.
+
+Where and how we answer those questions is a good debate. But I don't think I could vote for a proposal that simply ignores these questions.
+
+> (*) "From a starting date, give me every weekday for a timespan of 6
+> months", or "every sunday for
+> 12 weeks" and such. There's a whole host of dvr-ish stuff that could
+> use such facilities for
+> scheduled recordings...
+
+So, starting to prototype:
+
+namespace std { namespace chrono { // Uncontroversial?
+
+typedef duration<int_least32_t, ratio<86400>> days; // Uncontroversial?
+
+class date
+{
+ // unspecified data
+ // ...
+public:
+ date() noexcept; // as fast as possible?
+ // other constructors
+ // ...
+ date(const date&) noexcept = default;
+ date& operator=(const date&) noexcept = default;
+ ~date() noexcept = default;
+
+ // observers?
+
+ // day oriented arithmetic
+ date& operator+=(days d);
+ date& operator-=(days d);
+ friend date operator+(date x, days y);
+ friend date operator+(days x, date y);
+ friend date operator-(date x, days y);
+ friend days operator-(date x, date y);
+
+ // increment / decrement?
+ date& operator++(); // or should this be named tomorrow?
+ date operator++(int);
+ date& operator--(); // or should this be named yesterday?
+ date operator--(int);
+
+ // comparisons
+ friend bool operator==(const date& x, const date& y);
+ friend bool operator!=(const date& x, const date& y);
+ friend bool operator< (const date& x, const date& y);
+ friend bool operator> (const date& x, const date& y);
+ friend bool operator<=(const date& x, const date& y);
+ friend bool operator>=(const date& x, const date& y);
+
+};
+}} // namespace end
+
+I'm trying to hit the least controversial points here. Where have I over-stepped? And what can I add without controversy? Observers? I/O? Factory function for today? Conversions to/from std::chrono::system_clock::time_point?
+
+I've neglected to add constexpr, partly out of ignorance, mostly out of inability to test, and also wanting to be cautious about prematurely outlawing specific implementations without discussion.
+
+Howard
+
+====================================
+====================================
+
+
+
+Ville Voutilainen
+====================================
+ Autres options 4 sep, 02:57
+On 4 September 2011 02:49, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+> I'm trying to hit the least controversial points here. Where have I over-stepped? And what can I add without controversy? Observers? I/O? Factory function for today? Conversions to/from std::chrono::system_clock::time_point?
+
+I expect observers to be, while not necessarily quite controversial,
+something that will sparkle a lively discussion. :)
+
+Perhaps discussing i/o will have to wait until there's some clarity on
+observers? I do expect there to be some
+observers, but what kind of observers exactly, I don't know yet. Off
+the top of my hat I'd foolishly expect that
+while we need to construct from raw ints, it's less necessary to be
+able to observe raw int values.
+
+I would think that making it easy to create a date for today is
+fundamentally important.
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 4 sep, 10:22
+Il giorno 04/set/2011, alle ore 01:49, Howard Hinnant <howard.hinn..._at_[hidden]> ha scritto:
+
+> My opinion: We should target gregorian and only gregorian. As soon as we add constructors in terms of gregorian year, month and day, we are putting ourselves firmly in the gregorian calendar territory.
+
+In the design that I proposed in a previous post, the gregorian::date class is devoted to gregorian. However the design accommodates for other calendar classes in different namespaces (for example chinese::date). The post also showed how to realize a calendar_cast function to convert between calendars.
+
+That said, I'm ok with focusing on gregorian as long as we describe a path for future extensions.
+
+> Being able to easily specify, recognize and test against common holidays (including weekends) is important in many applications (many businesses don't function on holidays and must account for that). Exception: I'm happy to ignore the specification of Easter and other holidays that require extraordinary effort and/or special casing.
+
+Special holidays enter the realm of localization. I believe the user might simply check against a suitably created std::map. We don't need to support that.
+
+> So, starting to prototype:
+
+> namespace std { namespace chrono { // Uncontroversial?
+
+That might be good for general utilities and cross-calendar facilities. Gregorian date-specific classes should go in a nested namespace, we could make it an inline namespace though.
+
+> typedef duration<int_least32_t, ratio<86400>> days; // Uncontroversial?
+
+I have to think about that. What are the pros and cons against having a specific class which could have an implicit conversion to duration<>?
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 4 sep, 18:14
+On Sep 4, 2011, at 4:22 AM, Alberto Ganesh Barbati wrote:
+
+> Il giorno 04/set/2011, alle ore 01:49, Howard Hinnant <howard.hinn..._at_[hidden]> ha scritto:
+
+>> My opinion: We should target gregorian and only gregorian. As soon as we add constructors in terms of gregorian year, month and day, we are putting ourselves firmly in the gregorian calendar territory.
+
+> In the design that I proposed in a previous post, the gregorian::date class is devoted to gregorian. However the design accommodates for other calendar classes in different namespaces (for example chinese::date). The post also showed how to realize a calendar_cast function to convert between calendars.
+
+I already dislike the length of the namespace std::chrono. But I was overridden on that one. I'd really like to not further lengthen it. As it is, *every* time I'm using chrono facilities I find myself writing typedefs just for the purpose of short cuts:
+
+int main()
+{
+ typedef std::chrono::high_resolution_clock Clock;
+ typedef std::chrono::duration<double> sec;
+ Clock::time_point t0 = Clock::now();
+ // time stuff...
+ Clock::time_point t1 = Clock::now();
+ std::cout << sec(t1-t0).count() << " seconds\n";
+
+}
+
+> That said, I'm ok with focusing on gregorian as long as we describe a path for future extensions.
+
+Have you considered the path described in http://home.roadrunner.com/~hinnant/bloomington/date.html "Interoperability with other calendar systems"?
+
+>> Being able to easily specify, recognize and test against common holidays (including weekends) is important in many applications (many businesses don't function on holidays and must account for that). Exception: I'm happy to ignore the specification of Easter and other holidays that require extraordinary effort and/or special casing.
+
+> Special holidays enter the realm of localization. I believe the user might simply check against a suitably created std::map. We don't need to support that.
+
+I don't think I was clear on this one. I don't propose that we enumerate holidays. I propose that we provide the ability to easily compute them. E.g. we have already shown that we want to be able to enter dates corresponding to a gregorian year, month and day. This is sufficient to compute holidays such as New Years and Christmas. I also propose that we provide facilities to specify (for example) the first Monday in September for year y so that one can easily compute Labor Day in the US. I do not propose that we create a list of holidays that includes New Years, Christmas, or the US Labor day.
+
+Being able to specify the 1st, 2nd, 3rd, 4th or last weekday of a month for a given year is sufficient to specify all official US holidays. I'm not proposing anything more than that. If someone else points out another relatively simple computation that would also be of general use (e.g. the Monday on or before Jan 4 is the start of the ISO week-based year), I'm open to that. Computing nearest weekday from a date is generally useful. But I do not think we should get into computing phases of the moon, an equinox or solstice.
+
+>> So, starting to prototype:
+
+>> namespace std { namespace chrono { // Uncontroversial?
+
+> That might be good for general utilities and cross-calendar facilities. Gregorian date-specific classes should go in a nested namespace, we could make it an inline namespace though.
+
+>> typedef duration<int_least32_t, ratio<86400>> days; // Uncontroversial?
+
+> I have to think about that. What are the pros and cons against having a specific class which could have an implicit conversion to duration<>?
+
+Pros:
+
+days (as specified above) would be implicitly convertible to our other std::chrono::durations: hours, minutes, seconds, milliseconds, etc. But the conversion in the opposite direction (to days) could only be done via duration_cast. Such conversions might make multi-day countdowns to a specific event more convenient to code: Only 100 hours and 40 minutes until Product X goes on sale!
+
+The concept of days /is/ a duration. day, abbreviated d, with a definition of 86400 SI seconds is a unit that is accepted for use with the International System of Units (http://www.bipm.org/en/si/si_brochure/chapter4/table6.html).
+
+Cons:
+
+Its use will bring leap-second enthusiasts out. They will be quick to point out that we've made a mistake. There's this new fangled thing we've obviously never heard of called leap seconds and thus a day can not possibly be defined as 86400 seconds. My response: If you care about leap seconds then std::chrono::date and std::chrono::days are only basic building blocks for the tools you're looking for. You'll have to include (and update) your own table of leap second insertions. No OS I'm aware of even acknowledges the existence of leap seconds for their std::chrono::system_clock (http://en.wikipedia.org/wiki/Unix_time) (http://support.microsoft.com/kb/909614). These are not the droids you're looking for. Move along.
+
+Also note: http://en.wikipedia.org/wiki/Leap_second#Proposal_to_abolish_leap_sec...
+
+Alternatives:
+
+This operator has to return something:
+
+ auto operator-(date x, date y) -> ?;
+
+The choices I can imagine are:
+
+1. int_least32_t
+2. duration<int_least32_t, ratio<86400>>
+3. A class that has no interoperability with std::chrono::duration.
+
+Now imagine you've written some duration utility such as round() or display_as_broken_down_time(). Here's round:
+
+// round to nearest, to even on tie
+
+template <class To, class Rep, class Period>
+To
+round(const std::chrono::duration<Rep, Period>& d)
+{
+ To t0 = std::chrono::duration_cast<To>(d);
+ To t1 = t0;
+ ++t1;
+ auto diff0 = d - t0;
+ auto diff1 = t1 - d;
+ if (diff0 == diff1)
+ {
+ if (t0.count() & 1)
+ return t1;
+ return t0;
+ }
+ else if (diff0 < diff1)
+ return t0;
+ return t1;
+
+}
+
+One can easily imagine wanting to write code like:
+
+ hours h = round<hours>(d2-d1);
+
+and:
+
+ d1 += round<days>(h);
+
+If we choose 1, this would look more like:
+
+ hours h = round<hours>(duration<int_least32_t, ratio<86400>>(d2-d1));
+
+and:
+
+ d1 += round<duration<int_least32_t, ratio<86400>>(h).count();
+
+If we choose 3, this would look more like:
+
+ hours h = round<hours>(duration<int_least32_t, ratio<86400>>((d2-d1).count()));
+
+and:
+
+ d1 += days(round<duration<int_least32_t, ratio<86400>>(h).count());
+
+Or one could just write the conversion arithmetic between days and std::chrono::hours manually, not using your carefully written and debugged chrono utility functions such as round and display_as_broken_down_time. Of course you'll probably need to convert to minutes, seconds, maybe milliseconds too.
+
+Howard
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 4 sep, 18:37
+On 4 September 2011 11:14, Howard Hinnant <howard.hinn..._at_[hidden]> wrote:
+
+> But I do not think we should get into computing phases of the moon, an equinox or solstice.
+
+I agree. Much of that can be calculated if you have a different
+calendar, such as lunar.
+
+> Pros:
+
+> days (as specified above) would be implicitly convertible to our other std::chrono::durations: hours, minutes, seconds, milliseconds, etc. But the conversion in the opposite direction (to days) could only be done via duration_cast. Such conversions might make multi-day countdowns to a specific event more convenient to code: Only 100 hours and 40 minutes until Product X goes on sale!
+
+> The concept of days /is/ a duration. day, abbreviated d, with a definition of 86400 SI seconds is a unit that is accepted for use with the International System of Units (http://www.bipm.org/en/si/si_brochure/chapter4/table6.html).
+
+> Cons:
+
+> Its use will bring leap-second enthusiasts out.
+
+Also dayliight savings time. Your "pro" breaks down in that case.
+Similar issues with converting between time zones.
+
+It's a bit weird to be designing a date class completely distinct from
+a time class, since many of the things we want to do with dates depend
+on the time of day as well as location.
+
+Canonical example: "I want to eat lunch at noon every weekday, so
+I'll block it off on my calendar" vs. "I want to schedule a
+teleconference every weekday at noon so I can catch up on what my
+colleagues around the world are doing." (Heck, neither is an
+"absolute" date; the first one is relative to wherever I happen to be,
+which the second is relative to my home location.)
+
+I'm not saying we shouldn't define day as 86400 seconds; it's just
+that there will be controversy no matter what we do.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 4 sep, 19:17
+On Sep 4, 2011, at 12:37 PM, Nevin Liber wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+You make a good point. Let's include std::chrono::system_clock::time_point in the conversation. This is a time_point already in the standard that on every platform I know tracks UTC to at least millisecond precision. This type is truly a date-time, but with an extremely limited interface. One can, using completely std::components, I/O it in terms of the gregorian calendar:
+
+#include <ctime>
+#include <chrono>
+#include <iostream>
+
+int main()
+{
+ typedef std::chrono::system_clock Clock;
+ auto tt = Clock::to_time_t(Clock::now());
+ std::cout << std::ctime(&tt) << '\n';
+
+}
+
+Sun Sep 4 13:12:07 2011
+
+Note that I had to make a conscious decision as to what time zone to perform the I/O. The C/C++ standards give me two choices: My local time zone, or UTC.
+
+On date: This object is nothing but a count of sunrises. Subtracting dates is going to return an integral number of rotations of the earth, no matter how we package it. I'm not currently seeing how any of:
+
+1. int_least32_t
+2. duration<int_least32_t, ratio<86400>>
+3. A class that has no interoperability with std::chrono::duration.
+
+impacts differently issues with time zones, leap seconds, or setting events down to the minute on a calendar.
+
+Howard
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 4 sep, 23:01
+On Sep 4, 2011, at 1:17 PM, Howard Hinnant wrote:
+
+> On date: This object is nothing but a count of sunrises. Subtracting dates is going to return an integral number of rotations of the earth, no matter how we package it. I'm not currently seeing how any of:
+
+> 1. int_least32_t
+> 2. duration<int_least32_t, ratio<86400>>
+> 3. A class that has no interoperability with std::chrono::duration.
+
+> impacts differently issues with time zones, leap seconds, or setting events down to the minute on a calendar.
+
+It occurred to me that some of you may not be familiar with std::chrono::duration. So here is a very brief description:
+
+In each of the 3 choices above, if one subtracts today from tomorrow, a 1 is stored as the return. Nothing more. sizeof(duration<int_least32_t, ratio<86400>>) == sizeof(int_least32_t). The only real difference between int_least32_t(1) and duration<int_least32_t, ratio<86400>>(1) is that the latter comes with preprogrammed conversions to our other duration types. Oh, and the latter is a distinct type with no implicit conversion to int_least32_t so that it can not be confused with other int_least32_t that do not represent a number of earth rotations. It does have an explicit conversion though using a count() member function, which does nothing but return the internally stored int_least32_t:
+
+int_least32_t d1(1);
+duration<int_least32_t, ratio<86400>> d2(1);
+assert(d1 == d2.count());
+
+int_least32_t ms1 = 86400000 * d1;
+milliseconds ms2 = d2;
+assert(ms1 == ms2.count());
+
+static_assert( std::is_same<decltype(d1),
+ decltype(ms1)>::value,
+ "d1 and ms1 should be the same type");
+static_assert(!std::is_same<decltype(d2),
+ decltype(ms2)>::value,
+ "d2 and ms2 should not be the same type");
+
+So the questions are:
+
+A. Do we want a distinct (non-int) type for the return of date subtraction?
+ Yes, choose 2 or 3.
+ No, choose 1.
+
+B. If we want a distinct type, do we want to provide conversions to our existing duration types?
+ Yes, choose 2.
+ No, choose 3.
+
+Howard
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 4 sep, 23:05
+All, I have the following questions/observations regarding Howard's proposed baseline 'date' class:
+
+1. It is not clear to me why we need to build any sort of duration into
+ the difference operator between two dates. The difference between to
+ date objects is integral: Unless we are using date objects in a different
+ context -- e.g., one in which involves local time zones and DST (or leap
+ seconds) -- for me, it's just the (signed) integer number of whole days
+ between the two dates. Bottom line: ++date is NOT necessarily 86,400
+ seconds later, it IS one day later.
+
+2. I would not have bothered to use 'int_least32_t' as the result type for a
+ primitive date-difference operation because nothing we write at Bloomberg
+ would work if 'int' were 16 bits. I suspect this is true for most people
+ who write C++, but I could live with 'int_least32_t' for the C++ standard
+ if that's what makes people feel confortable, but then I'd want to see
+ where else we use 'int' in the standard and clean that up too (if necessary).
+
+3. The difference between two 'date_time' types is a 'date_time_interval', but
+ not of any particular precision. Building the precision into the difference
+ type would be brittle and (IMO) a mistake. (Type-safe programming can
+ ensure that dimensions are correct at compile time. Dimensions are
+ distance, time, velocity, acceleration, etc., but not specific units like
+ meters, seconds, meters-per-second, etc.).
+
+4. With a 'date_time', there is again no notion of local timezone or leap
+ seconds; hence, these concepts should be addressed at a higher level.
+
+5. We (at Bloomberg) would need accessors of the 'date' type for the year,
+ month, and day fields that (somehow) return 'int' year, 'int' month, and
+ 'int' day.
+
+6. The prefixe ++ and -- operators on date are *no*t to be named 'tomorrow' or
+ 'yesterday', as they modify the object! Even calling them 'makeTomorrow'
+ (and 'makeYesterday') would be wrong, as the name would suggest that the
+ operation is independent of the current value. The prefix operators are
+ unambiguous and correct, especially given the contiguous integral nature of
+ date values.
+
+7. By the same token, date += 3 modifies this date to be 3 days after its
+ original value (unambiguous). int days = d2 - d1; assert (d2 == d1 + days);
+
+8. As a general matter, postfix operators should not be members. The only
+ use case for making the postfix operators members is to modify an unnamed
+ temporary object, which is certainly a bug (and it is also inconstant with
+ the behavior w.r.t. user-defined conversion for fundamental types). I
+ propose that we make the two postfix operators, free (but not friend)
+ operators, and implement them -- by definition ("as if") -- in terms of
+ their corresponding member prefix operators.
+
+ -John Lakos
+
+- Afficher le texte des messages prŽcŽdents -
+
+
+====================================
+====================================
+
+
+
+Howard Hinnant
+====================================
+ Autres options 5 sep, 02:33
+On Sep 4, 2011, at 5:05 PM, JOHN LAKOS, BLOOMBERG/ 731 LEXIN wrote:
+
+> All, I have the following questions/observations regarding Howard's proposed baseline 'date' class:
+
+> 1. It is not clear to me why we need to build any sort of duration into
+> the difference operator between two dates. The difference between to
+> date objects is integral: Unless we are using date objects in a different
+> context -- e.g., one in which involves local time zones and DST (or leap
+> seconds) -- for me, it's just the (signed) integer number of whole days
+> between the two dates. Bottom line: ++date is NOT necessarily 86,400
+> seconds later, it IS one day later.
+
+I can respect that view. However I wanted to add: if we were to choose duration<int_least32_t, ratio<86400>>, or class days{}, there is zero overhead. I can supply assembly examples demonstrating that if that would help (in case it makes a difference to anyone).
+
+> 2. I would not have bothered to use 'int_least32_t' as the result type for a
+> primitive date-difference operation because nothing we write at Bloomberg
+> would work if 'int' were 16 bits. I suspect this is true for most people
+> who write C++, but I could live with 'int_least32_t' for the C++ standard
+> if that's what makes people feel confortable, but then I'd want to see
+> where else we use 'int' in the standard and clean that up too (if necessary).
+
+I did a quick survey, and actually we've done fairly well over the years with respect to this issue in the standard. There may be a couple of places where int isn't quite the right type. But I believe them to be relatively rare. I believe we can not assume at this point that int is greater than 16 bits (our standard says otherwise).
+
+> 3. The difference between two 'date_time' types is a 'date_time_interval', but
+> not of any particular precision. Building the precision into the difference
+> type would be brittle and (IMO) a mistake. (Type-safe programming can
+> ensure that dimensions are correct at compile time. Dimensions are
+> distance, time, velocity, acceleration, etc., but not specific units like
+> meters, seconds, meters-per-second, etc.).
+
+Informational:
+
+The difference between two std::chrono::system_clock::time_point has type std::chrono::system_clock::duration. The precision of this duration type is unspecified but inspectable at compile time (and thus self-documenting). The implicit precision conversion logic among the duration types ensures that you can convert std::chrono::system_clock::duration to a known duration of your choosing, and either it will compile and there will be no truncation error, or it will fail to compile.
+
+For example assume that std::chrono::system_clock::duration is a synonym for std::chrono::milliseconds and internally represented with a long long (as I suspect it is (or will be) in VC++). Then the following code will compile, and the arithmetic will be exact:
+
+using namespace std::chrono;
+system_clock::time_point t0 = system_clock::now();
+// do stuff
+system_clock::time_point t1 = system_clock::now();
+microseconds us = t1 - t0; // exact & implicit conversion from milliseconds to microseconds represented with signed integral type
+duration<double> dsec = t1 - t0; // implicit conversion from milliseconds to seconds represented with double
+ // the above conversion is subject to round-off error, but not truncation error
+
+However the following will not compile:
+
+seconds isec = t1 - t0; // compile time error.
+ // seconds is an integral duration and the conversion from milliseconds is subject to truncation error
+
+The conversions among duration types have exactly the same efficiency as hand-coded conversions, even when the conversion is identity:
+
+milliseconds ms = t1 -t0; // nothing but a long long subtraction and assignment
+
+Emphasis: The above will generate the exact same assembly as:
+
+ long long t0 = ...
+ long long t1 = ...
+ long long ms = t1 - t0;
+
+and:
+
+ microseconds us = t1 - t0;
+
+generates the same assembly as:
+
+ long long t0 = ...
+ long long t1 = ...
+ long long us = (t1 - t0) * 1000;
+
+> 4. With a 'date_time', there is again no notion of local timezone or leap
+> seconds; hence, these concepts should be addressed at a higher level.
+
+Agreed. And I think this is consistent with std::chrono::system_clock::time_point.
+
+> 5. We (at Bloomberg) would need accessors of the 'date' type for the year,
+> month, and day fields that (somehow) return 'int' year, 'int' month, and
+> 'int' day.
+
+and weekday? [Sun - Sat] == [0 - 6]?
+
+> 6. The prefixe ++ and -- operators on date are *no*t to be named 'tomorrow' or
+> 'yesterday', as they modify the object! Even calling them 'makeTomorrow'
+> (and 'makeYesterday') would be wrong, as the name would suggest that the
+> operation is independent of the current value. The prefix operators are
+> unambiguous and correct, especially given the contiguous integral nature of
+> date values.
+
+Thank you! I'm glad somebody was awake! :-)
+
+I envision "date day iteration" to be popular and coded similar to:
+
+ date start_date = ...
+ date end_date = ...
+ for(; start_date <= end_date; ++start_date)
+ // do stuff with start_date
+
+For C++ programmers this is a lot more readable than something like:
+
+ for(; start_date <= end_date; start_date.tomorrow())
+ // do stuff with start_date
+
+> 7. By the same token, date += 3 modifies this date to be 3 days after its
+> original value (unambiguous). int days = d2 - d1; assert (d2 == d1 + days);
+
+I agree in spirit, especially with the algebraic consistency. I do worry about:
+
+ int get_time_since();
+ ...
+ date += get_time_since();
+
+One has to read the docs to find out what units get_time_since() is returning. The compiler won't catch the error if the units aren't days.
+
+> 8. As a general matter, postfix operators should not be members. The only
+> use case for making the postfix operators members is to modify an unnamed
+> temporary object, which is certainly a bug (and it is also inconstant with
+> the behavior w.r.t. user-defined conversion for fundamental types). I
+> propose that we make the two postfix operators, free (but not friend)
+> operators, and implement them -- by definition ("as if") -- in terms of
+> their corresponding member prefix operators.
+
+I like this suggestion! Too bad the rest of the standard is patterned after this. Use of "rvalue-this" would be another way to get the same effect:
+
+struct A
+{
+ A operator++(int)&;
+
+};
+
+Howard
+
+- Afficher le texte des messages prŽcŽdents -
+
+...
+
+plus de dŽtails È
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 5 sep, 09:41
+
+Il giorno 05/set/2011, alle ore 02:33, Howard Hinnant ha scritto:
+
+> On Sep 4, 2011, at 5:05 PM, JOHN LAKOS, BLOOMBERG/ 731 LEXIN wrote:
+
+>> All, I have the following questions/observations regarding Howard's proposed baseline 'date' class:
+
+>> 1. It is not clear to me why we need to build any sort of duration into
+>> the difference operator between two dates. The difference between to
+>> date objects is integral: Unless we are using date objects in a different
+>> context -- e.g., one in which involves local time zones and DST (or leap
+>> seconds) -- for me, it's just the (signed) integer number of whole days
+>> between the two dates. Bottom line: ++date is NOT necessarily 86,400
+>> seconds later, it IS one day later.
+
+> I can respect that view. However I wanted to add: if we were to choose duration<int_least32_t, ratio<86400>>, or class days{}, there is zero overhead. I can supply assembly examples demonstrating that if that would help (in case it makes a difference to anyone).
+
+Howard's argument sounds convincing to me. The link Howard provided clearly shows that at least one international standard defines day as 86400 seconds. The *only* reason I see to not adopt duration<int_least32_t, ratio<86400>> for days is if we wanted to support leap seconds at the basic level. However, I see some agreement that we should consider leap seconds at that level.
+
+>> 2. I would not have bothered to use 'int_least32_t' as the result type for a
+>> primitive date-difference operation because nothing we write at Bloomberg
+>> would work if 'int' were 16 bits. I suspect this is true for most people
+>> who write C++, but I could live with 'int_least32_t' for the C++ standard
+>> if that's what makes people feel confortable, but then I'd want to see
+>> where else we use 'int' in the standard and clean that up too (if necessary).
+
+> I did a quick survey, and actually we've done fairly well over the years with respect to this issue in the standard. There may be a couple of places where int isn't quite the right type. But I believe them to be relatively rare. I believe we can not assume at this point that int is greater than 16 bits (our standard says otherwise).
+
+I have no problems with int_least32_t. It's probably going to be defined to be int on most platforms, anyway.
+
+The only place in the library where int is used and really shouldn't is in the specification of gbump/pbump. I believe there is already a DR about it.
+
+>> 3. The difference between two 'date_time' types is a 'date_time_interval', but
+>> not of any particular precision. Building the precision into the difference
+>> type would be brittle and (IMO) a mistake. (Type-safe programming can
+>> ensure that dimensions are correct at compile time. Dimensions are
+>> distance, time, velocity, acceleration, etc., but not specific units like
+>> meters, seconds, meters-per-second, etc.).
+
+In my proposal, the date_time class is a templated wrapper over date and a duration. So you can have:
+
+basic_date_time<date, milliseconds> d1; // time-of-day measured in milliseconds
+basic_date_time<date, microseconds> d2; // time-of-day measured in microseconds
+date_time d3; // an alias representing a reasonable default (seconds? milliseconds? we decide)
+
+(the first argument of basic_date_date takes a date to accommodate for different calendars)
+
+The time_duration arithmetic takes care of all the conversions as described by Howard.
+
+>> 4. With a 'date_time', there is again no notion of local timezone or leap
+>> seconds; hence, these concepts should be addressed at a higher level.
+
+> Agreed. And I think this is consistent with std::chrono::system_clock::time_point.
+
+Agreed.
+
+>> 6. The prefixe ++ and -- operators on date are *no*t to be named 'tomorrow' or
+>> 'yesterday', as they modify the object! Even calling them 'makeTomorrow'
+>> (and 'makeYesterday') would be wrong, as the name would suggest that the
+>> operation is independent of the current value. The prefix operators are
+>> unambiguous and correct, especially given the contiguous integral nature of
+>> date values.
+
+> Thank you! I'm glad somebody was awake! :-)
+
+I don't like ++ and -- very much. I'd prefer if we forced the user to a more explicit:
+
+ d += days(1);
+
+> I envision "date day iteration" to be popular and coded similar to:
+
+> date start_date = ...
+> date end_date = ...
+> for(; start_date <= end_date; ++start_date)
+> // do stuff with start_date
+
+> For C++ programmers this is a lot more readable than something like:
+
+> for(; start_date <= end_date; start_date.tomorrow())
+> // do stuff with start_date
+
+I believe we should investigate the possibility of having syntaxes like:
+
+ for (date d : date_range(start_date, end_date))
+ // ...
+
+or even
+
+ for (date d : day_iteration(start_date, end_date))
+ // ...
+
+ for (date d : month_iteration(start_date, end_date))
+ // ...
+
+or something like that. We could create a whole sort of date range traversals algorithms without having to overload a single iterator class, while having them totally decoupled from the date class. Such algorithms could also be used with regular algorithms, of course:
+
+ week_iteration wi(start_date, end_date);
+ for_each(wi.begin(), wi.end(), ...)
+
+>> 7. By the same token, date += 3 modifies this date to be 3 days after its
+>> original value (unambiguous). int days = d2 - d1; assert (d2 == d1 + days);
+
+> I agree in spirit, especially with the algebraic consistency. I do worry about:
+
+> int get_time_since();
+> ...
+> date += get_time_since();
+
+> One has to read the docs to find out what units get_time_since() is returning. The compiler won't catch the error if the units aren't days.
+
+I totally agree with Howard. The difference between two dates should be typed and type "days" shouldn't be implicitly convertible to integers. Accordingly, you should also be disallowed to add integers to a date.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Alberto Ganesh Barbati
+====================================
+ Autres options 5 sep, 12:34
+
+Il giorno 03/set/2011, alle ore 23:21, Robert Klarer <robert.kla..._at_[hidden]> ha scritto:
+
+> On Sat, Sep 3, 2011 at 5:13 PM, Alberto Ganesh Barbati <gan..._at_[hidden]>
+
+> My point is that any make_date function can be made into a tagged constructor and vice-versa. In the standard, make_ functions are used when type deduction can help omitting some template argument. We do not have that need here, so I find it difficult to prefer them to constructors. Just my opinion.
+
+> Daniel has pointed out that make_error_code and make_error_condition do not exist for type deduction reasons.
+
+make_error_code and make_error_condition are customizable extension points. They are not expected to be used directly by the user, although it would be no harm to do it. For example, I can write
+
+ std::io_errc ioerr = ...;
+
+ std::error_code ec(ioerr); // eventually calls make_error_code(ioerr);
+
+I don't need (and I am not expected) to write:
+
+ std::error_code ec = make_error_code(ioerr);
+
+As you can see, the motivation and the design pattern (which includes the specialization of the is_error_code_enum trait class) is totally different what we would have with date.
+
+Ganesh
+
+====================================
+====================================
+
+
+
+Nevin Liber
+====================================
+ Autres options 5 sep, 20:34
+On 5 September 2011 02:41, Alberto Ganesh Barbati <gan..._at_[hidden]> wrote:
+
+> I totally agree with Howard. The difference between two dates should be typed and type "days" shouldn't be implicitly convertible to integers. Accordingly, you should also be disallowed to add integers to a date.
+
++1. Durations may be integral, but they are certainly not scalars,
+and the type system should reflect that. Types are for more than just
+enforcing invariants.
+
+Heck, dates fundamentally are some number of integral days away from
+some epoch, but we are arguing to make them a type instead of a just a
+couple of conversion functions.
+--
+ Nevin ":-)" Liber <mailto:ne..._at_[hidden]> (847) 691-1404
+
+====================================
+====================================
+
+
+
+JOHN LAKOS, BLOOMBERG/ 731 LEXIN
+====================================
+ Autres options 5 sep, 20:17
+JSL: Responding Ganesh Responding to Howard Responding to me -- My comments JSL: look like this...
+
+- Masquer le texte des messages prŽcŽdents -
+
+----- Original Message -----
+From: kona-date-lib_at_[hidden]
+To: kona-date-lib_at_[hidden]
+
+At: 9/05 3:41:13
+
+Il giorno 05/set/2011, alle ore 02:33, Howard Hinnant ha scritto:
+
+> On Sep 4, 2011, at 5:05 PM, JOHN LAKOS, BLOOMBERG/ 731 LEXIN wrote:
+
+>> All, I have the following questions/observations regarding Howard's proposed baseline 'date' class:
+
+>> 1. It is not clear to me why we need to build any sort of duration into
+>> the difference operator between two dates. The difference between to
+>> date objects is integral: Unless we are using date objects in a different
+>> context -- e.g., one in which involves local time zones and DST (or leap
+>> seconds) -- for me, it's just the (signed) integer number of whole days
+>> between the two dates. Bottom line: ++date is NOT necessarily 86,400
+>> seconds later, it IS one day later.
+
+> I can respect that view. However I wanted to add: if we were to choose duration<int_least32_t, ratio<86400>>, or class days{}, there is zero overhead. I can supply assembly examples demonstrating that if that would help (in case it makes a difference to anyone).
+
+Howard's argument sounds convincing to me. The link Howard provided clearly shows that at least one international standard defines day as 86400 seconds. The *only* reason I see to not adopt duration<int_least32_t, ratio<86400>> for days is if we wanted to support leap seconds at the basic level. However, I see some agreement that we should consider leap seconds at that level.
+
+JSL: In this case, it is not an issue of overhead. It is the semantics.
+JSL: I agree with the difference between two date_time values being a
+JSL: date_time_interval (of unspecified precision) because there is no one
+JSL: base precision for time. But there is for days. So I don't see the
+JSL: need to have anything to do with time in just the date type. date_time
+JSL: is different. Separately, I do not think we should be dealing with
+JSL: leap seconds in the basic time or date_time class (at the primitive level):
+JSL: These are subtle issues that most people (including Bloomberg) don't care
+JSL: about at all, and are handled differently by different people who do
+JSL: care. For example, some operating systems gradually adjust their clocks
+JSL: over the entire year and side-step the issue entirely.
+
+>> 2. I would not have bothered to use 'int_least32_t' as the result type for a
+>> primitive date-difference operation because nothing we write at Bloomberg
+>> would work if 'int' were 16 bits. I suspect this is true for most people
+>> who write C++, but I could live with 'int_least32_t' for the C++ standard
+>> if that's what makes people feel confortable, but then I'd want to see
+>> where else we use 'int' in the standard and clean that up too (if necessary).
+
+> I did a quick survey, and actually we've done fairly well over the years with respect to this issue in the standard. There may be a couple of places where int isn't quite the right type. But I believe them to be relatively rare. I believe we can not assume at this point that int is greater than 16 bits (our standard says otherwise).
+
+I have no problems with int_least32_t. It's probably going to be defined to be int on most platforms, anyway.
+
+The only place in the library where int is used and really shouldn't is in the specification of gbump/pbump. I believe there is already a DR about it.
+
+JSL: OK: As long as we're consistent about it in the standard.
+
+>> 3. The difference between two 'date_time' types is a 'date_time_interval', but
+>> not of any particular precision. Building the precision into the difference
+>> type would be brittle and (IMO) a mistake. (Type-safe programming can
+>> ensure that dimensions are correct at compile time. Dimensions are
+>> distance, time, velocity, acceleration, etc., but not specific units like
+>> meters, seconds, meters-per-second, etc.).
+
+In my proposal, the date_time class is a templated wrapper over date and a duration. So you can have:
+
+JSL: I will need more convincing that duration is the right answer for
+JSL: date_time values. duration may be what we use to implement them (which is,
+JSL: in part, I voted for them) but they may not be the vocabulary type we need
+JSL: for date, time, date_time, and date_time_interval (no compile-time units).
+JSL: The goal is to be able to pass the value of the a date_time ubiquitously
+JSL: without making the client a template; this property is critical for
+JSL: Bloomberg (and IMO in general for large systems).
+
+basic_date_time<date, milliseconds> d1; // time-of-day measured in milliseconds
+basic_date_time<date, microseconds> d2; // time-of-day measured in microseconds
+date_time d3; // an alias representing a reasonable default (seconds? milliseconds? we decide)
+
+(the first argument of basic_date_date takes a date to accommodate for different calendars)
+
+The time_duration arithmetic takes care of all the conversions as described by Howard.
+
+>> 4. With a 'date_time', there is again no notion of local timezone or leap
+>> seconds; hence, these concepts should be addressed at a higher level.
+
+> Agreed. And I think this is consistent with std::chrono::system_clock::time_point.
+
+Agreed.
+
+JSL: Cool :-)
+
+>> 6. The prefixe ++ and -- operators on date are *no*t to be named 'tomorrow' or
+>> 'yesterday', as they modify the object! Even calling them 'makeTomorrow'
+>> (and 'makeYesterday') would be wrong, as the name would suggest that the
+>> operation is independent of the current value. The prefix operators are
+>> unambiguous and correct, especially given the contiguous integral nature of
+>> date values.
+
+> Thank you! I'm glad somebody was awake! :-)
+
+I don't like ++ and -- very much. I'd prefer if we forced the user to a more explicit:
+
+ d += days(1);
+
+JSL: You can use += if you want, but let's not stop people from using terse, JSL: familiar, and intuitive notation that cannot reasonably be misunderstood.
+
+> I envision "date day iteration" to be popular and coded similar to:
+
+> date start_date = ...
+> date end_date = ...
+> for(; start_date <= end_date; ++start_date)
+> // do stuff with start_date
+
+> For C++ programmers this is a lot more readable than something like:
+
+> for(; start_date <= end_date; start_date.tomorrow())
+> // do stuff with start_date
+
+I believe we should investigate the possibility of having syntaxes like:
+
+ for (date d : date_range(start_date, end_date))
+ // ...
+
+or even
+
+ for (date d : day_iteration(start_date, end_date))
+ // ...
+
+ for (date d : month_iteration(start_date, end_date))
+ // ...
+
+or something like that. We could create a whole sort of date range traversals algorithms without having to overload a single iterator class, while having them totally decoupled from the date class. Such algorithms could also be used with regular algorithms, of course:
+
+ week_iteration wi(start_date, end_date);
+ for_each(wi.begin(), wi.end(), ...)
+
+JSL: This is all more complicated than is needed. I am not going to say
+JSL: I am opposed, but pre and post fix operator ++ and -- belong here first.
+
+>> 7. By the same token, date += 3 modifies this date to be 3 days after its
+>> original value (unambiguous). int days = d2 - d1; assert (d2 == d1 + days);
+
+> I agree in spirit, especially with the algebraic consistency. I do worry about:
+
+> int get_time_since();
+> ...
+> date += get_time_since();
+
+> One has to read the docs to find out what units get_time_since() is returning. The compiler won't catch the error if the units aren't days.
+
+JSL: We need to make the code easy and safe to write, but reading the docs
+JSL: is not something we can eliminate (nor IMO should we try). Notice
+JSL: the function has "time" in it. If it said get_whole_days_since ..., it
+JSL: would satisfy my safety threshold -- that is, unless it returned whole
+JSL: multiples of 86,400 as an int ;-)
+
+I totally agree with Howard. The difference between two dates should be typed and type "days" shouldn't be implicitly convertible to integers. Accordingly, you should also be disallowed to add integers to a date.
+
+JSL: I think we have *true* *disagreement* here:
+JSL: IMO d1 - d2 is integral --> 'int' (or some kind of signed integer type)
+JSL: We agree that assert(d2 == d1 + (d2 - d1)).
+JSL: IMO int n = d2 - d1; should work fine.
+JSL: as should date d2 = d1 + 2;
+JSL: and then assert(2 == d2 - d1);
+JSL: I don't necessarily mind if people don't want to use this, but
+JSL: making people who fully qualify all types (i.e., don't use using) to type
+JSL: d2 = d1 + std::chrono::days(2);
+JSL: instead
+JSL: d2 = d1 + 2;
+JSL: will revolt.
+JSL:
+JSL: Again, dimensions are one thing, but integers are integers and this kind
+JSL: excessive over typing gets in the way of interoperability. You are, of
+JSL: course, not going to stop people from getting the number of days out of a
+JSL: std::chrono::days, which means that you constantly make people who want
+JSL: the 'int' to say something like 'n.asInteger()' instead of just 'n'!
+JSL: You may like this, but people who are used to writing terse code may well
+JSL: think this is nuts, and refuse to use it. Again, dates and date_times
+JSL: are different, used differently, and have different properties. I would
+JSL: never suggest that the difference between two datetime values is integeral.
+JSL: it is a date_time_interval (with unspecified precision) and you ask it
+JSL: for the units you want, which is totally correct and fine by me. But
+JSL: dates are integral in nature, and ++ += + - etc. are all intuitive and
+JSL: unambiguous (at least to the 1000s of programmers that have used our
+JSL:
+
+...
+
+plus de dŽtails È
+
+====================================
+====================================
+
+
+
+Sujet remplacŽ par "Difference between two dates" par Pablo Halpern
+
+
+
+Pablo Halpern
+====================================
+ Autres options 7 sep, 01:16
+
+On 09/05/2011 02:17 PM, JOHN LAKOS, BLOOMBERG/ 731 LEXIN wrote:
+
+- Afficher le texte des messages prŽcŽdents -
+
+I agree and would add an even more fundamental problem than precision.
+The notion of a "date" is fundamentally different than the notion of a
+timepoint. If that were not true, then there would be no need to have
+two separate types. The meaning of a date is context-dependent and is
+not necessarily 86400 seconds. For example, a work day might be 8
+hours. A business day might be something else. A birthday is the whole
+day, not a specific time (midnight or noon). If we impose the notion
+that the difference between two dates is convertible implicitly to a
+time duration, then we are inviting the programmer to make some very
+common errors while giving them a false sense that the the compiler will
+prevent these errors.
+
+For example, a ski area may have lifts that open at 9 and close at 4.
+If the user buys multi-day ski passes online and puts in firstday and
+lastday, how many hours of skiing did the user buy? Wrong answer:
+(lastday - firstday + 1) * 24 hours. If I have heated ski boots that
+last 12-hours on a charge, how many days can I ski without recharging
+the batteries? Wrong answer: less than 1 day. Here is a link to a joke
+that hinges on exactly these kinds of errors:
+http://www.funnyandjokes.com/so-you-want-a-day-off.html.
+<http://www.funnyandjokes.com/so-you-want-a-day-off.html>
+
+So, whatever gets returned from date subtraction, it should not be
+something that is convertible to seconds. So, of Howard's three
+proposed return values, I'm against #2: duration<int_least32_t,
+ratio<86400> >.
+> Ganesh Wrote:
+> I totally agree with Howard. The difference between two dates should be typed and type "days" shouldn't be implicitly convertible to integers. Accordingly, you should also be disallowed to add integers to a date.
+
+> JSL: I think we have *true* *disagreement* here:
+> JSL: IMO d1 - d2 is integral --> 'int' (or some kind of signed integer type)
+> JSL: We agree that assert(d2 == d1 + (d2 - d1)).
+> JSL: IMO int n = d2 - d1; should work fine.
+> JSL: as should date d2 = d1 + 2;
+> JSL: and then assert(2 == d2 - d1);
+> JSL: I don't necessarily mind if people don't want to use this, but
+> JSL: making people who fully qualify all types (i.e., don't use using) to type
+> JSL: d2 = d1 + std::chrono::days(2);
+> JSL: instead
+> JSL: d2 = d1 + 2;
+> JSL: will revolt.
+
+I have mixed feelings about this issue, i.e., whether the difference
+between dates should be a simple integer or a special type that is not a
+duration. I agree with John that most uses of integers with dates are
+safe and intuitive and I appreciate the terseness. However, I don't
+have much experience programming with dimensional types so I don't have
+a strong sense of the advantages. Dimensional types can have a nice
+benefit for I/O, as Howard showed in his time I/O proposal. I think it
+would be cool to be able to say:
+
+ std::cout << (a - b);
+
+and if a and b are dates, then the result has the word "days" after it.
+Would it be heresy to suggest a dimensional type like "days" that is
+implicitly convertible to and from integers. (Actually, calling
+x.count() is not too onerous, but std::chrono::days(y) is icky, IMO.)
+
+-Pablo
+
+====================================
+====================================
+
+
+
+Sujet remplacŽ par "Increment and decrement operators" par Pablo Halpern
+
+
+
+Pablo Halpern
+====================================
+ Autres options 7 sep, 01:20
+On 09/05/2011 02:17 PM, JOHN LAKOS, BLOOMBERG/ 731 LEXIN wrote:
+> JSL: Responding Ganesh Responding to Howard Responding to me -- My comments JSL: look like this...
+
+>>> 6. The prefixe ++ and -- operators on date are *no*t to be named 'tomorrow' or
+>>> 'yesterday', as they modify the object! Even calling them 'makeTomorrow'
+>>> (and 'makeYesterday') would be wrong, as the name would suggest that the
+>>> operation is independent of the current value. The prefix operators are
+>>> unambiguous and correct, especially given the contiguous integral nature of
+>>> date values.
+>> Thank you! I'm glad somebody was awake! :-)
+> I don't like ++ and -- very much. I'd prefer if we forced the user to a more explicit:
+
+> d += days(1);
+
+Ick! Come on. What possible meaning could ++d have than "increment d
+to the next day!" Especially if we decide that adding days to a date
+would require constructing a days object (which I'm not completely
+convinced of), then we need the terse ++ and -- operators for iterating
+through days.
+> JSL: You can use += if you want, but let's not stop people from using terse,
+> JSL: familiar, and intuitive notation that cannot reasonably be misunderstood.
+
+Agreed.
+
+-Pablo
+#endif

Added: sandbox/chrono_date/boost/chrono/date/tuples.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/tuples.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,444 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_TUPLES_HPP
+#define BOOST_CHRONO_DATE_DATE_TUPLES_HPP
+
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/day_of_year.hpp>
+#include <boost/chrono/date/week.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * Class year_month is a tuple-like class of year-month.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ */
+ class year_month
+ {
+ year y_;
+ month m_;
+ public:
+ year_month(year y, month m) BOOST_NOEXCEPT
+ : y_(y),
+ m_(m)
+ {
+ }
+ year_month(year::rep y, month::rep m, no_check_t) BOOST_NOEXCEPT
+ : y_(y, no_check),
+ m_(m, no_check)
+ {
+ }
+ /**
+ * @Return the year stored component.
+ */
+ year get_year() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+
+ /**
+ * @Return the month stored component.
+ */
+ month get_month() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+
+ /**
+ * @Return the number of days of this month in this year.
+ */
+ days days_in() const BOOST_NOEXCEPT
+ {
+ return y_.days_in(m_);
+ }
+ };
+
+ inline year_month operator/(year y, month m) BOOST_NOEXCEPT
+ {
+ return year_month(y, m);
+ }
+ inline year_month operator/(month m, year y) BOOST_NOEXCEPT
+ {
+ return year_month(y, m);
+ }
+
+ /**
+ * Class year_week is a tuple-like class of year-week.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ */
+ class year_week
+ {
+ year y_;
+ week w_;
+ public:
+ year_week(year y, week w) BOOST_NOEXCEPT
+ : y_(y),
+ w_(w)
+ {
+ }
+ year_week(year::rep y, week::rep w, no_check_t) BOOST_NOEXCEPT
+ : y_(y, no_check),
+ w_(w, no_check)
+ {
+ }
+
+ /**
+ * @Return the year stored component.
+ */
+ year get_year() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+ /**
+ * @Return the week stored component.
+ */
+ week get_week() const BOOST_NOEXCEPT
+ {
+ return w_;
+ }
+
+ };
+
+ inline year_week operator/(year y, week w) BOOST_NOEXCEPT
+ {
+ return year_week(y, w);
+ }
+
+ inline year_week operator/(week w, year y) BOOST_NOEXCEPT
+ {
+ return year_week(y, w);
+ }
+
+ /**
+ * Class month_day is a tuple-like class of month-day.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ *
+ * This class is useful while generating dates, allowing to generate dates
+ * that are quasi literals (e.g. jan_01/2012).
+ */
+ class month_day
+ {
+ month m_;
+ day d_;
+ public:
+ month_day(month m, day d)BOOST_NOEXCEPT
+ : m_(m),
+ d_(d)
+ {
+ // check validity of day relative to month.
+ }
+ month_day(month::rep m, day::rep d, no_check_t)BOOST_NOEXCEPT
+ : m_(m,no_check),
+ d_(d,no_check)
+ {
+ }
+ /**
+ * @Return the month stored component.
+ */
+ month get_month() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+ /**
+ * @Return the day stored component.
+ */
+ day get_day() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+ };
+
+ inline month_day operator/(month m, day d) BOOST_NOEXCEPT
+ {
+ return month_day(m, d);
+ }
+
+
+ inline month_day operator/(day d, month m) BOOST_NOEXCEPT
+ {
+ return month_day(m, d);
+ }
+
+
+ extern const month_day
+ jan_01, jan_02, jan_03, jan_04, jan_05, jan_06, jan_07,
+ jan_08, jan_09, jan_10, jan_11, jan_12, jan_13, jan_14,
+ jan_15, jan_16, jan_17, jan_18, jan_19, jan_20, jan_21,
+ jan_22, jan_23, jan_24, jan_25, jan_26, jan_27, jan_28, jan_29, jan_30, jan_31,
+ feb_01, feb_02, feb_03, feb_04, feb_05, feb_06, feb_07,
+ feb_08, feb_09, feb_10, feb_11, feb_12, feb_13, feb_14,
+ feb_15, feb_16, feb_17, feb_18, feb_19, feb_20, feb_21,
+ feb_22, feb_23, feb_24, feb_25, feb_26, feb_27, feb_28, feb_29,
+ mar_01, mar_02, mar_03, mar_04, mar_05, mar_06, mar_07,
+ mar_08, mar_09, mar_10, mar_11, mar_12, mar_13, mar_14,
+ mar_15, mar_16, mar_17, mar_18, mar_19, mar_20, mar_21,
+ mar_22, mar_23, mar_24, mar_25, mar_26, mar_27, mar_28, mar_29, mar_30, mar_31,
+ apr_01, apr_02, apr_03, apr_04, apr_05, apr_06, apr_07,
+ apr_08, apr_09, apr_10, apr_11, apr_12, apr_13, apr_14,
+ apr_15, apr_16, apr_17, apr_18, apr_19, apr_20, apr_21,
+ apr_22, apr_23, apr_24, apr_25, apr_26, apr_27, apr_28, apr_29, apr_30,
+ may_01, may_02, may_03, may_04, may_05, may_06, may_07,
+ may_08, may_09, may_10, may_11, may_12, may_13, may_14,
+ may_15, may_16, may_17, may_18, may_19, may_20, may_21,
+ may_22, may_23, may_24, may_25, may_26, may_27, may_28, may_29, may_30, may_31,
+ jun_01, jun_02, jun_03, jun_04, jun_05, jun_06, jun_07,
+ jun_08, jun_09, jun_10, jun_11, jun_12, jun_13, jun_14,
+ jun_15, jun_16, jun_17, jun_18, jun_19, jun_20, jun_21,
+ jun_22, jun_23, jun_24, jun_25, jun_26, jun_27, jun_28, jun_29, jun_30,
+ jul_01, jul_02, jul_03, jul_04, jul_05, jul_06, jul_07,
+ jul_08, jul_09, jul_10, jul_11, jul_12, jul_13, jul_14,
+ jul_15, jul_16, jul_17, jul_18, jul_19, jul_20, jul_21,
+ jul_22, jul_23, jul_24, jul_25, jul_26, jul_27, jul_28, jul_29, jul_30, jul_31,
+ aug_01, aug_02, aug_03, aug_04, aug_05, aug_06, aug_07,
+ aug_08, aug_09, aug_10, aug_11, aug_12, aug_13, aug_14,
+ aug_15, aug_16, aug_17, aug_18, aug_19, aug_20, aug_21,
+ aug_22, aug_23, aug_24, aug_25, aug_26, aug_27, aug_28, aug_29, aug_30, aug_31,
+ sep_01, sep_02, sep_03, sep_04, sep_05, sep_06, sep_07,
+ sep_08, sep_09, sep_10, sep_11, sep_12, sep_13, sep_14,
+ sep_15, sep_16, sep_17, sep_18, sep_19, sep_20, sep_21,
+ sep_22, sep_23, sep_24, sep_25, sep_26, sep_27, sep_28, sep_29, sep_30,
+ oct_01, oct_02, oct_03, oct_04, oct_05, oct_06, oct_07,
+ oct_08, oct_09, oct_10, oct_11, oct_12, oct_13, oct_14,
+ oct_15, oct_16, oct_17, oct_18, oct_19, oct_20, oct_21,
+ oct_22, oct_23, oct_24, oct_25, oct_26, oct_27, oct_28, oct_29, oct_30, oct_31,
+ nov_01, nov_02, nov_03, nov_04, nov_05, nov_06, nov_07,
+ nov_08, nov_09, nov_10, nov_11, nov_12, nov_13, nov_14,
+ nov_15, nov_16, nov_17, nov_18, nov_19, nov_20, nov_21,
+ nov_22, nov_23, nov_24, nov_25, nov_26, nov_27, nov_28, nov_29, nov_30,
+ dec_01, dec_02, dec_03, dec_04, dec_05, dec_06, dec_07,
+ dec_08, dec_09, dec_10, dec_11, dec_12, dec_13, dec_14,
+ dec_15, dec_16, dec_17, dec_18, dec_19, dec_20, dec_21,
+ dec_22, dec_23, dec_24, dec_25, dec_26, dec_27, dec_28, dec_29, dec_30, dec_31
+ ;
+
+ /**
+ * Class week_weekday is a tuple-like class of week-weekday.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ *
+ * It is useful when generation week based dates.
+ */
+ class week_weekday
+ {
+ week w_;
+ weekday wd_;
+ public:
+ week_weekday(week w, weekday wd)BOOST_NOEXCEPT
+ : w_(w),
+ wd_(wd)
+ {
+ }
+
+ week_weekday(week::rep w, weekday::rep wd, no_check_t)BOOST_NOEXCEPT
+ : w_(w, no_check),
+ wd_(wd, no_check)
+ {
+ }
+ week get_week() const BOOST_NOEXCEPT
+ {
+ return w_;
+ }
+ weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return wd_;
+ }
+
+ };
+
+ inline week_weekday operator/(week w, weekday wd) BOOST_NOEXCEPT
+ {
+ return week_weekday(w, wd);
+ }
+
+ inline week_weekday operator/(weekday wd, week w) BOOST_NOEXCEPT
+ {
+ return week_weekday(w, wd);
+ }
+
+ /**
+ * Class year_month_day is a tuple-like class of year-month-day.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ */
+ class year_month_day
+ {
+ year y_;
+ month m_;
+ day d_;
+ public:
+ year_month_day(year y, month m, day d)BOOST_NOEXCEPT
+ : y_(y),
+ m_(m),
+ d_(d)
+ {
+ }
+
+ year_month_day(year::rep y, month::rep m, day::rep d, no_check_t)BOOST_NOEXCEPT
+ : y_(y, no_check),
+ m_(m, no_check),
+ d_(d, no_check)
+ {
+ }
+ year get_year() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+ month get_month() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+ day get_day() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+
+ };
+
+ /**
+ * Class year_month_day is a tuple-like class of year-month-day.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ */
+ class year_month_day_leap
+ {
+ year y_;
+ month m_;
+ day d_;
+ bool leap_;
+ public:
+ year_month_day_leap(year y, month m, day d, bool leap)BOOST_NOEXCEPT
+ : y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ }
+
+ year_month_day_leap(year::rep y, month::rep m, day::rep d, bool leap, no_check_t)BOOST_NOEXCEPT
+ : y_(y, no_check),
+ m_(m, no_check),
+ d_(d, no_check),
+ leap_(leap)
+ {
+ }
+ year get_year() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+ month get_month() const BOOST_NOEXCEPT
+ {
+ return m_;
+ }
+ day get_day() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_;
+ }
+
+ };
+ /**
+ * Class year_day_of_year is a tuple-like class of year-day_of_year.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ */
+ class year_day_of_year
+ {
+ year y_;
+ day_of_year d_;
+ public:
+ year_day_of_year(year y, day_of_year d)BOOST_NOEXCEPT
+ : y_(y),
+ d_(d)
+ {
+ }
+ year_day_of_year(year::rep y, day_of_year::rep d, no_check_t) BOOST_NOEXCEPT
+ : y_(y, no_check),
+ d_(d, no_check)
+ {
+ }
+ year get_year() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+ day_of_year get_day_of_year() const BOOST_NOEXCEPT
+ {
+ return d_;
+ }
+
+ };
+
+
+ /**
+ * Class year_week_weekday is a tuple-like class of year-week-weekday.
+ *
+ * It is CopyConstructible, CopyAssignable, and Destructible.
+ */
+ class year_week_weekday
+ {
+ year y_;
+ week w_;
+ weekday wd_;
+ public:
+ year_week_weekday(year y, week w, weekday wd)BOOST_NOEXCEPT
+ : y_(y),
+ w_(w),
+ wd_(wd)
+ {
+ }
+ year_week_weekday(year::rep y, week::rep w, weekday::rep wd, no_check_t)BOOST_NOEXCEPT
+ : y_(y, no_check),
+ w_(w, no_check),
+ wd_(wd, no_check)
+ {
+ }
+ year get_year() const BOOST_NOEXCEPT
+ {
+ return y_;
+ }
+ week get_week() const BOOST_NOEXCEPT
+ {
+ return w_;
+ }
+ weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return wd_;
+ }
+
+ };
+
+
+
+
+
+
+
+
+
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/week.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/week.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,101 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_WEEK_HPP
+#define BOOST_CHRONO_DATE_DATE_WEEK_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class week is used to specify the week of the year.
+ */
+ class week
+ {
+ public:
+ typedef int_least8_t rep;
+ static const rep last_=53;
+ static const rep first_=1;
+ static const std::size_t size=last_-first_+1; // :6 bits
+
+ /**
+ * @Effects Constructs an object of class week by storing v.
+ * @Postconditions static_cast<rep>(*this) == v
+ * @Throws if v is outside of the range [1, 53], throws an exception of type bad_date.
+ */
+ explicit week(rep v)
+ : value_(v)
+ {
+ if (!is_valid())
+ {
+ throw bad_date("week day " + boost::chrono::to_string(v) + " is out of range");
+ }
+ }
+ /**
+ * @Effects Constructs an object of class week by storing v.
+ * @Postconditions static_cast<rep>(*this) == v
+ */
+ week(rep v,no_check_t) BOOST_NOEXCEPT
+ : value_(v)
+ {}
+
+ /**
+ * @return true if the v stored value is in the range [1, 53],
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+ /**
+ * @Returns: the value of the stored int.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Returns: the value of the stored int.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ static BOOST_CONSTEXPR week min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return week(first_,no_check);
+ }
+ static BOOST_CONSTEXPR week max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return week(last_,no_check);
+ }
+ private:
+ rep value_;
+ };
+
+ extern const week
+ w_01, w_02, w_03, w_04, w_05, w_06, w_07, w_08, w_09,
+ w_10, w_11, w_12, w_13, w_14, w_15, w_16, w_17, w_18, w_19,
+ w_20, w_21, w_22, w_23, w_24, w_25, w_26, w_27, w_28, w_29,
+ w_30, w_31, w_32, w_33, w_34, w_35, w_36, w_37, w_38, wv9,
+ w_40, w_41, w_42, w_43, w_44, w_45, wv6, w_47, w_48, w_49,
+ w_50, w_51, w_52, w_53;
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/weekday.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/weekday.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,156 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_WEEKDAY_HPP
+#define BOOST_CHRONO_DATE_DATE_WEEKDAY_HPP
+
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class weekday is used to specify a day of the week.
+ */
+ class weekday
+ {
+ public:
+ typedef int_least8_t rep;
+
+ static const rep last_=6;
+ static const rep first_=0;
+ static const int_least8_t size=last_-first_+1; //:3 bits
+ static const rep not_applicable=7;
+
+ /**
+ * @Effects Constructs an object of class weekday by storing v.
+ * @Postconditions static_cast<rep>(*this) == v
+ * @Throws if v is outside of the range [0, 6], throws an exception of type bad_date.
+ */
+ explicit weekday(rep v)
+ : value_(v)
+ {
+ if (!is_valid())
+ {
+ throw bad_date("week day " + boost::chrono::to_string(v) + " is out of range");
+ }
+ }
+ /**
+ * @Effects Constructs an object of class weekday by storing v.
+ * @Postconditions static_cast<rep>(*this) == v
+ */
+ explicit weekday(rep wd, no_check_t) BOOST_NOEXCEPT
+ :value_(wd)
+ {
+ };
+
+ /**
+ * @Returns: the value of the stored int.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * @Returns: the value of the stored int.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+
+ /**
+ * @Return if the stored value is a valid one.
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+
+
+ weekday next() const BOOST_NOEXCEPT
+ {
+ return weekday(((value_+1)%size),no_check);
+ }
+ weekday prev() BOOST_NOEXCEPT
+ {
+ return weekday((value_+size-1)%size,no_check);
+ }
+
+ /**
+ * @Returns: the first day of the week.
+ */
+ static BOOST_CONSTEXPR weekday first()
+ {
+ return weekday(first_,no_check);
+ }
+ /**
+ * @Returns: the last day of the week.
+ */
+ static BOOST_CONSTEXPR weekday last()
+ {
+ return weekday(last_,no_check);
+ }
+ static BOOST_CONSTEXPR weekday min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return weekday(first_,no_check);
+ }
+ static BOOST_CONSTEXPR weekday max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return weekday(last_,no_check);
+ }
+ private:
+ rep value_;
+ };
+
+ /**
+ * These const weekday objects are constructed prior to first use with the following values:
+ *
+ * const weekday sun(0);
+ * const weekday mon(1);
+ * const weekday tue(2);
+ * const weekday wed(3);
+ * const weekday thu(4);
+ * const weekday fri(5);
+ * const weekday sat(6);
+ *
+ */
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ inline std::string to_string(weekday v) {
+ switch (v) {
+ case 0: return "Sun";
+ case 1: return "Mon";
+ case 2: return "Tue";
+ case 3: return "Wed";
+ case 4: return "Thu";
+ case 5: return "Fri";
+ case 6: return "Sat";
+ default: throw bad_date("week day " + boost::chrono::to_string(v) + " is out of range");
+
+ }
+ }
+
+ } // chrono
+
+} // boost
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/ydoy_date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/ydoy_date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,524 @@
+// ydoy_date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_YDOY_DATE_HPP
+#define BOOST_CHRONO_DATE_YDOY_DATE_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/day_of_year.hpp>
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/week.hpp>
+#include <boost/chrono/date/tuples.hpp>
+#include <boost/chrono/date/config.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+#include <boost/chrono/date/conversions.hpp>
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/days_date.hpp>
+#include <boost/chrono/date/optional_date.hpp>
+#include <boost/chrono/date/is_date.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class @c ydoy_date is a model of Date storing
+ * - the @c year,
+ * - the @c day_of_year
+ * and optionally
+ * - whether the year is leap or not.
+ */
+ class ydoy_date
+ {
+
+ // Store y/doy + leap. Total 32 bits
+ int_least16_t y_;
+ uint_least16_t doy_ :9;
+ uint_least8_t leap_ :1;
+ uint_least8_t reserved2_ :6;
+
+ public:
+
+ /**
+ * @Effect Constructs a ydoy_date using the year, month, day stored in the arguments as follows:
+ * If the value stored in d is outside the range of valid dates for this month m and year y,
+ * throws an exception of type bad_date.
+ * Else constructs a ydoy_date for which get_year() == y, get_month() == m, get_day() == d.
+ * @Throws bad_date if the specified ydoy_date is invalid.
+ */
+ ydoy_date(chrono::year y, chrono::month m, chrono::day d);
+ /**
+ * @Effect Constructs a ydoy_date constructor from year, month, day stored in the arguments as follows:
+ * Constructs a ydoy_date so that get_year() == y, get_month() = m=, get_day() == d.
+ */
+ ydoy_date(year::rep y, month::rep m, day::rep d, no_check_t)
+BOOST_NOEXCEPT ;
+ /**
+ * @Effect Constructs a ydoy_date using the year, month_day stored in the arguments as follows:
+ * If the value stored in md is outside the range of valid dates for this year y,
+ * throws an exception of type bad_date.
+ * Else constructs a ydoy_date for which get_year() == y, get_month() == md.get_month(), get_day() == md.get_month().
+ *
+ * @Throws bad_date if the specified ydoy_date is invalid.
+ * @Note This constructor can be more efficient as the month_day is already valid.
+ */
+ ydoy_date(chrono::year y, chrono::month_day md);
+ /**
+ * @Effect Constructs a ydoy_date using the year, month_day stored in the arguments as follows:
+ * Constructs a ydoy_date for which get_year() == y, get_month() == md.get_month(), get_day() == md.get_month().
+ * @Note This constructor can be more efficient as the month_day is already valid.
+ */
+ ydoy_date(chrono::year::rep, chrono::month_day, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a ydoy_date using the year, day_of_year stored in the arguments as follows:
+ * If the value stored in doy is 366 and the year.is_leap()
+ * throws an exception of type bad_date.
+ * Else constructs a ydoy_date for which days_since_epoch() == y.days_since_epoch()+doy.value()
+ * @Throws bad_date if the specified ydoy_date is invalid.
+ * @Note This constructor can be more efficient as the check is simple.
+ */
+ ydoy_date(chrono::year y, chrono::day_of_year doy);
+ /**
+ * @Effect Constructs a ydoy_date using the year, day_of_year stored in the arguments as follows:
+ * Constructs a ydoy_date for which days_since_epoch() == y.days_since_epoch()+doy.value()
+ * @Throws bad_date if the specified ydoy_date is invalid.
+ */
+ ydoy_date(year::rep y, day_of_year::rep m, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a ydoy_date using the days given as parameter so that:
+ * days_since_epoch() == ds.count()
+ */
+ explicit ydoy_date(chrono::days);
+ /**
+ * Unchecked constructor from days.
+ */
+ ydoy_date(days::rep m, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ ydoy_date(days::rep, year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ : y_(y),
+ doy_(month_day_to_day_of_year(leap,m,d)),
+ leap_(leap)
+ {
+
+ }
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ ydoy_date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ : y_(y),
+ doy_(month_day_to_day_of_year(leap,m,d)),
+ leap_(leap)
+ {
+ }
+
+ /**
+ * @Return A ydoy_date which represents the current day taking the local time zone into account.
+ */
+ static ydoy_date today() BOOST_NOEXCEPT;
+
+ /**
+ * Effects: Constructs a ydoy_date as if by year(0)/jan/1.
+ * Note: the purpose of this constructor is to have a very efficient means
+ * of ydoy_date construction when the specific value for that ydoy_date is unimportant.
+ */
+ ydoy_date() BOOST_NOEXCEPT;
+
+ /**
+ * @Effects: tp is converted to UTC, and then trucated to 00:00:00 hours.
+ * A ydoy_date is created which reflects this point in time.
+ * @Throws If the conversion from tp overflows the range of ydoy_date, throws
+ * an exception of type bad_date.
+ *
+ */
+ explicit ydoy_date(boost::chrono::system_clock::time_point tp);
+ /**
+ * @Returns: A chrono::system_clock::time_point which represents the ydoy_date
+ * referred to by *this at 00:00:00 UTC.
+ *
+ * @Throws: If the conversion to tp overflows the range of
+ * boost::chrono::system_clock::time_point, throws an exception of type bad_date.
+ *
+ */
+ // explicit
+ operator boost::chrono::system_clock::time_point () const;
+
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return year(y_,no_check).is_valid() && day_of_year(doy_,no_check).is_valid();
+ }
+
+ /**
+ * @Returns: the number of days since an undefined epoch.
+ */
+ days days_since_epoch() const
+ {
+ return days(days_before_year(y_+32799)+doy_-1);
+ }
+
+ ydoy_date(ymd_date dt);
+ operator ymd_date() const
+ {
+ return days_date(y_, doy_, no_check);
+ }
+
+ ydoy_date(days_date dt);
+ operator days_date() const
+ {
+ return days_date(y_, doy_, no_check);
+ }
+
+ /**
+ * @Returns: chrono::day(d_,no_check).
+ */
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(day_of_year_day_of_month(leap_,doy_),no_check);
+ }
+ /**
+ * @Returns: chrono::month(m_,no_check).
+ */
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(day_of_year_month(leap_,doy_),no_check);
+ }
+ /**
+ * @Returns: chrono::year(y_,no_check).
+ */
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(y_,no_check);
+ }
+ month_day get_month_day() const BOOST_NOEXCEPT
+ {
+ return month_day(day_of_year_month(leap_,doy_), day_of_year_day_of_month(leap_,doy_), no_check);
+ }
+ year_month get_year_month() const BOOST_NOEXCEPT
+ {
+ return year_month(y_,day_of_year_month(leap_,doy_),no_check);
+ }
+ year_month_day get_year_month_day() const BOOST_NOEXCEPT
+ {
+ return to_ymd(year_day_of_year(y_,doy_,no_check));
+ }
+ /**
+ * @Returns: true if year() is a leap year, and otherwise returns false.
+ */
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_;
+ }
+
+ /**
+ * @Returns: A weekday constructed with an int corresponding to *this
+ * ydoy_date's day of the week (a value in the range of [0 - 6], 0 is Sunday).
+ */
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((days_since_epoch()+days(1)).count() % weekday::size,no_check);
+ }
+
+ /**
+ * @Effects: Adds d.count() days to the current ydoy_date.
+ * @Returns: *this.
+ * @Throws: If the addition would create a ydoy_date with a y_ outside of the
+ * range of year, throws an exception of type bad_date.
+ *
+ */
+ ydoy_date& operator+=(days d);
+
+ /**
+ * @Effects: *this += days(1).
+ * @Returns: *this.
+ */
+ ydoy_date& operator++()
+ {
+ return *this += days(1);
+ }
+ /**
+ * @Effects: *this += days(1).
+ * @Returns: A copy of *this prior to the increment.
+ */
+ ydoy_date operator++(int)
+ {
+ ydoy_date tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+ /**
+ * @Effects: *this += -d.
+ * @Returns: *this.
+ */
+ ydoy_date& operator-=(days d)
+ {
+ return *this += -d;
+ }
+ /**
+ * @Effects: *this -= days(1).
+ * @Returns: *this.
+ */
+ ydoy_date& operator--()
+ {
+ return *this -= days(1);
+ }
+ /**
+ * @Effects: *this -= days(1).
+ * @Returns: A copy of *this prior to the increment.
+ */
+ ydoy_date operator--(int)
+ {
+ ydoy_date tmp(*this); --(*this); return tmp;
+ }
+
+ /**
+ * @Returns: dt += d.
+ *
+ */
+ friend ydoy_date operator+(ydoy_date dt, days d)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: dt += d.
+ *
+ */
+ friend ydoy_date operator+(days d, ydoy_date dt)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: dt -= d.
+ *
+ */
+ friend ydoy_date operator-(ydoy_date dt, days d)
+ {
+ dt -= d;
+ return dt;
+ }
+ /**
+ * @Returns: Computes the number of days x is ahead of y in the calendar,
+ * and returns that signed integral number n as days(n).
+ */
+ friend days operator-(ydoy_date x, ydoy_date y) BOOST_NOEXCEPT
+ {
+ return days(x.days_since_epoch() - y.days_since_epoch());
+ }
+
+ friend days operator-(ymd_date x, ydoy_date y) BOOST_NOEXCEPT
+ {
+ return days(x.days_since_epoch() - y.days_since_epoch());
+ }
+
+ friend days operator-(ydoy_date x, ymd_date y) BOOST_NOEXCEPT
+ {
+ return days(x.days_since_epoch() - y.days_since_epoch());
+ }
+
+ /**
+ * @Effects Adds m.count() months to the current ydoy_date.
+ * This is accomplished as if by storing temporary values of the ydoy_date's y_, doy_.
+ * Computing new values for y_ and doy_ based on m. And then assigning to
+ * *this a new ydoy_date constructed from the newly computed y_ and doy_.
+ *
+ * @Returns: *this.
+ *
+ * @Throws: If the addition would create a ydoy_date with a y_ outside of the
+ * range of year, or a doy_ outside the range for the newly computed y_,
+ * throws an exception of type bad_date.
+ *
+ */
+ ydoy_date& operator+=(months m);
+
+ /**
+ * @Returns: *this += -m.
+ */
+ ydoy_date& operator-=(months m)
+ {
+ return *this += months(-m.count());
+ }
+
+ /**
+ * @Returns: dt += m.
+ *
+ */
+ friend ydoy_date operator+(ydoy_date dt, months m)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: dt += m.
+ *
+ */
+ friend ydoy_date operator+(months m, ydoy_date dt)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: dt += -m.
+ *
+ */
+ friend ydoy_date operator-(ydoy_date dt, months m)
+ {
+ dt -= m;
+ return dt;
+ }
+
+ /**
+ * @Effects: Adds y.count() years to the current ydoy_date.
+ * This is accomplished as if by storing temporary values of the ydoy_date's
+ * y_, doy_. Computing a new value for y_. And then assigning to *this
+ * a new ydoy_date constructed from the newly computed y_, and the original doy_.
+ * @Returns: *this.
+ * @Throws: If the addition would create a ydoy_date with a y_ outside of the
+ * range of year, or a doy_ outside the range for the newly computed y_,
+ * throws an exception of type bad_date.
+ */
+ ydoy_date& operator+=(years y);
+
+ /**
+ * @Returns: *this += -y.
+ *
+ */
+ ydoy_date& operator-=(years y)
+ {
+ return *this += years(-y.count());
+ }
+
+ /**
+ * @Returns: dt += y.
+ *
+ */
+ friend ydoy_date operator+(ydoy_date dt, years y)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: dt += y.
+ *
+ */
+ friend ydoy_date operator+(years y, ydoy_date dt)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: dt -= y.
+ *
+ */
+ friend ydoy_date operator-(ydoy_date dt, years y)
+ {
+ dt -= y;
+ return dt;
+ }
+
+ /**
+ * @Returns: x.days_since_epoch() == y.days_since_epoch()
+ */
+ friend bool operator==(const ydoy_date& x, const ydoy_date& y) BOOST_NOEXCEPT
+ {
+ return x.y_ == y.y_ && x.doy_ == y.doy_;
+ }
+ /**
+ * @Returns: x.days_since_epoch() < y.days_since_epoch()
+ */
+ friend bool operator< (const ydoy_date& x, const ydoy_date& y)
+ {
+ return x.y_ < y.y_ ||
+ (!(y.y_ < x.y_) && (x.doy_ < y.doy_));
+ }
+ /**
+ * @Returns: !(x == y).
+ */
+ friend bool operator!=(const ydoy_date& x, const ydoy_date& y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ /**
+ * @Returns: y < x.
+ */
+ friend bool operator> (const ydoy_date& x, const ydoy_date& y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ /**
+ * @Returns: !(y < x).
+ */
+ friend bool operator<=(const ydoy_date& x, const ydoy_date& y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ /**
+ * @Returns: !(x < y).
+ */
+ friend bool operator>=(const ydoy_date& x, const ydoy_date& y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+ /**
+ * @Effects Update the ydoy_date if the parameters represents a valid ydoy_date.
+ * @Returns true if the parameters represents a valid ydoy_date.
+ */
+ bool set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT;
+
+ };
+
+ template <>
+ struct is_date<ydoy_date> : true_type {};
+
+// /**
+// * A type representing an optional ydoy_date.
+// */
+// typedef optional<ydoy_date> optional_ydoy_date;
+// /**
+// * @Returns If the parameters represents a valid ydoy_date the ydoy_date,
+// * otherwise a none optional.
+// */
+// optional_ydoy_date make_valid_ydoy_date(year,month,day) BOOST_NOEXCEPT;
+
+ inline ydoy_date operator/(year y, day_of_year d)
+ {
+ return ydoy_date(y, d);
+ }
+ inline ydoy_date operator/(day_of_year d, year y)
+ {
+ return ydoy_date(y, d);
+ }
+ inline ydoy_date operator/(year y, day_of_year::rep d)
+ {
+ return y / day_of_year(d);
+ }
+ inline ydoy_date operator/(day_of_year d, year::rep y)
+ {
+ return d / year(y);
+ }
+
+ } // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/year.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/year.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,153 @@
+// date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_DATE_YEAR_HPP
+#define BOOST_CHRONO_DATE_DATE_YEAR_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/config.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class year is used to specify the year when constructing a date.
+ * It also defines the range of the date class by restricting the value of
+ * the year to a range.
+ *
+ * That range shall be at least [year(-32767)/jan/1 thru year(32767)/dec/31].
+ */
+ class year
+ {
+ public:
+ /**
+ * Internal representation of a year.
+ *
+ * In order for year to detect overflow, the integral type used to construct the year must have a range greater than that of year.
+ */
+ typedef int_least32_t rep;
+ static const rep last_ = 32767;
+ static const rep first_ = -32768;
+ static const std::size_t size = last_ - first_ + 1; // :16 bits
+
+ /**
+ * @Effects: Constructs an object of class year by storing y.
+ * @Postconditions: static_cast<int>(*this) == y.
+ * @Throws: if y is outside of the supported range, throws an exception of type bad_date.
+ */
+ explicit year(rep v) :
+ value_(v)
+ {
+ if (!is_valid())
+ {
+ throw bad_date("year " + to_string(v) + " is out of range");
+ }
+ }
+
+ /**
+ * @Effects: Constructs an object of class year by storing y.
+ * @Postconditions: static_cast<int>(*this) == y.
+ */
+ BOOST_CONSTEXPR year(rep y, no_check_t)BOOST_NOEXCEPT
+ :value_(y)
+ {}
+ /**
+ * @Return if the stored value is a valid one.
+ */
+ bool is_valid() const BOOST_NOEXCEPT
+ {
+ return (first_ <= value_ && value_ <= last_);
+ }
+
+ /**
+ * Returns: the value of the stored int.
+ */
+ operator rep() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+ /**
+ * Returns: the value of the stored int.
+ */
+ rep value() const BOOST_NOEXCEPT
+ {
+ return value_;
+ }
+
+ // year& operator++() BOOST_NOEXCEPT
+ // {
+ // ++value_;
+ // return *this;
+ // }
+ // year& operator--() BOOST_NOEXCEPT
+ // {
+ // --value_;
+ // return *this;
+ // }
+
+ /**
+ * @Return the number of days of this year.
+ */
+ days days_in() const BOOST_NOEXCEPT
+ {
+ return days(365+days::rep(is_leap()));
+ }
+
+ /**
+ * @Return the number of days of the month parameter in this year.
+ */
+ days days_in(month m) const
+BOOST_NOEXCEPT ;
+
+ /**
+ * @Return the number of days since the epoch until the fist day of this year.
+ */
+ inline days days_since_epoch() const BOOST_NOEXCEPT
+ {
+ return days(days_before_year(value_));
+ }
+
+ /**
+ * @Return whether this year is leap or not.
+ */
+ bool is_leap() const BOOST_NOEXCEPT
+ {
+ int32_t y = value_;
+ return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
+ }
+
+ static BOOST_CONSTEXPR year zero()
+ {
+ return year(0);
+ }
+ static BOOST_CONSTEXPR year min BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return year(first_);
+ }static BOOST_CONSTEXPR year max BOOST_PREVENT_MACRO_SUBSTITUTION ()
+ {
+ return year(last_);
+ }
+
+ private:
+ rep value_;
+
+ };
+
+ } // chrono
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/boost/chrono/date/ymd_date.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/boost/chrono/date/ymd_date.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,630 @@
+// ymd_date
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_DATE_YMD_DATE_HPP
+#define BOOST_CHRONO_DATE_YMD_DATE_HPP
+
+#include <boost/cstdint.hpp>
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/no_check.hpp>
+#include <boost/chrono/date/date_durations.hpp>
+#include <boost/chrono/date/exceptions.hpp>
+#include <boost/chrono/date/year.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/day.hpp>
+#include <boost/chrono/date/day_of_year.hpp>
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/week.hpp>
+#include <boost/chrono/date/tuples.hpp>
+#include <boost/chrono/date/config.hpp>
+#include <boost/chrono/date/days_date.hpp>
+#include <boost/chrono/date/optional_date.hpp>
+#include <boost/chrono/date/is_date.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ /**
+ * The class @c ymd_date is a model of Date storing
+ * - the @c year,
+ * - the @c month,
+ * - the @c day of the month
+ * and optionally
+ * - the number of @c days since an undetermined epoch.
+ * - whether the year is leap or not.
+ */
+ class ymd_date
+ {
+
+#if !defined BOOST_CHRONO_DATE_COMPACT
+ // Store x, y/m/d, leap. Total 64 bits
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ uint_least32_t x_;
+#endif
+ int_least16_t y_;
+
+ uint_least8_t m_ :4;
+ uint_least8_t reserved1_ :4;
+
+ uint_least8_t d_ :5;
+ uint_least8_t leap_ :1;
+ uint_least8_t reserved2_ :2;
+#else
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ days x_;
+#endif
+ year y_;
+ month m_;
+ day d_;
+ bool leap_;
+#endif
+ public:
+ /**
+ * @Effect Constructs a @c ymd_date using the @c year, @c month, @c day stored in the arguments as follows:
+ * If the value stored in @c d is outside the range of valid dates for this month @c m and year @c y,
+ * throws an exception of type @c bad_date.
+ * Else constructs a @c ymd_date for which <c>get_year() == y && get_month() == m && get_day() == d</c>.
+ * @Throws @c bad_date if the specified @c ymd_date is invalid.
+ */
+ ymd_date(chrono::year y, chrono::month m, chrono::day d);
+ /**
+ * @Effect Constructs a @c ymd_date constructor from @c year, @c month, @c day stored in the arguments as follows:
+ * Constructs a ymd_date so that <c>get_year() == y && get_month() = m && get_day() == d</c>.
+ */
+ ymd_date(year::rep y, month::rep m, day::rep d, no_check_t)
+BOOST_NOEXCEPT ;
+ /**
+ * @Effect Constructs a ymd_date using the year, month_day stored in the arguments as follows:
+ * If the value stored in md is outside the range of valid dates for this year y,
+ * throws an exception of type bad_date.
+ * Else constructs a ymd_date for which get_year() == y, get_month() == md.get_month(), get_day() == md.get_month().
+ *
+ * @Throws bad_date if the specified ymd_date is invalid.
+ * @Note This constructor can be more efficient as the month_day is already valid.
+ */
+ ymd_date(chrono::year y, chrono::month_day md);
+ /**
+ * @Effect Constructs a ymd_date using the year, month_day stored in the arguments as follows:
+ * Constructs a ymd_date for which get_year() == y, get_month() == md.get_month(), get_day() == md.get_month().
+ * @Note This constructor can be more efficient as the month_day is already valid.
+ */
+ ymd_date(chrono::year::rep, chrono::month_day, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a ymd_date using the year, day_of_year stored in the arguments as follows:
+ * If the value stored in doy is 366 and the year.is_leap()
+ * throws an exception of type bad_date.
+ * Else constructs a ymd_date for which days_since_epoch() == y.days_since_epoch()+doy.value()
+ * @Throws bad_date if the specified ymd_date is invalid.
+ * @Note This constructor can be more efficient as the check is simple.
+ */
+ ymd_date(chrono::year y, chrono::day_of_year doy);
+ /**
+ * @Effect Constructs a ymd_date using the year, day_of_year stored in the arguments as follows:
+ * Constructs a ymd_date for which days_since_epoch() == y.days_since_epoch()+doy.value()
+ * @Throws bad_date if the specified ymd_date is invalid.
+ */
+ ymd_date(year::rep y, day_of_year::rep m, no_check_t) BOOST_NOEXCEPT;
+
+ /**
+ * @Effect Constructs a ymd_date using the days given as parameter so that:
+ * days_since_epoch() == ds.count()
+ */
+ explicit ymd_date(chrono::days);
+ /**
+ * Unchecked constructor from days.
+ */
+ ymd_date(days::rep m, no_check_t) BOOST_NOEXCEPT;
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ /**
+ * Unchecked constructor from days+ymd+leap
+ */
+ ymd_date(days::rep x, year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ : x_(x),
+ y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ }
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ ymd_date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT;
+
+#elif BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 3
+ /**
+ * Unchecked constructor from days+ymd+leap
+ */
+ ymd_date(days::rep, year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ :
+ y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ }
+ /**
+ * Unchecked constructor from ymd+leap
+ */
+ ymd_date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ : y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ }
+#endif
+
+ /**
+ * @Effects Update the ymd_date if the parameters represents a valid ymd_date.
+ * @Returns true if the parameters represents a valid ymd_date.
+ */
+ bool set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT;
+ /**
+ * @Effects Update the ymd_date if the parameters represents a valid ymd_date.
+ * @Returns true if the parameters represents a valid ymd_date.
+ */
+ bool set_if_valid_date(year y, day_of_year doy) BOOST_NOEXCEPT;
+
+ /**
+ * @Effects Update the ymd_date if the parameters represents a valid ymd_date.
+ * @Returns true if the parameters represents a valid ymd_date.
+ */
+ bool set_if_valid_date(days d) BOOST_NOEXCEPT;
+
+ /**
+ * @Return A ymd_date which represents the current day taking the local time zone into account.
+ */
+ static ymd_date today() BOOST_NOEXCEPT;
+
+ /**
+ * Effects: Constructs a ymd_date as if by year(0)/jan/1.
+ * Note: the purpose of this constructor is to have a very efficient means
+ * of ymd_date construction when the specific value for that ymd_date is unimportant.
+ */
+ ymd_date() BOOST_NOEXCEPT
+ :
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ x_(11979588),
+#endif
+ y_(0),
+ m_(1),
+ d_(1),
+ leap_(1)
+ {
+ }
+ /**
+ * @Effects: tp is converted to UTC, and then trucated to 00:00:00 hours.
+ * A ymd_date is created which reflects this point in time.
+ * @Throws If the conversion from tp overflows the range of ymd_date, throws
+ * an exception of type bad_date.
+ *
+ */
+ explicit ymd_date(boost::chrono::system_clock::time_point tp);
+ /**
+ * @Returns: A chrono::system_clock::time_point which represents the ymd_date
+ * referred to by *this at 00:00:00 UTC.
+ *
+ * @Throws: If the conversion to tp overflows the range of
+ * boost::chrono::system_clock::time_point, throws an exception of type bad_date.
+ *
+ */
+ // explicit
+ operator boost::chrono::system_clock::time_point () const;
+
+ bool is_valid() const BOOST_NOEXCEPT;
+
+ /**
+ * @Returns: the number of days since an undefined epoch.
+ */
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ days days_since_epoch() const
+ {
+ return days(x_);
+ }
+#elif BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 3
+ days days_since_epoch() const
+ {
+ return days(day_number_from_ymd());
+ }
+#endif
+
+ ymd_date(days_date dt);
+ operator days_date() const
+ {
+ return days_date(days_since_epoch().count(), no_check);
+ }
+
+ /**
+ * Returns: chrono::day(d_,no_check).
+ */
+ chrono::day get_day() const BOOST_NOEXCEPT
+ {
+ return chrono::day(d_,no_check);
+ }
+ /**
+ * Returns: chrono::month(m_,no_check).
+ */
+ chrono::month get_month() const BOOST_NOEXCEPT
+ {
+ return chrono::month(m_,no_check);
+ }
+ /**
+ * Returns: chrono::year(y_,no_check).
+ */
+ chrono::year get_year() const BOOST_NOEXCEPT
+ {
+ return chrono::year(y_,no_check);
+ }
+ month_day get_month_day() const BOOST_NOEXCEPT
+ {
+ return month_day(m_, d_, no_check);
+ }
+ year_month get_year_month() const BOOST_NOEXCEPT
+ {
+ return year_month(y_,m_,no_check);
+ }
+ year_month_day get_year_month_day() const BOOST_NOEXCEPT
+ {
+ return year_month_day(y_,m_,d_, no_check);
+ }
+ /**
+ * Returns: true if year() is a leap year, and otherwise returns false.
+ */
+ bool is_leap_year() const BOOST_NOEXCEPT
+ {
+ return leap_;
+ }
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ /**
+ * @Returns: A weekday constructed with an int corresponding to *this
+ * ymd_date's day of the week (a value in the range of [0 - 6], 0 is Sunday).
+ */
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((x_ + 1) % weekday::size, no_check);
+ }
+#elif BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 3
+ chrono::weekday get_weekday() const BOOST_NOEXCEPT
+ {
+ return chrono::weekday((day_number_from_ymd()+1) % weekday::size,no_check);
+ }
+#endif
+
+ /**
+ * @Effects: Adds d.count() days to the current ymd_date.
+ * @Returns: *this.
+ * @Throws: If the addition would create a ymd_date with a y_ outside of the
+ * range of year, throws an exception of type bad_date.
+ *
+ */
+ ymd_date& operator+=(days d);
+
+ /**
+ * @Effects: *this += days(1).
+ * @Returns: *this.
+ */
+ ymd_date& operator++()
+ {
+ return *this += days(1);
+ }
+ /**
+ * @Effects: *this += days(1).
+ * @Returns: A copy of *this prior to the increment.
+ */
+ ymd_date operator++(int)
+ {
+ ymd_date tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+ /**
+ * @Effects: *this += -d.
+ * @Returns: *this.
+ */
+ ymd_date& operator-=(days d)
+ {
+ return *this += -d;
+ }
+ /**
+ * @Effects: *this -= days(1).
+ * @Returns: *this.
+ */
+ ymd_date& operator--()
+ {
+ return *this -= days(1);
+ }
+ /**
+ * @Effects: *this -= days(1).
+ * @Returns: A copy of *this prior to the increment.
+ */
+ ymd_date operator--(int)
+ {
+ ymd_date tmp(*this); --(*this); return tmp;
+ }
+
+ /**
+ * @Returns: dt += d.
+ *
+ */
+ friend ymd_date operator+(ymd_date dt, days d)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: dt += d.
+ *
+ */
+ friend ymd_date operator+(days d, ymd_date dt)
+ {
+ dt += d;
+ return dt;
+ }
+ /**
+ * @Returns: dt -= d.
+ *
+ */
+ friend ymd_date operator-(ymd_date dt, days d)
+ {
+ dt -= d;
+ return dt;
+ }
+ /**
+ * @Returns: Computes the number of days x is ahead of y in the calendar,
+ * and returns that signed integral number n as days(n).
+ */
+ friend days operator-(ymd_date x, ymd_date y) BOOST_NOEXCEPT
+ {
+ return days(x.days_since_epoch() - y.days_since_epoch());
+ }
+ friend days operator-(days_date x, ymd_date y) BOOST_NOEXCEPT
+ {
+ return days(x.days_since_epoch() - y.days_since_epoch());
+ }
+ friend days operator-(ymd_date x, days_date y) BOOST_NOEXCEPT
+ {
+ return days(x.days_since_epoch() - y.days_since_epoch());
+ }
+
+ /**
+ * @Effects Adds m.count() months to the current ymd_date.
+ * This is accomplished as if by storing temporary values of the ymd_date's y_, m_, d_.
+ * Computing new values for y_ and m_ based on m. And then assigning to
+ * *this a new ymd_date constructed from the newly computed y_ and m_, and the
+ * original d_.
+ *
+ * @Note Thus for example if a ymd_date is constructed as the second Sunday
+ * in May, adding two months to this ymd_date results in the second Sunday
+ * in July.
+ *
+ * @Returns: *this.
+ *
+ * @Throws: If the addition would create a ymd_date with a y_ outside of the
+ * range of year, or a d_ outside the range for the newly computed y_/m_,
+ * throws an exception of type bad_date.
+ *
+ */
+ ymd_date& operator+=(months m);
+
+ /**
+ * Returns: *this += -m.
+ */
+ ymd_date& operator-=(months m)
+ {
+ return *this += months(-m.count());
+ }
+
+ /**
+ * @Returns: dt += m.
+ *
+ */
+ friend ymd_date operator+(ymd_date dt, months m)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: dt += m.
+ *
+ */
+ friend ymd_date operator+(months m, ymd_date dt)
+ {
+ dt += m;
+ return dt;
+ }
+ /**
+ * @Returns: dt += -m.
+ *
+ */
+ friend ymd_date operator-(ymd_date dt, months m)
+ {
+ dt -= m;
+ return dt;
+ }
+
+ /*
+ * @Effects: Adds y.count() years to the current ymd_date.
+ * This is accomplished as if by storing temporary values of the ymd_date's
+ * y_, m_, d_. Computing a new value for y_. And then assigning to *this
+ * a new ymd_date constructed from the newly computed y_, and the original m_, d_.
+ * @Note: Thus for example if a ymd_date is constructed as the second Sunday
+ * in May 2011, adding two years to this ymd_date results in the second Sunday
+ * in May 2013.
+ * @Returns: *this.
+ * @Throws: If the addition would create a ymd_date with a y_ outside of the
+ * range of year, or a d_ outside the range for the newly computed y_/m_,
+ * throws an exception of type bad_date.
+ */
+ ymd_date& operator+=(years y);
+
+ /**
+ * @Returns: *this += -y.
+ *
+ */
+ ymd_date& operator-=(years y)
+ {
+ return *this += years(-y.count());
+ }
+
+ /**
+ * @Returns: dt += y.
+ *
+ */
+ friend ymd_date operator+(ymd_date dt, years y)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: dt += y.
+ *
+ */
+ friend ymd_date operator+(years y, ymd_date dt)
+ {
+ dt += y;
+ return dt;
+ }
+ /**
+ * @Returns: dt -= y.
+ *
+ */
+ friend ymd_date operator-(ymd_date dt, years y)
+ {
+ dt -= y;
+ return dt;
+ }
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ /**
+ * Returns: x.days_since_epoch() == y.days_since_epoch()
+ */
+ friend bool operator==(const ymd_date& x, const ymd_date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ == y.x_;
+ }
+ /**
+ * Returns: x.days_since_epoch() < y.days_since_epoch()
+ */
+ friend bool operator< (const ymd_date& x, const ymd_date& y) BOOST_NOEXCEPT
+ {
+ return x.x_ < y.x_;
+ }
+#elif BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 3
+ friend bool operator==(const ymd_date& x, const ymd_date& y) BOOST_NOEXCEPT
+ {
+ return x.y_ == y.y_ && x.m_ == y.m_ && x.d_ == y.d_;
+ }
+ friend bool operator< (const ymd_date& x, const ymd_date& y)
+ {
+ return x.y_ < y.y_ ||
+ (!(y.y_ < x.y_) && (x.m_ < y.m_ ||
+ (!(y.m_ < x.m_) && x.d_ < y.d_)));
+ }
+#endif
+ /**
+ * @Returns: !(x == y).
+ */
+ friend bool operator!=(const ymd_date& x, const ymd_date& y) BOOST_NOEXCEPT
+ {
+ return !(x == y);
+ }
+ /**
+ * @Returns: y < x.
+ */
+ friend bool operator> (const ymd_date& x, const ymd_date& y) BOOST_NOEXCEPT
+ {
+ return y < x;
+ }
+ /**
+ * @Returns: !(y < x).
+ */
+ friend bool operator<=(const ymd_date& x, const ymd_date& y) BOOST_NOEXCEPT
+ {
+ return !(y < x);
+ }
+ /**
+ * @Returns: !(x < y).
+ */
+ friend bool operator>=(const ymd_date& x, const ymd_date& y) BOOST_NOEXCEPT
+ {
+ return !(x < y);
+ }
+
+
+
+ private:
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 3
+ days::rep day_number_from_ymd() const BOOST_NOEXCEPT;
+#endif
+ //#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ // day::rep day_from_day_number() const BOOST_NOEXCEPT;
+ // month::rep month_from_day_number() const BOOST_NOEXCEPT;
+ // year::rep year_from_day_number() const BOOST_NOEXCEPT;
+ // bool leap_from_day_number() const BOOST_NOEXCEPT;
+ //#endif
+
+ };
+
+ template <>
+ struct is_date<ymd_date> : true_type {};
+
+// /**
+// * A type representing an optional ymd_date.
+// */
+// typedef optional<ymd_date> optional_ymd_date;
+// /**
+// * @Returns If the parameters represents a valid ymd_date the ymd_date,
+// * otherwise a none optional.
+// */
+// inline optional_ymd_date make_valid_ymd_date(year y,month m,day d) BOOST_NOEXCEPT
+// {
+// ymd_date res;
+// if (res.set_if_valid_date(y,m,d)) return optional_ymd_date(res);
+// else return optional_ymd_date();
+//
+// }
+
+ // ymd_date make_ymd_date(year::rep,month::rep,day::rep) BOOST_NOEXCEPT;
+ // ymd_date make_ydoy_date(year::rep,day_of_year::rep) BOOST_NOEXCEPT;
+ // ymd_date make_epoch_date(days::rep) BOOST_NOEXCEPT;
+
+ inline ymd_date operator/(year_month ym, day d)
+ {
+ return ymd_date(ym.get_year(), ym.get_month(), d);
+ }
+ inline ymd_date operator/(year_month ym, day::rep d)
+ {
+ return ym / day(d);
+ }
+ inline ymd_date operator/(month_day md, year y)
+ {
+ return ymd_date(y, md.get_month(), md.get_day());
+ }
+ inline ymd_date operator/(year y, month_day md)
+ {
+ return ymd_date(y, md.get_month(), md.get_day());
+ }
+ inline ymd_date operator/(month_day md, year::rep y)
+ {
+ return md / year(y);
+ }
+
+ } // chrono
+
+} // boost
+
+
+#endif // header

Added: sandbox/chrono_date/libs/date/build/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/build/Jamfile.v2 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,104 @@
+# Boost Chrono Library Build Jamfile
+
+# Copyright Vicente J. Botet Escriba 2011
+
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or www.boost.org/LICENSE_1_0.txt)
+
+# See library home page at http://www.boost.org/libs/chrono
+
+project boost/chrono/date
+ : source-location ../src
+ : requirements
+ <target-os>freebsd:<linkflags>"-lrt"
+ <target-os>linux:<linkflags>"-lrt"
+ <toolset>pgi:<linkflags>"-lrt"
+ #<threading>single:<define>BOOST_CHRONO_THREAD_DISABLED
+
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ #<define>BOOST_SYSTEM_INLINED
+
+ <define>BOOST_CHRONO_DONT_PROVIDE_DEPRECATED_IO_V1
+ <define>BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
+ #<define>BOOST_CHRONO_HEADER_ONLY
+
+ #<define>BOOST_COMMON_TYPE_USES_STATIC_ASSERT
+ #<define>BOOST_RATIO_USES_STATIC_ASSERT
+ #<define>BOOST_CHRONO_USES_STATIC_ASSERT
+ #<define>BOOST_COMMON_TYPE_USES_MPL_ASSERT
+ #<define>BOOST_RATIO_USES_MPL_ASSERT
+ #<define>BOOST_CHRONO_USES_MPL_ASSERT
+ #<define>BOOST_COMMON_TYPE_USES_ARRAY_ASSERT
+ #<define>BOOST_RATIO_USES_ARRAY_ASSERT
+ #<define>BOOST_CHRONO_USES_ARRAY_ASSERT
+ <toolset>sun:<define>BOOST_TYPEOF_EMULATION
+ <define>BOOST_SYSTEM_NO_DEPRECATED
+ #<toolset>gcc-3.4.4:<linkflags>--enable-auto-import
+ #<toolset>gcc-4.3.4:<linkflags>--enable-auto-import
+ #<toolset>gcc-mingw-4.4.0:<linkflags>--enable-auto-import
+ #<toolset>gcc-mingw-4.5.0:<linkflags>--enable-auto-import
+ <warnings>all
+ <toolset>gcc:<cxxflags>-Wextra
+ <toolset>gcc:<cxxflags>-pedantic
+ <toolset>gcc:<cxxflags>-Wno-long-long
+ <toolset>darwin:<cxxflags>-Wextra
+ <toolset>darwin:<cxxflags>-pedantic
+ <toolset>darwin:<cxxflags>-Wno-long-long
+ #<toolset>pathscale:<cxxflags>-Wextra
+ <toolset>pathscale:<cxxflags>-Wno-long-long
+ <toolset>pathscale:<cxxflags>-pedantic
+ <toolset>clang:<cxxflags>-Wextra
+ <toolset>clang:<cxxflags>-pedantic
+ <toolset>clang:<cxxflags>-Wno-long-long
+ <toolset>gcc-mingw-4.4.0:<cxxflags>-fdiagnostics-show-option
+ <toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
+ <toolset>gcc-mingw-4.6.0:<cxxflags>-fdiagnostics-show-option
+# Note: Some of the remarks from the Intel compiler are disabled
+# remark #304: access control not specified ("public" by default)
+# remark #383: value copied to temporary, reference to temporary used
+# remark #1418: external function definition with no prior declaration
+ <toolset>intel:<cxxflags>-wd304,383,1418
+
+ : usage-requirements # pass these requirement to dependents (i.e. users)
+ <threading>single:<define>BOOST_CHRONO_THREAD_DISABLED
+
+ <define>BOOST_CHRONO_DONT_PROVIDE_DEPRECATED_IO_V1
+ <define>BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
+ #<define>BOOST_CHRONO_HEADER_ONLY
+
+ <library>/boost/system//boost_system
+ #<define>BOOST_SYSTEM_INLINED
+ #<define>BOOST_COMMON_TYPE_USES_STATIC_ASSERT
+ #<define>BOOST_RATIO_USES_STATIC_ASSERT
+ #<define>BOOST_CHRONO_USES_STATIC_ASSERT
+ #<define>BOOST_COMMON_TYPE_USES_MPL_ASSERT
+ #<define>BOOST_RATIO_USES_MPL_ASSERT
+ #<define>BOOST_CHRONO_USES_MPL_ASSERT
+ #<define>BOOST_COMMON_TYPE_USES_ARRAY_ASSERT
+ #<define>BOOST_RATIO_USES_ARRAY_ASSERT
+ #<define>BOOST_CHRONO_USES_ARRAY_ASSERT
+ <toolset>sun:<define>BOOST_COMMON_TYPE_DONT_USE_TYPEOF
+ <toolset>sun:<define>BOOST_TYPEOF_EMULATION
+ <define>BOOST_SYSTEM_NO_DEPRECATED
+ <link>shared:<define>BOOST_CHRONO_DYN_LINK=1
+ <link>static:<define>BOOST_CHRONO_STATIC_LINK=1
+ <toolset>gcc-3.4.4:<linkflags>--enable-auto-import
+ <toolset>gcc-4.3.4:<linkflags>--enable-auto-import
+ <toolset>gcc-mingw-4.4.0:<linkflags>--enable-auto-import
+ <toolset>gcc-mingw-4.5.0:<linkflags>--enable-auto-import
+ ;
+
+SOURCES =
+rel_date vars days_date ymd_date ydoy_date conversions
+#date rel_date days_date ymd_date ydoy_date conversions vars
+;
+
+
+lib boost_chrono_date
+ : $(SOURCES).cpp
+ :
+ <link>shared:<define>BOOST_ALL_DYN_LINK=1 # tell source we're building dll's
+ <link>static:<define>BOOST_All_STATIC_LINK=1 # tell source we're building static lib's
+ ;
+

Added: sandbox/chrono_date/libs/date/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/doc/Jamfile.v2 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,76 @@
+# Boost.Chrono library documentation Jamfile ---------------------------------
+#
+# Copyright Vicente J. Botet Escriba 2009. Use, modification and
+# distribution is subject to the Boost Software License, Version
+# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+# See http://www.boost.org for updates, documentation, and revision history.
+
+#import doxygen ;
+using quickbook ;
+
+#doxygen autodoc
+# :
+# [ glob ../../../boost/chrono/*.hpp ]
+# [ glob ../../../boost/chrono/allocators/*.hpp ]
+# :
+# <doxygen:param>EXTRACT_ALL=NO
+# <doxygen:param>HIDE_UNDOC_MEMBERS=YES
+# <doxygen:param>EXTRACT_PRIVATE=NO
+# <doxygen:param>EXPAND_ONLY_PREDEF=YES
+# <doxygen:param>PREDEFINED=BOOST_INTERPROCESS_DOXYGEN_INVOKED
+# <xsl:param>"boost.doxygen.reftitle=Boost.Chrono Reference"
+# ;
+
+xml chrono : chrono.qbk ;
+
+boostbook standalone
+ :
+ chrono
+ :
+ # HTML options first:
+ # Use graphics not text for navigation:
+ <xsl:param>navig.graphics=1
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=2
+ # Don't put the first section on the same page as the TOC:
+ <xsl:param>chunk.first.sections=1
+ # How far down sections get TOC's
+ <xsl:param>toc.section.depth=4
+ # Max depth in each TOC:
+ <xsl:param>toc.max.depth=2
+ # How far down we go with TOC's
+ <xsl:param>generate.section.toc.level=10
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ # Path for libraries index:
+ <xsl:param>boost.libraries=../../../../libs/libraries.htm
+ # Use the main Boost stylesheet:
+ <xsl:param>html.stylesheet=../../../../doc/src/boostbook.css
+
+ # PDF Options:
+ # TOC Generation: this is needed for FOP-0.9 and later:
+ <format>pdf:<xsl:param>fop1.extensions=0
+ # Or enable this if you're using XEP:
+ <format>pdf:<xsl:param>xep.extensions=1
+ # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
+ <format>pdf:<xsl:param>fop.extensions=0
+ # No indent on body text:
+ <xsl:param>body.start.indent=0pt
+ # Margin size:
+ <xsl:param>page.margin.inner=0.5in
+ # Margin size:
+ <xsl:param>page.margin.outer=0.5in
+ # Yes, we want graphics for admonishments:
+ <xsl:param>admon.graphics=1
+ # Set this one for PDF generation *only*:
+ # default pnd graphics are awful in PDF form,
+ # better use SVG's instead:
+ <format>pdf:<xsl:param>admon.graphics.extension=".svg"
+ <format>pdf:<xsl:param>admon.graphics.path=$(boost-images)
+ <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/chrono/doc/html
+ ;
+
+install pdf-install : standalone : <location>. <install-type>PDF ;
+

Added: sandbox/chrono_date/libs/date/doc/date.html
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/doc/date.html 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,3476 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>chrono::date</title>
+ <style type="text/css">
+ p {text-align:justify}
+ li {text-align:justify}
+ blockquote.note
+ {
+ background-color:#E0E0E0;
+ padding-left: 15px;
+ padding-right: 15px;
+ padding-top: 1px;
+ padding-bottom: 1px;
+ }
+ ins {background-color:#A0FFA0}
+ del {background-color:#FFA0A0}
+ </style>
+</head>
+<body>
+
+<address align=right>
+Document number: Dxxxx=xx-xxxx<br>
+<br>
+<a href="mailto:howard.hinnant_at_[hidden]">Howard Hinnant</a><br>
+
+2011-05-11
+</address>
+<hr>
+<h1 align=center><code>chrono::date</code></h1>
+
+<!--
+<h2>Introduction</h2>
+-->
+<h2>Introduction</h2>
+
+<p>
+The subject of this paper is a date class which has been strongly influenced by
+<code>boost::date</code>, but is not proposing exactly what is currently
+<code>boost::date</code>. What is proposed herein is a relatively small
+library. The implementation is currently composed of 3 different performance
+designs, all conforming to a single specification, and the total number of
+semicolons in the union of all three designs is only 694. Suffice it to say
+that we are talking about 600 lines of C++ code, not 6000 or 60,000 lines of C++
+code. The API proposed herein is correspondingly small, and yet powerful enough
+to enable the client to express everything needed in this area.
+</p>
+
+<p>
+The example implementation can be found in <a
+href="date"><code>&lt;date&gt;</code></a> and <a
+href="date.cpp"><code>date.cpp</code></a>.
+</p>
+
+<p>
+The <code>boost::date</code> API is considerably larger. Additionally the
+<code>boost::date</code> API allows for a few situations which can be visually
+ambiguous. For example, here is an example using boost with the intent of
+forming January 2, 2011:
+</p>
+
+<blockquote><pre>
+#include "boost/date_time/gregorian/gregorian.hpp"
+#include &lt;iostream&gt;
+
+int main()
+{
+ using namespace boost::gregorian;
+ <font color="#C80000">// I'm from the US and am used to month/day/year</font>
+ std::cout &lt;&lt; date(1, 2, 2011) &lt;&lt; '\n';
+}
+</pre></blockquote>
+
+<p>
+The above results in a run time error because the <code>boost::date</code>
+constructor expects the order of arguments to be year, month, day. This
+proposal allows the entry of day, month and year to vary. Additionally the first
+two entries must be a type that unambiguously gives the units (day,
+month or year). For example:
+</p>
+
+<blockquote><pre>
+std::cout &lt;&lt; month(1)/day(2)/2011 &lt;&lt; '\n'; <font color="#C80000">// 2011-01-02</font>
+</pre></blockquote>
+
+<p>
+If you prefer the year/month/day order, that is just as easily accomplished:
+</p>
+
+<blockquote><pre>
+std::cout &lt;&lt; year(2011)/month(1)/2 &lt;&lt; '\n'; <font color="#C80000">// 2011-01-02</font>
+</pre></blockquote>
+
+<p>
+This library is placed in namespace <code>std::chrono</code>. This is just
+another time-keeping library, but it counts sunrises instead of seconds. And it
+interoperates with the existing <code>chrono</code> library.
+</p>
+
+<!--
+<h2><code>date</code> Construction</h2>
+-->
+<h2><code>date</code> Construction</h2>
+
+<p>
+Significant effort has been put into designing a library that makes it easy to
+correctly construct a date, and unlikely to construct an invalid or unexpected
+date.
+</p>
+
+<p>
+In all a <code>chrono::date</code> can be entered with three variations of the
+order of years, months and days. The first two units must be specified, and
+disambiguates which order you are using. Use of explicit units for the third
+unit is optional. These three orders were chosen out of the six possible orders
+because these are the only orders that people actually use worldwide.
+</p>
+
+<blockquote><pre>
+int m, d, y;
+<font color="#C80000">// give values to m, d and y ...</font>
+date d1 = year(y) / month(m) / day(d); <font color="#C80000">// ymd ok</font>
+date d2 = month(m) / day(d) / year(y); <font color="#C80000">// mdy ok</font>
+date d3 = day(d) / month(m) / year(y); <font color="#C80000">// dmy ok</font>
+</pre></blockquote>
+
+<p>
+The other three orderings of <code>year</code>, <code>month</code>, and
+<code>day</code> are rejected <b>at compile time.</b>
+</p>
+
+<blockquote><pre>
+int m, d, y;
+<font color="#C80000">// give values to m, d and y ...</font>
+date d1 = year(y) / day(d) / month(m); <font color="#C80000">// error: use of overloaded operator '/' is ambiguous</font>
+date d2 = month(m) / year(y) / day(d); <font color="#C80000">// error: invalid operands to operator '/'</font>
+date d3 = day(d) / year(y) / month(m); <font color="#C80000">// error: invalid operands to operator '/'</font>
+</pre></blockquote>
+
+<p>
+The rationale for this is that there exists <a
+href="http://en.wikipedia.org/wiki/Date_format_by_country">no country on the
+planet</a> which uses any other ordering. This is in contradiction to
+[locale.time.get] which specifies the above three orderings plus a
+<code>ydm</code> ordering. There is no inconsistency in not offering a
+<code>year/day/month</code> ordering. No current code will be invalidated. This
+is simply a lack of support for the <code>ydm</code> ordering.
+</p>
+
+<p>
+Furthermore, there exists <code>const</code> objects of type <tt>month</tt>
+named <code>jan</code>, <code>feb</code>, ... <code>dec</code>. These can be
+used exactly as <tt>month(m)</tt> is used:
+</p>
+
+<blockquote><pre>
+date d1 = jan/day(2)/2011; <font color="#C80000">// jan/2/2011</font>
+date d2 = year(2011)/jan/2; <font color="#C80000">// jan/2/2011</font>
+date d3 = day(2)/jan/2011; <font color="#C80000">// jan/2/2011</font>
+</pre></blockquote>
+
+<p>
+This makes creating date literals very easy, not prone to error due to ordering
+issues, and unambiguous to read. Also in this proposal it is not possible to
+create an invalid date. As dates are constructed or modified by date
+arithmetic, range checking is done, and an exception (<code>bad_date</code>) is
+thrown if any field of the <code>date</code> goes out of range.
+</p>
+
+<p>
+Additionally there are const objects with the following names that can be used
+to specify the day of the month:
+</p>
+
+<blockquote><pre>
+_1st
+_2nd
+_3rd
+_4th
+_5th
+last
+</pre></blockquote>
+
+<p>
+Now you can write (for example):
+</p>
+
+<blockquote><pre>
+date d1 = jan/_2nd/2011; <font color="#C80000">// jan/2/2011</font>
+date d2 = year(2011)/jan/_2nd; <font color="#C80000">// jan/2/2011</font>
+date d3 = _2nd/jan/2011; <font color="#C80000">// jan/2/2011</font>
+</pre></blockquote>
+
+<p>
+Note the constant <code>last</code>. This provides a very easy way to specify
+the last day of the month:
+</p>
+
+<blockquote><pre>
+date d1 = last/jan/2011; <font color="#C80000">// jan/31/2011</font>
+</pre></blockquote>
+
+<p>
+Sometimes you don't know exactly which day of the month you want, but instead
+know what weekday of the month you want. For example Mother's Day is celebrated
+on the second Sunday in May in the US:
+</p>
+
+<blockquote><pre>
+date MothersDay = sun[2]/may/2011; <font color="#C80000">// may/8/2011</font>
+date MothersDay = sun[_2nd]/may/2011; <font color="#C80000">// may/8/2011</font>
+</pre></blockquote>
+
+<p>
+If you ask for a non-existent date (e.g. the fifth Friday of May in 2011) a
+<code>bad_date</code> exception will be thrown. If what you really want is the
+fifth Friday in May only if it exists, else the fourth Friday, you can use
+<code>last</code>.
+</p>
+
+<blockquote><pre>
+date d1 = fri[last]/may/2011; <font color="#C80000">// may/27/2011</font>
+</pre></blockquote>
+
+<p>
+If you want to find out how many Fridays there are in May 2011, it is easy to
+code with:
+</p>
+
+<blockquote><pre>
+int num_fri_in_may = (fri[last]/may/2011).day() > 28 ? 5 : 4; <font color="#C80000">// 4</font>
+</blockquote></pre>
+
+<p>
+If you don't know which day of the week you're looking for until run time, you
+can use <code>weekday</code> in the exact same was you use the const objects
+<code>sun</code> through <code>sat</code>:
+</p>
+
+<blockquote><pre>
+int wd = ...
+date d1 = weekday(wd)[_1st]/may/2011;
+</pre></blockquote>
+
+<p>
+Creating <code>date</code>s is safe, easy, intuitive, and efficient.
+</p>
+
+<!--
+<h2><code>date</code> Arithmetic</h2>
+-->
+<h2><code>date</code> Arithmetic</h2>
+
+<p>
+Date arithmetic is supported for the units of days, months and years. In the
+chrono calendar, the length of months and years is not a constant number of days.
+This complicates the meaning of arithmetic with months and years. This library
+takes a pragmatic approach to this problem which gives clients choices on how
+they want to perform the arithmetic.
+</p>
+
+<!--
+<h3>Year-oriented Arithmetic</h3>
+-->
+<h3>Year-oriented Arithmetic</h3>
+
+<p>
+For every day of the year but one, adding a year to the date has a straight
+forward meaning: it modifies the year of the date, but not the day of the month
+or month of the year. For example <code>oct/day(15)/2011 + years(1) ==
+oct/day(15)/2012</code>. But what about Feb. 29?
+</p>
+
+<p>
+The boost library addresses this issue by "snapping to the end of the month."
+That is Feb. 29, 2012 + 1 year is Feb. 28, 2013. And Feb. 28, 2011 + 1 year is
+Feb. 29, 2012. But consider this example: John's birthday is Feb. 28. And he
+wants to print out his birthday for the decade. Using boost this looks like:
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print Feb. 28 for each year in the decade</font>
+for (date d(2010, Feb, 28), e(2020, Feb, 28); d &lt;= e; d += years(1))
+ std::cout &lt;&lt; d &lt;&lt; '\n';
+
+2010-Feb-28
+2011-Feb-28
+2012-Feb-29
+2013-Feb-28
+2014-Feb-28
+2015-Feb-28
+2016-Feb-29
+2017-Feb-28
+2018-Feb-28
+2019-Feb-28
+</pre></blockquote>
+
+<p>
+Using the boost design, every leap year the output prints out Feb. 29
+instead of Feb. 28. But John wasn't born on Feb. 29! That isn't the behavior
+he wants. He finds this behavior surprising.
+</p>
+
+<p>
+This library prints out Feb. 28 for each year using the syntax below.
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print Feb. 28 for each year in the decade</font>
+for (date d = feb/day(28)/2010, e = feb/day(28)/2020; d != e; d += years(1))
+ std::cout << d << '\n';
+
+2010-02-28
+2011-02-28
+2012-02-28
+2013-02-28
+2014-02-28
+2015-02-28
+2016-02-28
+2017-02-28
+2018-02-28
+2019-02-28
+</pre></blockquote>
+
+<p>
+And if you add 1 year to <code>feb/day(29)/2012</code>, a <code>bad_date</code>
+exception is thrown because there is no <code>feb/day(29)/2013</code>. You get
+exactly the same result as if you had attempted to construct
+<code>feb/day(29)/2013</code> directly.
+</p>
+
+<p>
+But now Sue comes along, and she happens to have been born on Feb. 29. And she
+doesn't want to have to wait 4 years to celebrate her birthday. She decides
+that she wants to celebrate her birthday on the last day of Feb. every year.
+She can print out her birthdays just as easily as John did:
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print the last day in Feb. for each year in the decade</font>
+for (date d = feb/last/2010, e = feb/last/2020; d != e; d += years(1))
+ std::cout << d << '\n';
+
+2010-02-28
+2011-02-28
+2012-02-29
+2013-02-28
+2014-02-28
+2015-02-28
+2016-02-29
+2017-02-28
+2018-02-28
+2019-02-28
+</pre></blockquote>
+
+<p>
+When year-oriented arithmetic is applied to a date that has been constructed
+with <code>last</code>, the library knows that although <code>feb/last/2011 ==
+feb/day(28)/2011</code>, <code>feb/last/2011 + years(1) ==
+feb/day(29)/2012</code>. And the result of this computation behaves as if it had
+been constructed with <code>feb/last/2012</code>, not
+<code>feb/day(29)/2012</code>. Thus throughout the for-loop above, the variable
+<code>d</code> always represents the last day of Feb., no matter what the year
+is.
+</p>
+
+<p>
+So this library enables both desired behaviors (do not "snap-to" and "snap-to"),
+and also delivers results that are not surprising to the casual reader of the
+code. And the arithmetic is reversible. If you add a year to a date (and this
+results in a valid date), and then subtract a year from that result, then you
+<i>always</i> get back your original date. This is <b>not</b> true of the boost
+date library.
+</p>
+
+<blockquote><pre>
+void test(date d)
+{
+ <font color="#C80000">// This should never assert!</font>
+ assert(d + years(1) - years(1) == d);
+}
+</pre></blockquote>
+
+<p>
+For example, using boost, <code>test(date(2012, Feb, 28))</code> asserts.
+Indeed boost will fail this test for Feb. 28 of every leap year. But using this
+proposal, the above test never asserts. It will however throw a
+<code>bad_date</code> for <code>test(feb/day(29)/2012)</code> (because
+<code>feb/day(29)/2013</code> doesn't exist). But it passes for
+<code>test(feb/last/2012)</code>
+</p>
+
+<p>
+To complete the birthday example, Sam, like Sue, was born on Feb. 29. But unlike
+Sue, he wants to always celebrate his birthday on the day after Feb. 28. This
+is also easy to accomplish:
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print the day after Feb. 28 for each year in the decade</font>
+for (date d = feb/day(28)/2010, e = feb/day(28)/2020; d != e; d += years(1))
+ std::cout &lt;&lt; d + days(1) &lt;&lt; '\n';
+
+2010-03-01
+2011-03-01
+2012-02-29
+2013-03-01
+2014-03-01
+2015-03-01
+2016-02-29
+2017-03-01
+2018-03-01
+2019-03-01
+</pre></blockquote>
+
+<p>
+The implementation cost of this behavior is very inexpensive. It need not
+impact the <code>sizeof(date)</code> at all, no matter what strategy the
+vendor is using to store the <code>date</code>. The run time cost is minimal,
+involving simply checking a few bits of the representation to choose the exact
+arithmetic algorithm. These assertions are backed by an example implementation
+for each of the three obvious storage strategies:
+</p>
+
+<ol>
+<li>Store year, month, day, and a count of days since the epoch. (Storage space is 64 bits)</li>
+<li>Store year, month, and day. (Storage space is 32 bits)</li>
+<li>Store a count of days since the epoch. (Storage space is 32 bits)</li>
+</ol>
+
+<p>
+In each example implementation above, 6 bits of storage are used to store
+information such as: this date represents the last day of February. These
+6 bits do not participate in the date comparison operations. The remaining bits
+(58 or 26) are more than sufficient to store the indicated data.
+</p>
+
+<p>
+Each of the above example implementations support a range of
+<code>year(numeric_limits&lt;short&gt;::min())/jan/1</code> through
+<code>year(numeric_limits&lt;short&gt;::max())/dec/31</code> inclusive (range
+governed by representing the year by a <code>short</code>). Thus this is a
+<a href="http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar">proleptic
+Gregorian calendar</a>. The year preceding year 1 is year 0, and year 0 is a
+leap year. This is consistent with the definition of an <i>expanded
+calendar</i> given in ISO 8601:2004: <i>Data elements and interchange formats
+&mdash; Information interchange &mdash; Representation of dates and times</i>.
+</p>
+
+<!--
+<h3>Month-oriented Arithmetic</h3>
+ -->
+<h3>Month-oriented Arithmetic</h3>
+
+<p>
+One can add and subtract <code>months</code> to a <code>date</code> with the
+same ease and semantics as is done with <code>years</code>. For example you can
+add a month to <code>jul/day(31)/2011</code> which results in
+<code>aug/day(31)/2011</code>. But if you add a month to
+<code>aug/day(31)/2011</code> a <code>bad_date</code> is thrown since
+<code>sep/day(31)/2011</code> does not exist. However you can <i>always</i> add
+a month to the <code>_1st</code> day of the month, or to <i>any</i> day of the
+month &lt;= 28, or to the <code>last</code> day of the month. For example:
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print last day of every month in 2011</font>
+for (date d = jan/last/2011, e = dec/last/2011; d &lt;= e; d += months(1))
+ std::cout &lt;&lt; d &lt;&lt; '\n';
+
+2011-01-31
+2011-02-28
+2011-03-31
+2011-04-30
+2011-05-31
+2011-06-30
+2011-07-31
+2011-08-31
+2011-09-30
+2011-10-31
+2011-11-30
+2011-12-31
+
+<font color="#C80000">// Print the 28th of every month in 2011</font>
+for (date d = jan/day(28)/2011, e = dec/day(28)/2011; d &lt;= e; d += months(1))
+ std::cout &lt;&lt; d &lt;&lt; '\n';
+
+2011-01-28
+2011-02-28
+2011-03-28
+2011-04-28
+2011-05-28
+2011-06-28
+2011-07-28
+2011-08-28
+2011-09-28
+2011-10-28
+2011-11-28
+2011-12-28
+</pre></blockquote>
+
+<p>
+It is also easy to print out the 29th of every month. However one needs to
+explicitly decide what you want to do for months with less than 29 days. One
+obvious choice is to simply skip such months:
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print the 29th of every month in 2011</font>
+for (date d = last/jan/2011, e = last/dec/2011; d &lt;= e; d += months(1))
+ if (d.day() &gt;= 29)
+ std::cout &lt;&lt; d.year()/d.month()/29 &lt;&lt; '\n';
+
+2011-01-29
+2011-03-29
+2011-04-29
+2011-05-29
+2011-06-29
+2011-07-29
+2011-08-29
+2011-09-29
+2011-10-29
+2011-11-29
+2011-12-29
+</pre></blockquote>
+
+<p>
+Year and month-oriented arithmetic also respects nth-day-of-the-week dates.
+For example if you want to print out the 2nd Tuesday of every odd month that
+is easily done with:
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print the 2nd Tuesday of every odd month in 2011</font>
+for (date d = tue[2]/jan/2011, e = dec/day(31)/2011; d &lt;= e; d += months(2))
+ std::cout &lt;&lt; d &lt;&lt; '\n';
+
+2011-01-11
+2011-03-08
+2011-05-10
+2011-07-12
+2011-09-13
+2011-11-08
+</pre></blockquote>
+
+<p>
+This final example should be emphasized. Imagine you've just met an extended
+family at a restaurant, one whom you have not met before. They're celebrating.
+There's children, parents and grandparents present. They enjoy your company so
+much they invite you back for the same celebration, same place, "next year." You
+check the current date and it is May 8, 2011.
+</p>
+
+<p>
+On what date should you plan to attend? If they were celebrating a birthday,
+then you should come back on May 8, 2012. But if they were celebrating Mother's
+Day then you should come back on May 13, 2012 (the second Sunday of May in 2012)
+&mdash; five whole days later!
+</p>
+
+<blockquote><i>
+Adding a year (or a month) to a date is intrinsically context sensitive.
+</i></blockquote>
+
+<p>
+The expressions <code>d + years(1)</code> and <code>d + months(1)</code> are
+only unambiguous when you know the context within which <code>d</code> was
+constructed. This library stores that context as part of <code>d</code>'s
+state.
+</p>
+
+<h3>Day-oriented Arithmetic</h3>
+
+<p>
+Day-oriented arithmetic is intrinsically less complicated than month and
+year-oriented arithmetic. The chrono calendar is nothing but a count of
+sunrises, and a distinct name for each sunrise. You can add any number of
+<code>days</code> to any <code>date</code> and the result is <i>always</i> a
+valid date (unless one exceeds the valid range for years). For example:
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// Print out every monday between jan/1/2011 and mar/1/2011;</font>
+for (date d = mon[_1st]/jan/2011, e = mar/_1st/2011; d &lt;= e; d += days(7))
+ std::cout &lt;&lt; d &lt;&lt; '\n';
+
+2011-01-03
+2011-01-10
+2011-01-17
+2011-01-24
+2011-01-31
+2011-02-07
+2011-02-14
+2011-02-21
+2011-02-28
+</pre></blockquote>
+
+<p>
+In the above example, the first Monday of the year is found, and then to get
+each Monday after that, one simply adds 7 days. There is <i>always</i> another
+Monday coming up!
+</p>
+
+<p>
+Additionally, if you subtract two dates, the result is a
+<code>chrono::duration</code> with the name <code>days</code>.
+</p>
+
+<blockquote><pre>
+<font color="#C80000">// How many days between may/1/2011 and jan/1/2011?</font>
+int x = (may/_1st/2011 - jan/_1st/2011).count(); <font color="#C80000">// x == 120</font>
+</pre></blockquote>
+
+<p>
+<i>Question:</i> So what happens when you subtract a day from
+<code>aug/last/2011</code> and then add a day back? The resultant day will be
+equal to <code>aug/day(31)/2011</code>. But will it still represent the last day
+of the month as far as month and year arithmetic is concerned?
+</p>
+
+<p>
+<i>Answer:</i> No. <code>date</code>s tagged with "last" information become
+untagged with that information as soon as they have <code>days</code> added to
+or subtracted from them. So while <code>aug/last/2011 + months(1)</code> is
+equal to <code>sep/day(30)/2011</code>, <code>aug/last/2011 - days(1) + days(1)
++ months(1)</code> results in a <code>bad_date</code> exception because
+<code>sep/day(31)/2011</code> does not exist. This is the same behavior you
+would get if you added <code>months(1)</code> to <code>aug/day(31)/2011</code>.
+</p>
+
+<h2><code>date</code> Observers</h2>
+
+<p>
+Given a date <code>d</code> you can ask for its <tt>day()</tt>, <tt>month()</tt>
+and <tt>year()</tt>. These each return a <tt>day</tt>, <tt>month</tt> and
+<tt>year</tt> respectively. Note that these returned types are not the
+<i>durations</i> <tt>days</tt>, <tt>months</tt> and <tt>years</tt>. Rather they
+are the <i>unit-specifiers</i> used to specify a day, month and year which you
+used to construct the <code>date</code>. Each unit-specifier is implicitly
+convertible to an <code>int</code>. Example uses:
+</p>
+
+<blockquote><pre>
+date dt = aug/day(16)/2011;
+int d = dt.day(); <font color="#C80000">// d == 16</font>
+int m = dt.month(); <font color="#C80000">// m == 8</font>
+int y = dt.year(); <font color="#C80000">// y == 2011</font>
+</pre></blockquote>
+
+<p>
+And:
+</p>
+
+<blockquote><pre>
+date dt = aug/day(16)/2011;
+<font color="#C80000">// ...</font>
+<font color="#C80000">// Create date with the same month and year but on the 5th</font>
+date dt2 = dt.year()/dt.month()/5; <font color="#C80000">// aug/5/2011</font>
+</pre></blockquote>
+
+<p>
+Note that in the latter example if <code>year()</code> returned a simple
+<code>int</code> instead of a <code>year</code> then the construction of
+<code>dt2</code> would start with an <code>int</code> instead of a
+<code>year</code> and thus not be a well-formed <code>date</code>.
+</p>
+
+<p>
+To get the <tt>weekday</tt> (day of the week) of a date use the
+<code>weekday()</code> member function. This returns a <tt>weekday</tt> type
+which is implicitly convertible to <code>int</code>. One can use this to
+print out an <code>int</code> which represents the day of the week:
+</p>
+
+<blockquote><pre>
+date dt = aug/day(16)/2011;
+<font color="#C80000">// What day of the week is this?</font>
+int wd = dt.weekday(); <font color="#C80000">// 2 (Tuesday)</font>
+</pre></blockquote>
+
+<p>
+Or one can find the first same weekday of the month of the following year:
+</p>
+
+<blockquote><pre>
+date dt = aug/day(16)/2011;
+<font color="#C80000">// ...</font>
+<font color="#C80000">// Get the date that is the first occurrence of the same day of the week</font>
+<font color="#C80000">// in the same month of the next year</font>
+date dt2 = dt.weekday()[_1st]/dt.month()/(dt.year() + 1); <font color="#C80000">// aug/7/2012, first Tuesday of Aug 2012</font>
+</pre></blockquote>
+
+<p>
+<i>This syntax <b>has</b> power.</i> There are nearly infinitely many
+applications for a date class which we can not imagine. This library creates a
+small, simple, efficient and consistent language of dates and date arithmetic
+which is widely applicable to all of the date applications which we have yet to
+imagine. And because the API for this library is small, it is easy to teach,
+and easy to learn.
+</p>
+
+<h2>Finding the next or previous <code>weekday</code></h2>
+
+<p>
+Sometimes, given a date, one needs to find the previous Monday, or the following
+Sunday. For example the ISO week-based year starts on the Monday that falls on
+or before Jan 4 of each year. With this library you can code that date for
+year <code>y</code> as:
+</p>
+
+<blockquote><pre>
+date ISO_week_start = mon &lt;= jan/day(4)/y;
+</pre></blockquote>
+
+<p>
+That is, the expression <code>wd &lt;= x</code> returns the <code>date y</code>
+such that <code>y</code> is the first <code>date</code> equal to or prior to
+<code>x</code> such that <code>y.weekday() == wd</code>. There are four such
+operations summarized here. Let <code>wd</code> be a <code>weekday</code>
+expression and <code>d</code> be a <code>date</code> expression:
+</p>
+
+<blockquote>
+<table border="1" cellpadding="5">
+<tr>
+<td><code>wd &lt; d</code></td>
+<td>Returns the first <code>date</code> prior to <code>d</code> that has
+<code>wd</code> as its <code>weekday</code>.</td>
+</tr>
+<tr>
+<td><code>wd &lt;= d</code></td>
+<td>Returns the first <code>date</code> on or prior to <code>d</code> that has
+<code>wd</code> as its <code>weekday</code>.</td>
+</tr>
+<td><code>wd &gt; d</code></td>
+<td>Returns the first <code>date</code> after <code>d</code> that has
+<code>wd</code> as its <code>weekday</code>.</td>
+</tr>
+<td><code>wd &gt;= d</code></td>
+<td>Returns the first <code>date</code> on or after <code>d</code> that has
+<code>wd</code> as its <code>weekday</code>.</td>
+</tr>
+</table>
+</blockquote>
+
+<h2><code>date</code> I/O</h2>
+
+<p>
+<code>date</code>s are obviously streamable. The default formatting is
+consistent with ISO 8601: yyyy-mm-dd, as has been alluded to in previous
+examples. Additionally there is a <code>datepunct facet</code> and a
+<code>date_fmt</code> manipulator. These are basically C++ wrappers around C's
+<code>strftime</code>. And they also serve as wrappers around the
+non-standard-but-popular <code>strptime</code> for parsing <code>date</code>s
+from an <code>istream</code>.
+</p>
+
+<p>
+To demonstrate the ease with which <code>date</code>s can be formatted, I'm
+taking a real-world example from my wife: She once set up a recurring meeting
+for the odd Fridays of every month. That is, they met on the first, third, and
+if it existed, the fifth Friday of every month. When I asked her why, she said:
+"Every week was too often, and every other week wasn't often enough."
+&lt;shrug&gt;
+</p>
+
+<p>
+Here is how you print out the odd Fridays of every month in 2011, using
+<code>date_fmt</code> to format the <code>date</code> however you want:
+</p>
+
+<blockquote><pre>
+std::cout &lt;&lt; date_fmt("%a %b %e, %Y");
+<font color="#C80000">// Print the odd fridays of every month in 2011</font>
+for (date d = fri[_1st]/jan/2011, e = dec/last/2011; d &lt;= e; d += months(1))
+{
+ std::cout &lt;&lt; d &lt;&lt; '\n'; <font color="#C80000">// first Friday of the month</font>
+ std::cout &lt;&lt; d + days(14) &lt;&lt; '\n'; <font color="#C80000">// third Friday of the month</font>
+ date last_fri = fri[last]/d.month()/d.year();
+ if (last_fri.day() &gt;= 29)
+ std::cout &lt;&lt; last_fri &lt;&lt; '\n'; <font color="#C80000">// fifth Friday of the month if it exists</font>
+}
+
+Fri Jan 7, 2011
+Fri Jan 21, 2011
+Fri Feb 4, 2011
+Fri Feb 18, 2011
+Fri Mar 4, 2011
+Fri Mar 18, 2011
+Fri Apr 1, 2011
+Fri Apr 15, 2011
+Fri Apr 29, 2011
+Fri May 6, 2011
+Fri May 20, 2011
+Fri Jun 3, 2011
+Fri Jun 17, 2011
+Fri Jul 1, 2011
+Fri Jul 15, 2011
+Fri Jul 29, 2011
+Fri Aug 5, 2011
+Fri Aug 19, 2011
+Fri Sep 2, 2011
+Fri Sep 16, 2011
+Fri Sep 30, 2011
+Fri Oct 7, 2011
+Fri Oct 21, 2011
+Fri Nov 4, 2011
+Fri Nov 18, 2011
+Fri Dec 2, 2011
+Fri Dec 16, 2011
+Fri Dec 30, 2011
+</pre></blockquote>
+
+<h2>Interoperability with other calendar systems</h2>
+
+<p>
+There are other calendar systems besides the <code>chrono</code> (Gregorian)
+calendar. For example just to name a few:
+</p>
+
+<ul>
+<li>Islamic calendar</li>
+<li>Hebrew calendar</li>
+<li>Hindu calendar</li>
+<li>Chinese calendar</li>
+<li>Buddhist calendar</li>
+<li>Julian calendar</li>
+</ul>
+
+<p>
+This paper proposes only the
+Gregorian calendar
+because this represents existing practice for C, C++, POSIX, and ISO 8601.
+However one has to wonder: shouldn't we design a framework which can support
+any of the world's calendars?
+</p>
+
+<p>
+I claim that such a general framework is unnecessary, and we would likely get it
+wrong. The reason it is unnecessary is that clients can easily write their own
+calendars which convert to and from the <code>chrono</code> calendar using only
+the public API proposed herein. Their calendar may or may not use an API
+similar to the <code>chrono</code> API. Aside from the Julian calendar, the
+I/O facets <code>time_get</code>, <code>time_put</code>, and
+<code>datepunct</code> are not reusable by these other calendars. Indeed,
+there is very little opportunity for code reuse by making a "calendar
+framework".
+</p>
+
+<p>
+To demonstrate, I coded a Julian calendar which converts to and from the
+<code>chrono</code> calendar (using no knowledge whatsoever of the implementation
+of <code>chrono</code>). This calendar is <em>not</em> proposed but shown here
+only for demonstration purposes.
+</p>
+
+<ul>
+<li>julian.h</li>
+<li>julian.cpp</li>
+</ul>
+
+<p>
+And here is example use showing how the two calendars can be converted to one
+another:
+</p>
+
+<blockquote><pre>
+#include &lt;iostream&gt;
+#include "date"
+#include "julian.h"
+
+int main()
+{
+ std::cout &lt;&lt; std::chrono::date_fmt("%a %b %e, %Y");
+ std::chrono::date cd = std::chrono::date::today();
+ <b>julian::date jd(cd);</b>
+ std::cout &lt;&lt; "Today is:\n"
+ &lt;&lt; cd &lt;&lt; " in the std::chrono calendar and\n"
+ &lt;&lt; jd &lt;&lt; " in the Julian calendar\n";
+ jd -= julian::years(1800);
+ <b>cd = std::chrono::date(jd);</b>
+ std::cout &lt;&lt; "1800 years ago the two calendars were aligned:\n"
+ &lt;&lt; cd &lt;&lt; " in the std::chrono calendar and\n"
+ &lt;&lt; jd &lt;&lt; " in the Julian calendar\n";
+}
+
+Today is:
+Fri May 6, 2011 in the std::chrono calendar and
+Fri Apr 23, 2011 in the Julian calendar
+1800 years ago the two calendars were aligned:
+Tue Apr 23, 0211 in the std::chrono calendar and
+Tue Apr 23, 0211 in the Julian calendar
+</pre></blockquote>
+
+<p>
+I firmly believe that any other calendar can be converted to and from the
+<code>chrono</code> calendar using the techniques shown here for the Julian
+calendar, and that we need to do nothing to enable clients to do so. Furthermore
+actually providing these other calendars is far outside of our scope.
+</p>
+
+<h2>A non-trivial example</h2>
+
+<p>
+There's nothing like real-world use to test an interface. This is when you
+find out if using a given API is like flying with the wind, or wading through
+waist-deep water. In this spirit we would like to present two <i>user-written</i>
+functions drawn from real-world usage. These two functions are not proposed,
+though they certainly could be.
+</p>
+
+<blockquote><pre>
+std::tuple&lt;int, std::chrono::weekday, std::chrono::year&gt;
+ date_to_week(std::chrono::date d)
+std::chrono::date
+ week_to_date(int weeknum, std::chrono::weekday wd, std::chrono::year y);
+</pre></blockquote>
+
+<p>
+These functions convert a <code>std::chrono::date</code> to and from the ISO
+8601 week-based year format. The rules for this format are:
+</p>
+
+<ol>
+<li>The week starts with Monday, and ends with Sunday.</li>
+<li>The first day of the year is the Monday that occurs on or before Jan. 4.</li>
+<li>A date is specified by the week number [1 - 53], day of the week [Mon - Sun]
+and year number.</li>
+<li>The year number is the same as the Gregorian year number for the Thursday
+that follows the start of the week-based year.</li>
+<ul>
+<li>This makes it possible for a day in the week-based year to have a different
+year number than in the Gregorian calendar for that day.</li>
+</ul>
+</ol>
+
+<p>
+ISO 8601 gives two examples:
+</p>
+
+<ol>
+<li>Sunday Jan. 1, 1995 is the Sunday of week 52 of the year 1994.
+(Week 1 of 1995 starts on Monday Jan. 2, 1995)</li>
+<li>Tuesday Dec. 31, 1996 is the Tuesday of week 1 of the year 1997. (The
+first day of the week-based year 1997 begins on Monday Dec. 30, which is the
+first Monday on or before Jan. 4, 1997, a Saturday)</li>
+</ol>
+
+<p>
+These rules seem complex. And yet the code using <code>std::chrono::date</code>
+to convert to and from the week-based year is remarkably compact and
+self-explanatory. First we present <code>date_to_week</code>, which returns a
+triple: week number, day of the week, and week-based year number:
+</p>
+
+<blockquote><pre>
+std::tuple&lt;int, std::chrono::weekday, std::chrono::year&gt;
+date_to_week(std::chrono::date d)
+{
+ using namespace std::chrono;
+ month_day jan4 = jan/_4th;
+ date start = mon &lt;= jan4/d.year();
+ if (d &lt; start)
+ start = mon &lt;= jan4/(d.year()-1);
+ else
+ {
+ date next_start = mon &lt;= jan4/(start.year()+1);
+ if (d &gt;= next_start)
+ start = next_start;
+ }
+ return std::tuple&lt;int, weekday, year&gt;((d - start).count()/7 + 1,
+ d.weekday(),
+ (thu &gt; start).year());
+}
+</pre></blockquote>
+
+<p>
+The first line of code creates a "shortcut" for Jan. 4. This isn't necessary.
+It is used here to demonstrate the use of the <code>month_day</code> object. We
+could just have easily written <code>jan/_4th/d.year()</code> instead of
+<code>jan4/d.year()</code> (for example). Use of <code>jan4</code> is purely a
+stylistic issue and has negligible performance impact.
+</p>
+
+<p>
+The start of the ISO year is stored in <code>start</code> and is found by
+identifying the Monday on or before Jan. 4. If <code>d</code> falls before the
+start of the year we just computed, then <code>d</code> must be in the previous
+ISO year, and so <code>start</code> is recomputed. Else we need to make sure
+that <code>d</code> does not lie beyond the current ISO year. We compute the
+start of the next ISO year to check for that, and if necessary, set
+<code>start</code> to the next ISO year.
+</p>
+
+<p>
+Now we have the start of the ISO year which contains <code>d</code>. It is now
+a simple process to compute the week number and year number for <code>d</code>
+which are returned in a <code>tuple</code>. Care is taken for the fact that
+weeks are numbered starting from 1, not 0. And the year number is that of the
+Thursday following the start of the ISO year. The day of the week remains
+unchanged from <code>d</code>'s.
+</p>
+
+<p>
+The reverse conversion, <code>week_to_date</code> is even simpler:
+</p>
+
+<blockquote><pre>
+std::chrono::date
+week_to_date(int weeknum, std::chrono::weekday wd, std::chrono::year y)
+{
+ using namespace std::chrono;
+ return (mon <= jan/_4th/y) + days((weeknum - 1)*7 + (wd == 0 ? 6 : wd - 1));
+}
+</pre></blockquote>
+
+<ol>
+<li>
+Compute the start of the week-based year <code>y</code>.
+</li>
+<li>
+Add to the start <code>date</code> 7 <code>days</code> for each full week,
+taking into account that the week numbers start at 1, not 0.
+</li>
+<li>
+Add to that the number of days <code>wd</code> is past Monday. Note that
+Sunday is 6 days past Monday, not one day before it.
+</li>
+</ol>
+
+<p>
+These functions can now be used as:
+</p>
+
+<blockquote><pre>
+date d = /* ... */
+int weeknum;
+weekday wd(0);
+year y(0);
+std::tie(weeknum, wd, y) = date_to_week(d);
+</pre></blockquote>
+
+<p>
+and
+</p>
+
+<blockquote><pre>
+d = week_to_date(weeknum, wd, y);
+</pre></blockquote>
+
+<p>Notes:</p>
+
+<ul>
+<li>
+This code is <em>readable</em>.
+</li>
+<li>
+The syntax for finding the Monday on or before a previous date is succinct.
+</li>
+<li>
+The syntax for finding the Thursday after a date is succinct. In this example
+<code>start + days(3)</code> could have been used in place of <code>thu &gt;
+start</code>. But the ISO rules are worded in terms of Thursday, and this
+library provides a natural translation from English to C++.
+</li>
+<li>
+The implicit conversion from the unit specifiers <code>year</code> and
+<code>weekday</code> to <code>int</code> is helpful, intuitive and safe in
+this example code. These conversions are so natural that they are not even noticed
+unless you're looking for them.
+</li>
+<li>
+The arguments to the functions are type-safe. If the client gets the order
+of the arguments wrong, a compile-time error will result. This is easily
+achievable by the author of these functions because the same type-safety
+exists in the <code>&lt;date&gt;</code> library.
+</li>
+<li>
+The reasons for not proposing these functions include:
+<ul>
+<li>They are easy to write using the public API of this proposal.</li>
+<li>The best precise syntax for these functions is unclear: Should
+<code>date_to_week</code> return a <code>tuple</code>? Should
+<code>week_to_date</code> take a <code>tuple</code>? Are these the best names
+for these functions? etc.</li>
+<li>Should this functionality exist instead as a separate calendar system (like
+the <code>julian</code> example?)</li>
+</ul>
+</li>
+</ul>
+
+<h2>Proposed Wording</h2>
+
+<blockquote class="note">
+Text formatted like this is intended to be rationale for some of the proposed
+wording. It is not part of the proposed wording.
+</blockquote>
+
+<h3>Date utilities</h3>
+
+<h4>In general</h4>
+
+<p>
+This subclause describes the chrono calendar library which provides date
+generation and date arithmetic facilities.
+</p>
+
+<h4> Header <code>&lt;date&gt;</code> synopsis</h4>
+
+<blockquote><pre>
+namespace std {
+namespace chrono {
+
+// error handling
+
+class bad_date;
+
+// Unit specifiers
+
+class day;
+class month;
+class year;
+class weekday;
+class year_month;
+class month_day;
+
+// Specifier constants
+
+extern const <i>see below</i> _1st;
+extern decltype(_1st) _2nd;
+extern decltype(_1st) _3rd;
+extern decltype(_1st) _4th;
+extern decltype(_1st) _5th;
+extern decltype(_1st) last;
+
+extern const month jan;
+extern const month feb;
+extern const month mar;
+extern const month apr;
+extern const month may;
+extern const month jun;
+extern const month jul;
+extern const month aug;
+extern const month sep;
+extern const month oct;
+extern const month nov;
+extern const month dec;
+
+extern const weekday sun;
+extern const weekday mon;
+extern const weekday tue;
+extern const weekday wed;
+extern const weekday thu;
+extern const weekday fri;
+extern const weekday sat;
+
+// Date generation functions
+
+month_day operator/(day, month) noexcept;
+month_day operator/(month, day) noexcept;
+
+year_month operator/(year, month) noexcept;
+
+date operator/(year_month, day);
+date operator/(month_day, year);
+date operator/(year_month, int);
+date operator/(month_day, int);
+
+// Durations
+
+typedef duration&lt;int_least32_t, ratio&lt;86400&gt;&gt; days;
+
+class months;
+
+// months arithmetic
+
+months operator+(months x, months y) noexcept;
+months operator-(months x, months y) noexcept;
+months operator*(months x, months::rep y) noexcept;
+months operator*(months::rep x, months y) noexcept;
+months operator/(months x, months::rep y) noexcept;
+months::rep operator/(months x, months y) noexcept;
+months operator%(months x, months::rep y) noexcept;
+months operator%(months x, months y) noexcept;
+
+// months comparisons
+
+bool operator==(months x, months y) noexcept;
+bool operator!=(months x, months y) noexcept;
+bool operator&lt; (months x, months y) noexcept;
+bool operator&gt; (months x, months y) noexcept;
+bool operator&lt;=(months x, months y) noexcept;
+bool operator&gt;=(months x, months y) noexcept;
+
+class years;
+
+// years arithmetic
+
+years operator+(years x, years y) noexcept;
+years operator-(years x, years y) noexcept;
+years operator*(years x, years::rep y) noexcept;
+years operator*(years::rep x, years y) noexcept;
+years operator/(years x, years::rep y) noexcept;
+years::rep operator/(years x, years y) noexcept;
+years operator%(years x, years::rep y) noexcept;
+years operator%(years x, years y) noexcept;
+
+// years comparisons
+
+bool operator==(years x, years y) noexcept;
+bool operator!=(years x, years y) noexcept;
+bool operator&lt; (years x, years y) noexcept;
+bool operator&gt; (years x, years y) noexcept;
+bool operator&lt;=(years x, years y) noexcept;
+bool operator&gt;=(years x, years y) noexcept;
+
+// date
+
+class date;
+
+// date comparisons
+
+bool operator==(const date&amp; x, const date&amp; y) noexcept;
+bool operator!=(const date&amp; x, const date&amp; y) noexcept;
+bool operator&lt; (const date&amp; x, const date&amp; y) noexcept;
+bool operator&gt; (const date&amp; x, const date&amp; y) noexcept;
+bool operator&lt;=(const date&amp; x, const date&amp; y) noexcept;
+bool operator&gt;=(const date&amp; x, const date&amp; y) noexcept;
+
+// date day arithmetic
+date operator+(date dt, days d);
+date operator+(days d, date dt);
+date operator-(date dt, days d);
+days operator-(date x, date y) noexcept;
+
+// date month arithmetic
+date operator+(date dt, months m);
+date operator+(months m, date dt);
+date operator-(date dt, months m);
+
+// date year arithmetic
+date operator+(date dt, years y);
+date operator+(years y, date dt);
+date operator-(date dt, years y);
+
+// find prior / next weekday
+date operator&lt; (weekday wd, date x);
+date operator&lt;=(weekday wd, date x);
+date operator&gt; (weekday wd, date x);
+date operator&gt;=(weekday wd, date x);
+
+// date I/O
+
+template &lt;class charT&gt; class datepunct;
+
+template&lt;class charT&gt;
+<i>unspecified</i>
+date_fmt(basic_string&lt;charT&gt; fmt);
+
+template&lt;class charT&gt;
+<i>unspecified</i>
+date_fmt(const charT* fmt);
+
+template&lt;class charT, class Traits&gt;
+basic_istream&lt;charT,Traits&gt;&amp;
+operator&gt;&gt;(basic_istream&lt;charT,Traits&gt;&amp; is, date&amp; d);
+
+template&lt;class charT, class Traits&gt;
+basic_ostream&lt;charT, Traits&gt;&amp;
+operator&lt;&lt;(basic_ostream&lt;charT, Traits&gt;&amp; os, const date&amp; d);
+
+} // namespace chrono
+} // namespace std
+
+</pre></blockquote>
+
+<h4>Class <code>bad_date</code></h4>
+
+<pre>
+namespace std {
+namespace chrono {
+ class bad_date
+ : public runtime_error
+{
+ public:
+ explicit bad_date(const string&amp; s);
+ explicit bad_date(const char* s);
+ };
+}
+}
+</pre>
+
+<p>
+The class <code>bad_date</code> is thrown when an exceptional condition is
+created within the <code>chrono</code> library.
+</p>
+
+<pre>
+bad_date(const string&amp; s);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs an object of class <code>bad_date</code>.
+</p>
+<p>
+<i>Postcondition:</i> <code>what() == s</code>.
+</p>
+</blockquote>
+
+<pre>
+bad_date(const char* s);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs an object of class <code>bad_date</code>.
+</p>
+<p>
+<i>Postcondition:</i> <code>strcmp(what(), s) == 0</code>.
+</p>
+</blockquote>
+
+<h4>Unit specifiers</h4>
+
+<p>
+The classes defined in this section represent the different components of a
+date and when properly combined represent a date.
+</p>
+
+<blockquote class="note">
+<p>
+Each unit specifier is implicitly convertible to <code>int</code>. This
+conversion is implicit because an explicit conversion would require an
+excessively clumsy synax for some common use cases. For example:
+</p>
+
+<blockquote><pre>
+date d1 = ...;
+date d2 = d1.weekday()[_1st] / d1.month() / (d1.year() + 1);
+</pre></blockquote>
+
+<p>vs</p>
+
+<blockquote><pre>
+date d2 = d1.weekday()[_1st] / d1.month() / (static_cast&lt;int&gt;(d1.year()) + 1);
+</pre></blockquote>
+
+<p>
+It would also not be appropriate to create arithmetic for the unit specifiers.
+This would blur the distinction between date unit specifiers and date durations.
+</p>
+
+<p>
+The simple fact is that people specify days, months and years using integers
+just as often (if not more so) than using words. This library strives to make
+the syntax as natural as possible without sacrificing type safety. The implicit
+conversion from unit specifier to int (but not vice-versa) does not compromise
+this type safety.
+</p>
+
+</blockquote>
+
+<h5>Class <code>day</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class day
+ {
+ public:
+ explicit day(int d);
+ day(decltype(_1st) d) noexcept;
+ operator int() const noexcept;
+
+ day() = delete;
+ day(const day&amp;) = default;
+ day&amp; operator=(const day&amp;) = default;
+ ~day() = default;
+ };
+
+ extern const <i>see below</i> _1st;
+ extern decltype(_1st) _2nd;
+ extern decltype(_1st) _3rd;
+ extern decltype(_1st) _4th;
+ extern decltype(_1st) _5th;
+ extern decltype(_1st) last;
+}
+}
+</pre>
+
+<p>
+The class <code>day</code> is used to specify the day of the month when
+constructing a <code>date</code>. It is capable of storing the day number of
+any month, a day of the week (Sunday thru Saturday), and a small integral value
+that indicates which weekday of a month the day represents (example: 2nd
+Sunday).
+</p>
+
+<pre>
+explicit day(int d);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs an object of class <code>day</code> by storing
+<code>d</code>.
+</p>
+
+<p>
+<i>Postconditions:</i> <code>static_cast&lt;int&gt;(*this) == d</code>
+</p>
+
+<p>
+<i>Throws:</i> if <code>d</code> is outside of the range [1, 31], throws an
+exception of type <code>bad_date</code>.
+</p>
+</blockquote>
+
+<pre>
+day(decltype(_1st) d) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs an object of class <code>day</code> by storing
+<code>d</code>.
+</p>
+
+<p>
+<i>Postconditions:</i> The value returned by casting <code>*this</code> to
+<code>int</code> depends on the value of <code>d</code> as follows:
+</p>
+
+<blockquote>
+<ul>
+<li><code>_1st</code>: returns <code>1</code>.</li>
+<li><code>_2nd</code>: returns <code>2</code>.</li>
+<li><code>_3rd</code>: returns <code>3</code>.</li>
+<li><code>_4th</code>: returns <code>4</code>.</li>
+<li><code>_5th</code>: returns <code>5</code>.</li>
+<li><code>last</code>: The value returned is unspecified. Other parts of the
+<code>chrono</code> library will need to recognize a <code>day</code> constructed
+with this value.</li>
+</ul>
+</blockquote>
+</blockquote>
+
+<pre>
+operator int() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> If <code>*this</code> has a value that resulted from
+constructing a <code>day</code> from an <code>int</code>, returns the value of
+that <code>int</code>. Otherwise the value returned is specified as above.
+</p>
+
+</blockquote>
+
+<p>
+The type of <code>_1st</code> is an unspecified class type except that it is in
+the same namespace as <code>day</code>, it is <code>CopyConstructible</code>,
+<code>CopyAssignable</code> and <code>Destructible</code>. It is not
+<code>DefaultConstructible</code>.
+</p>
+
+<h5>Class <code>month</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class month
+ {
+ public:
+ explicit month(int m);
+ operator int() const noexcept;
+
+ month() = delete;
+ month(const month&amp;) = default;
+ month&amp; operator=(const month&amp;) = default;
+ ~month() = default;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+}
+}
+</pre>
+
+<p>
+The class <code>month</code> is used to specify the month of the year when
+constructing a <code>date</code>.
+</p>
+
+<pre>
+explicit month(int m);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs an object of class <code>month</code> by storing
+<code>m</code>.
+</p>
+
+<p>
+<i>Postconditions:</i> <code>static_cast&lt;int&gt;(*this) == m</code>
+</p>
+
+<p>
+<i>Throws:</i> if <code>m</code> is outside of the range [1, 12], throws an
+exception of type <code>bad_date</code>.
+</p>
+</blockquote>
+
+<pre>
+operator int() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> the value of the stored <code>int</code>.
+</p>
+
+</blockquote>
+
+<p>
+These <code>const month</code> objects are constructed prior to first use with
+the following values:
+</p>
+
+<blockquote><pre>
+const month jan(1);
+const month feb(2);
+const month mar(3);
+const month apr(4);
+const month may(5);
+const month jun(6);
+const month jul(7);
+const month aug(8);
+const month sep(9);
+const month oct(10);
+const month nov(11);
+const month dec(12);
+</pre></blockquote>
+
+<h5>Class <code>year</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class year
+ {
+ public:
+ explicit year(<i>signed-integral-with-range-greater-than-the-range-of-year</i> y);
+ operator int() const noexcept;
+
+ year() = delete;
+ year(const year&amp;) = default;
+ year&amp; operator=(const year&amp;) = default;
+ ~year() = default;
+ };
+}
+}
+</pre>
+
+<p>
+The class <code>year</code> is used to specify the year when constructing a
+<code>date</code>. It also defines the range of the <code>date</code> class by
+restricting the value of the <code>year</code> to a range. That range shall be
+at least <code>[year(-32767)/jan/1</code> thru <code>year(32767)/dec/31]</code>.
+</p>
+
+<pre>
+explicit year(<i>signed-integral-with-range-greater-than-the-range-of-year</i> y);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs an object of class <code>year</code> by storing
+<code>y</code>.
+</p>
+
+<p>
+<i>Postconditions:</i> <code>static_cast&lt;int&gt;(*this) == y</code>
+</p>
+
+<p>
+<i>Throws:</i> if <code>y</code> is outside of the range, throws an exception of
+type <code>bad_date</code>.
+</p>
+</blockquote>
+
+<blockquote class="note">
+<p>
+In order for <code>year</code> to detect overflow, the integral type used to
+construct the <code>year</code> must have a range greater than that of
+<code>year</code>.
+</p>
+</blockquote>
+
+<pre>
+operator int() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> the value of the stored <code>int</code>.
+</p>
+
+</blockquote>
+
+<h5>Class <code>weekday</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class weekday
+ {
+ public:
+ explicit weekday(int wd);
+ operator int() const noexcept;
+
+ day operator[](decltype(_1st) d) const noexcept;
+ day operator[](int n) const;
+
+ weekday() = delete;
+ weekday(const weekday&amp;) = default;
+ weekday&amp; operator=(const weekday&amp;) = default;
+ ~weekday() = default;
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+}
+}
+</pre>
+
+<p>
+The class <code>weekday</code> is used to specify a day of the week.
+</p>
+
+<pre>
+explicit weekday(int wd);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs an object of class <code>week_day</code> by storing
+<code>wd</code>.
+</p>
+
+<p>
+<i>Postconditions:</i> <code>static_cast&lt;int&gt;(*this) == wd</code>
+</p>
+
+<p>
+<i>Throws:</i> if <code>wd</code> is outside of the range [0, 6], throws an
+exception of type <code>bad_date</code>.
+</p>
+</blockquote>
+
+<pre>
+operator int() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> the value of the stored <code>int</code>.
+</p>
+
+</blockquote>
+
+<pre>
+day operator[](decltype(_1st) d) const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> A <code>day</code> with copies of <code>d</code> and
+<code>*this</code> stored within. If this <code>day</code> is converted to an
+<code>int</code> the value of that <code>int</code> is unspecified.
+</p>
+
+</blockquote>
+
+<pre>
+day operator[](int n) const;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> A <code>day</code> with copies of <code>n</code> and
+<code>*this</code> stored within. If this <code>day</code> is converted to an
+<code>int</code> the value of that <code>int</code> is unspecified.
+</p>
+
+<p>
+<i>Throws:</i> if <code>n</code> is outside of the range [1, 5], throws an
+exception of type <code>bad_date</code>.
+</p>
+</blockquote>
+
+<p>
+These <code>const weekday</code> objects are constructed prior to first use with
+the following values:
+</p>
+
+<blockquote><pre>
+const weekday sun(0);
+const weekday mon(1);
+const weekday tue(2);
+const weekday wed(3);
+const weekday thu(4);
+const weekday fri(5);
+const weekday sat(6);
+</pre></blockquote>
+
+<h5>Class <code>year_month</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class year_month
+ {
+ public:
+ year_month() = delete;
+ year_month(const year_month&amp;) = default;
+ year_month&amp; operator=(const year_month&amp;) = default;
+ ~year_month() = default;
+ };
+}
+}
+</pre>
+
+<p>
+Class <code>year_month</code> has no public member API except for being
+<code>CopyConstructible</code>, <code>CopyAssignable</code>, and
+<code>Destructible</code>. It is capable of storing both a <code>year</code>
+and a <code>month</code>.
+</p>
+
+<h5>Class <code>month_day</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class month_day
+ {
+ public:
+ month_day() = delete;
+ month_day(const month_day&amp;) = default;
+ month_day&amp; operator=(const month_day&amp;) = default;
+ ~month_day() = default;
+ };
+}
+}
+</pre>
+
+<p>
+Class <code>month_day</code> has no public member API except for being
+<code>CopyConstructible</code>, <code>CopyAssignable</code>, and
+<code>Destructible</code>. It is capable of storing both a <code>month</code>
+and a <code>day</code>.
+</p>
+
+<h4>Date generation functions</h4>
+
+<pre>
+namespace std {
+namespace chrono {
+ month_day operator/(day, month) noexcept;
+ month_day operator/(month, day) noexcept;
+
+ year_month operator/(year, month) noexcept;
+
+ date operator/(year_month, day);
+ date operator/(month_day, year);
+ date operator/(year_month, int);
+ date operator/(month_day, int);
+}
+}
+</pre>
+
+<p>
+These operators are used to construct objects of type <code>day</code>,
+<code>month_day</code>, <code>year_month</code>, and <code>date</code>.
+[<i>Note:</i> In each case, these operators are the only public way to construct
+the returned objects with the supplied arguments. Implementations will access
+unspecified constructors to return the specified value. &mdash; <i>end note</i>]
+</p>
+
+<pre>
+month_day operator/(day d, month m) noexcept;
+month_day operator/(month m, day d) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> A <code>month_day</code> with copies of <code>d</code> and
+<code>m</code> stored within.
+</p>
+</blockquote>
+
+<pre>
+year_month operator/(year y, month m) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> A <code>year_month</code> with copies of <code>y</code> and
+<code>m</code> stored within.
+</p>
+</blockquote>
+
+<pre>
+date operator/(year_month ym, day d);
+date operator/(month_day md, year y);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> A <code>date</code> constructed using the <code>year</code>,
+<code>month</code>, <code>day</code>, <code>weekday</code>, and pre-multipliers
+of <code>weekday</code> stored in the arguments as follows. [<i>Note:</i> A
+<code>date</code> is not constructible by these arguments except via these
+operators. Implementations will construct the <code>date</code> via an
+unspecified interface. &mdash; <i>end note</i>]
+</p>
+<blockquote>
+
+<p>
+Let <code>d</code> represent both the <code>day</code> argument, and the
+<code>day</code> stored within <code>md</code>. Let <code>m</code> represent
+both the <code>month</code> stored within <code>ym</code>, and the
+<code>month</code> stored within <code>md</code>. Let <code>y</code> represent
+both the <code>year</code> argument, and the <code>year</code> stored within
+<code>ym</code>. The symbols <code>y_</code>, <code>m_</code>, <code>d_</code>,
+and <code>meta_</code> refer to the exposition-only private data members of
+<code>date</code> in [class.date].
+</p>
+
+<ul>
+<li>
+If <code>d</code> was constructed with <code>_1st</code>, <code>_2nd</code>,
+<code>_3rd</code>, <code>_4th</code>, or <code>_5th</code>, the construction
+has the same behavior as if the <code>day</code> was constructed with the
+integers 1 through 5 respectively.
+</li>
+<li>
+If <code>d</code> was constructed with <code>last</code>, then constructs a
+<code>date</code> with <code>y_ = y</code>, <code>m_ = m</code>, and <code>d_ =
+</code>to the last day of the month <code>m</code> for the indicated year
+<code>y</code>, and stores within <code>meta_</code> the fact that this
+<code>date</code> represents the last day of the month for purposes of month and
+year-oriented arithmetic.
+</li>
+<li>
+If <code>d</code> was constructed by pre-multiplying a <code>weekday</code>
+with <code>_1st</code> through <code>_5th</code>, or equivalently by 1 through
+5, then constructs a <code>date</code> corresponding to the nth day of the week
+for the indicated month <code>m</code> and year <code>y</code>. If the
+pre-multiplier is 5 or <code>_5th</code>, and the computed day exceeds the end
+of the month, an exception of type <code>bad_date</code> is thrown. Stores
+within <code>meta_</code> the fact that this <code>date</code> represents the
+nth weekday of the month for purposes of month and year-oriented arithmetic.
+</li>
+<li>
+If <code>d</code> was constructed by pre-multiplying a <code>weekday</code>
+with <code>last</code>, then constructs a <code>date</code> corresponding to the
+last day of the week for the indicated month <code>m</code> and year
+<code>y</code>. Stores within the <code>meta_</code> the fact that this
+<code>date</code> represents the last weekday of the month for purposes of
+month and year-oriented arithmetic.
+</li>
+<li>
+Else <code>d</code> was constructed with an integral value in the range [1, 31].
+If the value stored in <code>d</code> is outside the range of valid dates for
+this month <code>m</code> and year <code>y</code>, throws an exception of type
+<code>bad_date</code>. Else constructs a <code>date</code> for which
+<code>y_ = y</code>, <code>m_ = m</code>, <code>d_ = d</code>, and
+<code>meta_</code> indicates that this <code>date</code> is of the simple
+form yyyy-mm-dd.
+</li>
+</ul>
+
+<blockquote class="note">
+<p>
+The meta-data stored in the <code>date</code> is that the <code>date</code> is
+one of 3 forms:
+</p>
+
+<ol>
+<li>nth day of the month [1-31]</li>
+<li>last day of the month</li>
+<li>nth weekday of the month, where n may be [1-5] or last</li>
+</ol>
+
+<p>
+The third form must store n, which can take on 6 values (counting
+<code>last</code>), and the weekday which can take on 7 values. That combines
+to 42 possible values which can be stored in 6 bits. Six bits can store up to
+64 values, and some of those values not used for storing the 42 states
+associated with form 3 can go towards indicating which form the date is. The
+example implementation uses two 3-bit fields to store this data.
+</p>
+
+</blockquote>
+
+</blockquote>
+</blockquote>
+
+<pre>
+date operator/(year_month ym, int d);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>ym / day(d)</code></code>.
+</p>
+</blockquote>
+
+<pre>
+date operator/(month_day md, int y);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>md / year(y)</code>.
+</p>
+</blockquote>
+
+<h4>Date durations</h4>
+
+<p>
+There are three <code>chrono date</code> duration types: <code>days</code>,
+<code>months</code> and <code>years</code>. <code>days</code> is a
+<code>chrono::duration</code> The latter two types are modeled after
+<code>chrono::duration</code> except that there are no conversions to and from
+the the different durations, not even amongst themselves. These durations
+represent time durations, as opposed to representing a date component (e.g. 7
+months) and are used in <code>date</code> arithmetic. These durations are based
+on a signed integral type that must be at least 32 bits.
+</p>
+
+<blockquote class="note">
+<p>
+In the example implementation <code>months</code> and <code>years</code> are
+implemented as a <code>typdef</code> to an "unnamed" template specialization.
+I.e. they differ in type only, not in functionality.
+</p>
+</blockquote>
+
+<h5>Class <code>months</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class months
+ {
+ public:
+ typedef <i>signed-integral-type-of-at-least-32-bits</i> rep;
+ months() = default;
+ explicit months(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ months operator+() const noexcept;
+ months operator-() const noexcept;
+
+ months&amp; operator++() noexcept;
+ months operator++(int) noexcept;
+ months&amp; operator--() noexcept;
+ months operator--(int) noexcept;
+
+ months&amp; operator+=(const months&amp; x) noexcept;
+ months&amp; operator-=(const months&amp; x) noexcept;
+
+ months&amp; operator*=(const rep&amp; rhs) noexcept;
+ months&amp; operator/=(const rep&amp; rhs) noexcept;
+ months&amp; operator%=(const rep&amp; rhs) noexcept;
+ months&amp; operator%=(const months&amp; rhs) noexcept;
+ private:
+ rep x_; // exposition only
+ };
+
+ months operator+(months x, months y) noexcept;
+ months operator-(months x, months y) noexcept;
+ months operator*(months x, months::rep y) noexcept;
+ months operator*(months::rep x, months y) noexcept;
+ months operator/(months x, months::rep y) noexcept;
+ months::rep operator/(months x, months y) noexcept;
+ months operator%(months x, months::rep y) noexcept;
+ months operator%(months x, months y) noexcept;
+
+ bool operator==(months x, months y) noexcept;
+ bool operator!=(months x, months y) noexcept;
+ bool operator&lt; (months x, months y) noexcept;
+ bool operator&gt; (months x, months y) noexcept;
+ bool operator&lt;=(months x, months y) noexcept;
+ bool operator&gt;=(months x, months y) noexcept;
+}
+}
+</pre>
+
+<pre>
+months(rep x) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs a <code>months</code>.
+</p>
+<p>
+<i>Postconditions:</i> <code>count() == x</code>.
+</p>
+</blockquote>
+
+<pre>
+rep count() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x_</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator+() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x_)</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator-() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(-x_)</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator++() noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>++x_</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator++(int) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x_++)</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator--() noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>--x_</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator--(int) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x_--)</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator+=(const months&amp; x) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ += x.count()</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator-=(const months&amp; x) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ -= x.count()</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator*=(const rep&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ *= rhs</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator/=(const rep&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ /= rhs</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator%=(const rep&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ %= rhs</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months&amp; operator%=(const months&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ %= rhs.count()</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator+(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x.count() + y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator-(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x.count() - y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator*(months x, months::rep y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x.count() * y)</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator*(months::rep x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x * y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator/(months x, months::rep y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x.count() / y)</code>.
+</p>
+</blockquote>
+
+<pre>
+months::rep operator/(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.count() / y.count()</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator%(months x, months::rep y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x.count() % y)</code>.
+</p>
+</blockquote>
+
+<pre>
+months operator%(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>months(x.count() % y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator==(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.count() == y.count()</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator!=(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(x == y)</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&lt; (months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.count() &lt; y.count()</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&gt; (months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>y &lt; x</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&lt;=(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(y &lt; x)</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&gt;=(months x, months y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(x &lt; y)</code>.
+</p>
+</blockquote>
+
+<h5>Class <code>years</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ class years
+ {
+ public:
+ typedef <i>signed-integral-type-of-at-least-32-bits</i> rep;
+ years() = default;
+ explicit years(rep x) noexcept;
+
+ rep count() const noexcept;
+
+ years operator+() const noexcept;
+ years operator-() const noexcept;
+
+ years&amp; operator++() noexcept;
+ years operator++(int) noexcept;
+ years&amp; operator--() noexcept;
+ years operator--(int) noexcept;
+
+ years&amp; operator+=(const years&amp; x) noexcept;
+ years&amp; operator-=(const years&amp; x) noexcept;
+
+ years&amp; operator*=(const rep&amp; rhs) noexcept;
+ years&amp; operator/=(const rep&amp; rhs) noexcept;
+ years&amp; operator%=(const rep&amp; rhs) noexcept;
+ years&amp; operator%=(const years&amp; rhs) noexcept;
+ private:
+ rep x_; // exposition only
+ };
+
+ years operator+(years x, years y) noexcept;
+ years operator-(years x, years y) noexcept;
+ years operator*(years x, years::rep y) noexcept;
+ years operator*(years::rep x, years y) noexcept;
+ years operator/(years x, years::rep y) noexcept;
+ years::rep operator/(years x, years y) noexcept;
+ years operator%(years x, years::rep y) noexcept;
+ years operator%(years x, years y) noexcept;
+
+ bool operator==(years x, years y) noexcept;
+ bool operator!=(years x, years y) noexcept;
+ bool operator&lt; (years x, years y) noexcept;
+ bool operator&gt; (years x, years y) noexcept;
+ bool operator&lt;=(years x, years y) noexcept;
+ bool operator&gt;=(years x, years y) noexcept;
+}
+}
+</pre>
+
+<pre>
+years(rep x) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs a <code>years</code>.
+</p>
+<p>
+<i>Postconditions:</i> <code>count() == x</code>.
+</p>
+</blockquote>
+
+<pre>
+rep count() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x_</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator+() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x_)</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator-() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(-x_)</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator++() noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>++x_</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator++(int) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x_++)</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator--() noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>--x_</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator--(int) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x_--)</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator+=(const years&amp; x) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ += x.count()</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator-=(const years&amp; x) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ -= x.count()</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator*=(const rep&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ *= rhs</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator/=(const rep&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ /= rhs</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator%=(const rep&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ %= rhs</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years&amp; operator%=(const years&amp; rhs) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>x_ %= rhs.count()</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator+(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x.count() + y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator-(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x.count() - y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator*(years x, years::rep y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x.count() * y)</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator*(years::rep x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x * y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator/(years x, years::rep y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x.count() / y)</code>.
+</p>
+</blockquote>
+
+<pre>
+years::rep operator/(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.count() / y.count()</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator%(years x, years::rep y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x.count() % y)</code>.
+</p>
+</blockquote>
+
+<pre>
+years operator%(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>years(x.count() % y.count())</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator==(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.count() == y.count()</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator!=(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(x == y)</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&lt; (years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.count() &lt; y.count()</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&gt; (years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>y &lt; x</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&lt;=(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(y &lt; x)</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&gt;=(years x, years y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(x &lt; y)</code>.
+</p>
+</blockquote>
+
+<h4>Class <code>date</code></h4>
+
+<pre>
+namespace std {
+namespace chrono {
+ class date
+ {
+ public:
+ // construction
+ date() noexcept;
+ static date today() noexcept;
+
+ // system_clock::time_point conversions
+ explicit date(chrono::system_clock::time_point tp);
+ explicit operator chrono::system_clock::time_point () const;
+
+ // obervers
+ chrono::day day() const noexcept;
+ chrono::month month() const noexcept;
+ chrono::year year() const noexcept;
+ chrono::weekday weekday() const noexcept;
+ bool is_leap_year() const noexcept;
+
+ // day arithmetic
+ date&amp; operator+=(days d);
+ date&amp; operator++();
+ date operator++(int);
+ date&amp; operator-=(days d);
+ date&amp; operator--();
+ date operator--(int);
+
+ // month arithmetic
+ date&amp; operator+=(months m);
+ date&amp; operator-=(months m);
+
+ // year arithmetic
+ date&amp; operator+=(years y);
+ date&amp; operator-=(years y);
+ private:
+ short y_; // exposition only, stores year number
+ unsigned char m_; // exposition only, stores month number [1-12]
+ unsigned char d_; // exposition only, stores day number [1-31]
+ unsigned char meta_; // exposition only, stores what date represents
+ };
+
+ // date comparisons
+
+ bool operator==(const date&amp; x, const date&amp; y) noexcept;
+ bool operator!=(const date&amp; x, const date&amp; y) noexcept;
+ bool operator&lt; (const date&amp; x, const date&amp; y) noexcept;
+ bool operator&gt; (const date&amp; x, const date&amp; y) noexcept;
+ bool operator&lt;=(const date&amp; x, const date&amp; y) noexcept;
+ bool operator&gt;=(const date&amp; x, const date&amp; y) noexcept;
+
+ // date day arithmetic
+ date operator+(date dt, days d);
+ date operator+(days d, date dt);
+ date operator-(date dt, days d);
+ days operator-(date x, date y) noexcept;
+
+ // date month arithmetic
+ date operator+(date dt, months m);
+ date operator+(months m, date dt);
+ date operator-(date dt, months m);
+
+ // date year arithmetic
+ date operator+(date dt, years y);
+ date operator+(years y, date dt);
+ date operator-(date dt, years y);
+
+ // find prior / next weekday
+ date operator&lt; (weekday wd, date x);
+ date operator&lt;=(weekday wd, date x);
+ date operator&gt; (weekday wd, date x);
+ date operator&gt;=(weekday wd, date x);
+}
+}
+</pre>
+
+<p>
+Class <code>date</code> represents a day in the proleptic Gregorian calendar.
+The year preceding year 1 is year 0, and year 0 is a leap year. The range of
+years representable by this class is the same as the range of <code>year</code>.
+</p>
+
+<h5>Construction and conversion</h5>
+
+<pre>
+date() noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs a <code>date</code> as if by
+<code>year(0)/jan/1</code>. [<i>Note:</i> the purpose of this constructor is to
+have a very efficient means of <code>date</code> construction when the specific
+value for that <code>date</code> is unimportant. &mdash; <i>end note</i>]
+</p>
+</blockquote>
+
+<pre>
+static date today() noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs a <code>date</code> which represents the current
+day taking the local time zone into account.
+</p>
+</blockquote>
+
+<pre>
+explicit date(chrono::system_clock::time_point tp);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>tp</code> is converted to UTC, and then trucated to
+00:00:00 hours. A <code>date </code>is created which reflects this point in
+time.
+</p>
+
+<p>
+<i>Throws:</i> If the conversion from <code>tp</code> overflows the range of
+<code>date</code>, throws an exception of type <code>bad_date</code>.
+</p>
+</blockquote>
+
+<pre>
+explicit operator chrono::system_clock::time_point () const;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> A <code>chrono::system_clock::time_point</code> which
+represents the date referred to by <code>*this</code> at 00:00:00 UTC.
+</p>
+
+<p>
+<i>Throws:</i> If the conversion to <code>tp</code> overflows the range of
+<code>chrono::system_clock::time_point</code>, throws an exception of type
+<code>bad_date</code>.
+</p>
+</blockquote>
+
+<h5><code>date</code> Observers</h5>
+
+<pre>
+chrono::day day() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>chrono::day(d_)</code>.
+</p>
+</blockquote>
+
+<pre>
+chrono::month month() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>chrono::month(m_)</code>.
+</p>
+</blockquote>
+
+<pre>
+chrono::year year() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>chrono::year(y_)</code>.
+</p>
+</blockquote>
+
+<pre>
+chrono::weekday weekday() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> A <code>weekday</code> constructed with an <code>int</code>
+corresponding to <code>*this date</code>'s day of the week (a value in the
+range of [0 - 6], 0 is Sunday).
+</p>
+</blockquote>
+
+<pre>
+bool is_leap_year() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>true</code> if <code>year()</code> is a leap year, and
+otherwise returns <code>false</code>.
+</p>
+</blockquote>
+
+<h5><code>date</code> comparisons</h5>
+
+<pre>
+bool operator==(const date&amp; x, const date&amp; y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.year() == y.year() &amp;&amp; x.month() == y.month()
+&amp;&amp; x.day() == y.day()</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator!=(const date&amp; x, const date&amp; y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(x == y)</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&lt; (const date&amp; x, const date&amp; y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>x.year() &lt; y.year() ||
+ (!(y.year() &lt; x.year()) &amp;&amp; (x.month() &lt; y.month() ||
+ (!(y.month() &lt; x.month()) &amp;&amp; x.day() &lt; y.day())))</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&gt; (const date&amp; x, const date&amp; y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>y &lt; x</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&lt;=(const date&amp; x, const date&amp; y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(y &lt; x)</code>.
+</p>
+</blockquote>
+
+<pre>
+bool operator&gt;=(const date&amp; x, const date&amp; y) noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>!(x &lt; y)</code>.
+</p>
+</blockquote>
+
+<h5><code>date</code> arithmetic</h5>
+
+<pre>
+date&amp; operator+=(days d);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Adds <code>d.count()</code> days to the current
+<code>date</code>. Sets <code>meta_</code> to indicate that this
+<code>date</code> was not constructed with a <code>day</code> constructed from
+<code>last</code> or from a pre-multiplied <code>weekday</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+
+<p>
+<i>Throws:</i> If the addition would create a date with a <code>y_</code>
+outside of the range of <code>year</code>, throws an exception of type
+<code>bad_date</code>.
+</p>
+</blockquote>
+
+<pre>
+date&amp; operator++();
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>*this += days(1)</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+date operator++(int);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>*this += days(1)</code>.
+</p>
+
+<p>
+<i>Returns:</i> A copy of <code>*this</code> prior to the increment.
+</p>
+</blockquote>
+
+<pre>
+date&amp; operator-=(days d);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>*this += -d</code>
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+
+</blockquote>
+
+<pre>
+date&amp; operator--();
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>*this -= days(1)</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+</blockquote>
+
+<pre>
+date operator--(int);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> <code>*this -= days(1)</code>.
+</p>
+
+<p>
+<i>Returns:</i> A copy of <code>*this</code> prior to the decrement.
+</p>
+</blockquote>
+
+<pre>
+date operator+(date dt, days d);
+date operator+(days d, date dt);
+</pre>
+
+<blockquote>
+
+<p>
+<i>Returns:</i> <code>dt += d</code>.
+</p>
+</blockquote>
+
+<pre>
+date operator-(date dt, days d);
+</pre>
+
+<blockquote>
+
+<p>
+<i>Returns:</i> <code>dt -= d</code>.
+</p>
+</blockquote>
+
+<pre>
+days operator-(date x, date y) noexcept;
+</pre>
+
+<blockquote>
+
+<p>
+<i>Returns:</i> Computes the number of days <code>x</code> is ahead of
+<code>y</code> in the calendar, and returns that signed integral number
+<code>n</code> as <code>days(n)</code>.
+</p>
+</blockquote>
+
+<pre>
+date&amp; operator+=(months m);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Adds <code>m.count()</code> months to the current
+<code>date</code>. This is accomplished as if by storing temporary values of
+the <code>date</code>'s <code>y_</code>, <code>m_</code>, <code>d_</code>, and
+<code>meta_</code>. Computing new values for <code>y_</code> and
+<code>m_</code> based on <code>m</code>. And then assigning to
+<code>*this</code> a new <code>date</code> constructed from the newly computed
+<code>y_</code> and <code>m_</code>, and the original <code>d_</code> and
+<code>meta_</code>. [<i>Note:</i> Thus for example if a <code>date</code> is
+constructed as the second Sunday in May, adding two <code>months</code> to this
+<code>date</code> results in the second Sunday in July. &mdash; <i>end note</i>]
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+
+<p>
+<i>Throws:</i> If the addition would create a date with a <code>y_</code>
+outside of the range of <code>year</code>, or a <code>d_</code> outside the
+range for the newly computed <code>y_/m_</code>, throws an exception of type
+<code>bad_date</code>.
+</p>
+</blockquote>
+
+<pre>
+date&amp; operator-=(months m);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>*this += -m</code>.
+</p>
+
+</blockquote>
+
+<pre>
+date operator+(date dt, months m);
+date operator+(months m, date dt);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>dt += m</code>.
+</p>
+
+</blockquote>
+
+<pre>
+date operator-(date dt, months m);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>dt += -m</code>.
+</p>
+
+</blockquote>
+
+<pre>
+date& operator+=(years y);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Adds <code>y.count()</code> years to the current
+<code>date</code>. This is accomplished as if by storing temporary values of
+the <code>date</code>'s <code>y_</code>, <code>m_</code>, <code>d_</code>, and
+<code>meta_</code>. Computing a new value for <code>y_</code>. And then
+assigning to <code>*this</code> a new <code>date</code> constructed from the
+newly computed <code>y_</code>, and the original <code>m_</code>,
+<code>d_</code> and <code>meta_</code>. [<i>Note:</i> Thus for example if a
+<code>date</code> is constructed as the second Sunday in May 2011, adding two
+<code>years</code> to this <code>date</code> results in the second Sunday in May
+2013. &mdash; <i>end note</i>]
+</p>
+
+<p>
+<i>Returns:</i> <code>*this</code>.
+</p>
+
+<p>
+<i>Throws:</i> If the addition would create a date with a <code>y_</code>
+outside of the range of <code>year</code>, or a <code>d_</code> outside the
+range for the newly computed <code>y_/m_</code>, throws an exception of type
+<code>bad_date</code>.
+</p>
+</blockquote>
+
+<pre>
+date&amp; operator-=(years y);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>*this += -y</code>.
+</p>
+
+</blockquote>
+
+<pre>
+date operator+(date dt, years y);
+date operator+(years y, date dt);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>dt += y</code>.
+</p>
+
+</blockquote>
+
+<pre>
+date operator-(date dt, years y);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>dt += -y</code>.
+</p>
+
+</blockquote>
+
+<pre>
+date operator&lt; (weekday wd, date x);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> Let <code>a</code> be <code>wd</code> converted to an
+<code>int</code>, and <code>b</code> be <code>x.weekday()</code> converted to an
+<code>int</code>. If <code>a &lt; b</code>, returns <code>x - days(b-a)</code>,
+else returns <code>x - days(7 - (a-b))</code>.
+</p>
+</blockquote>
+
+<pre>
+date operator&lt;=(weekday wd, date x);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> Let <code>a</code> be <code>wd</code> converted to an
+<code>int</code>, and <code>b</code> be <code>x.weekday()</code> converted to an
+<code>int</code>. If <code>a &lt;= b</code>, returns <code>x - days(b-a)</code>,
+else returns <code>x - days(7 - (a-b))</code>.
+</p>
+</blockquote>
+
+<pre>
+date operator&gt; (weekday wd, date x);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> Let <code>a</code> be <code>wd</code> converted to an
+<code>int</code>, and <code>b</code> be <code>x.weekday()</code> converted to an
+<code>int</code>. If <code>a &lt; b</code>, returns <code>x + days(b-a)</code>,
+else returns <code>x + days(7 - (a-b))</code>.
+</p>
+</blockquote>
+
+<pre>
+date operator&gt;=(weekday wd, date x);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> Let <code>a</code> be <code>wd</code> converted to an
+<code>int</code>, and <code>b</code> be <code>x.weekday()</code> converted to an
+<code>int</code>. If <code>a &lt;= b</code>, returns <code>x + days(b-a)</code>,
+else returns <code>x + days(7 - (a-b))</code>.
+</p>
+</blockquote>
+
+<h4><code>date</code> I/O</h4>
+
+<h5>Class template <code>datepunct</code></h5>
+
+<pre>
+namespace std {
+namespace chrono {
+ template &lt;class charT&gt;
+ class datepunct
+ : public locale::facet
+ {
+ public:
+ typedef basic_string&lt;charT&gt; string_type;
+
+ static locale::id id;
+
+ explicit datepunct(size_t refs = 0);
+ explicit datepunct(string_type frmt, size_t refs = 0);
+
+ const string_type&amp; fmt() const noexcept;
+ private:
+ string_type fmt_; // exposition only
+ };
+}
+}
+</pre>
+
+<p>
+<code>datepunct</code> is a <code>facet</code> which holds a string of
+formatting characters to be used with <code>time_get</code> ([locale.time.get])
+and <code>time_put</code> ([locale.time.put]).
+</p>
+
+<pre>
+explicit datepunct(size_t refs = 0);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs a <code>datepunct</code> by constructing the base
+class with <code>refs</code>.
+</p>
+
+<p>
+<i>Postconditions:</i> <code>fmt() == "%F"</code>.
+</p>
+</blockquote>
+
+<pre>
+explicit datepunct(string_type frmt, size_t refs = 0);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Constructs a <code>datepunct</code> by constructing the base
+class with <code>refs</code>.
+</p>
+
+<p>
+<i>Postconditions:</i> <code>fmt() == frmt</code>.
+</p>
+</blockquote>
+
+<pre>
+const string_type&amp; fmt() const noexcept;
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> <code>fmt_</code>.
+</p>
+
+</blockquote>
+
+<h5><code>date_fmt</code> Manipulator</h5>
+
+<pre>
+template&lt;class charT&gt;
+<i>unspecified</i>
+date_fmt(basic_string&lt;charT&gt; fmt);
+
+template&lt;class charT&gt;
+<i>unspecified</i>
+date_fmt(const charT* fmt);
+</pre>
+
+<blockquote>
+<p>
+<i>Returns:</i> An object of unspecifed type such that if <code>out</code> is an
+object of type <code>basic_ostream&lt;charT, traits&gt;</code> then the
+expression <code>out &lt;&lt; date_fmt(fmt)</code> behaves as if it called
+<code>f(out, fmt)</code>, or if <code>in</code> is an object of type
+<code>basic_istream&lt;charT, traits&gt;</code> then the expression <code>in
+&gt;&gt; date_fmt(fmt)</code> behaves as if it called <code>f(in, fmt)</code>,
+where the function <code>f</code> is defined as:
+</p>
+<blockquote><pre>
+template&lt;class charT, class traits&gt;
+void f(basic_ios&lt;charT, traits&gt;&amp; str, basic_string&lt;charT&gt; fmt)
+{
+ str.imbue(locale(str.getloc(), new datepunct&lt;charT&gt;(move(fmt))));
+}
+</pre></blockquote>
+</blockquote>
+
+<h5><code>date</code> inserter and extractor</h5>
+
+<pre>
+template&lt;class charT, class Traits&gt;
+basic_istream&lt;charT,Traits&gt;&amp;
+operator&gt;&gt;(basic_istream&lt;charT,Traits&gt;&amp; is, date&amp; d);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Behaves as a formatted input function
+([istream.formatted.reqmts]). After constructing a <code>sentry</code> object,
+if the sentry converts to true, acquires the <code>time_get</code> facet from
+the stream's <code>locale</code>. If the <code>locale</code> has a
+<code>datepunct</code> facet, obtains the conversion specifier string from that
+facet, otherwise sets the conversion specifier string to "%F". Then extracts a
+<code>tm</code> from <code>is</code> as if:
+</p>
+<blockquote><pre>
+tg.get(is, 0, is, err, &amp;t, fmt, fmtend);
+</pre></blockquote>
+
+<p>
+Where <code>tg</code> is the <code>time_get</code> facet, <code>err</code> is a
+local variable of type <code>ios_base::iostate</code>, <code>t</code> is a local
+variable of type <code>tm</code>, and <code>[fmt, fmtend)</code> are local
+variables of type <code>charT*</code> which delimit the conversion specifier
+string.
+</p>
+
+<p>
+If <code>(err &amp; ios_base::failbit)</code> is false, assigns a
+<code>date</code> to <code>d</code> which is constructed from the year, month
+and day information stored within <code>t</code>. In any case, then calls
+<code>is.setstate(err)</code>.
+</p>
+
+<p>
+<i>Returns:</i> <code>is</code>.
+</p>
+</blockquote>
+
+<pre>
+template&lt;class charT, class Traits&gt;
+basic_ostream&lt;charT, Traits&gt;&amp;
+operator&lt;&lt;(basic_ostream&lt;charT, Traits&gt;&amp; os, const date&amp; d);
+</pre>
+
+<blockquote>
+<p>
+<i>Effects:</i> Behaves as a formatted output function
+([ostream.formatted.reqmts]). After constructing a <code>sentry</code> object,
+if the sentry converts to true, acquires the <code>time_put</code> facet from
+the stream's <code>locale</code>. If the <code>locale</code> has a
+<code>datepunct</code> facet, obtains the formatting string from that
+facet, otherwise sets the formatting string to "%F". Then creates a local variable
+<code>t</code> of type <code>tm</code>. The variable <code>t</code> is filled
+with the year, month, day and weekday information contained in <code>d</code>.
+<code>t</code> is then inserted into <code>os</code> as if:
+</p>
+<blockquote><pre>
+bool failed = tp.put(os, os, os.fill(), &amp;t, pattern, pat_end).failed();
+</pre></blockquote>
+
+<p>
+Where <code>tp</code> is the <code>time_put</code> facet, and <code>[pattern,
+pat_end)</code> are local variables of type <code>charT*</code> which delimit
+the formatting string.
+</p>
+
+<p>
+If <code>failed</code> is true, calls <code>os.setstate(ios_base::failbit |
+ios_base::badbit)</code>.
+</p>
+
+
+
+<p>
+<i>Returns:</i> <code>os</code>.
+</p>
+</blockquote>
+
+<h2>Acknowledgements</h2>
+
+<p>
+I'm very grateful for the thorough review given by Daniel Kr&uuml;gler.
+</p>
+
+</body>
+</html>

Added: sandbox/chrono_date/libs/date/example/ex_julian.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/example/ex_julian.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,36 @@
+// ex_julian.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <iostream>
+#include <boost/chrono/date/date_io.hpp>
+#include "julian.hpp"
+
+int main()
+{
+ std::cout << boost::chrono::date_fmt("%a %b %e, %Y");
+ boost::chrono::date cd = boost::chrono::date::today();
+ julian::date jd(cd);
+ std::cout << "Today is:\n"
+ << cd << " in the boost::chrono calendar and\n"
+ << jd << " in the Julian calendar\n";
+ jd -= julian::years(1800);
+ cd = boost::chrono::date(jd);
+ std::cout << "1800 years ago the two calendars were aligned:\n"
+ << cd << " in the boost::chrono calendar and\n"
+ << jd << " in the Julian calendar\n";
+
+ return 0;
+}
+
+//Today is:
+//Wed Oct 12, 2011 in the boost::chrono calendar and
+//Wed Sep 29, 2011 in the Julian calendar
+//1800 years ago the two calendars were aligned:
+//Sun Sep 29, 0211 in the boost::chrono calendar and
+//Sun Sep 29, 0211 in the Julian calendar
+

Added: sandbox/chrono_date/libs/date/example/ex_week_based_year.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/example/ex_week_based_year.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,30 @@
+// week_base_year.hpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <iostream>
+#include <boost/chrono/date/date_io.hpp>
+#include "week_based_year.hpp"
+
+int main()
+{
+ using namespace boost::chrono;
+
+ date d = oct / day(12) / 2011;
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< d << '\n';
+ int weeknum;
+ weekday wd(0);
+ year y(0);
+ boost::tie(weeknum, wd, y) = date_to_week(d);
+
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< weeknum << " " << wd << " " << y << '\n';
+
+ d = week_to_date(weeknum, wd, y);
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< d << '\n';
+
+ return 0;
+}

Added: sandbox/chrono_date/libs/date/example/hello_world.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/example/hello_world.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,251 @@
+// hello_world.cpp ----------------------------------------------------------//
+
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <iostream>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/chrono_io.hpp>
+#include <boost/chrono/date/relative_date.hpp>
+#include <boost/chrono/date/date_generators.hpp>
+#include <boost/chrono/date.hpp>
+
+int main()
+{
+
+ using std::cout;
+ //using namespace boost;
+ using namespace boost::chrono;
+ typedef boost::chrono::high_resolution_clock Clock;
+ typedef boost::chrono::duration<double,boost::micro> micros;
+
+ std::cout << jan/day(2)/2011 << '\n'; // 2011-01-02
+ std::cout << month(1,no_check)/day(2)/2011 << '\n'; // 2011-01-02
+ std::cout << date(2011, 1, 2, no_check) << '\n'; // 2011-01-02
+ std::cout << '\n';
+
+ std::cout << jan/day(1)/2011 << '\n'; // 2011-01-02
+ std::cout << jan/day(2)/2011 << '\n'; // 2011-01-02
+ std::cout << feb/day(1)/2011 << '\n'; // 2011-01-02
+
+ // Print Feb. 28 for each year in the decade
+ for (date d = feb/day(28)/2010, e = feb/day(28)/2020; d <= e; d += years(1))
+ std::cout << d << '\n';
+ std::cout << '\n';
+
+
+ // Print the day after Feb. 28 for each year in the decade
+ for (date d = feb/day(28)/2010, e = feb/day(28)/2020; d <= e; d += years(1))
+ std::cout << d + days(1) << '\n';
+ std::cout << '\n';
+
+ // Print the 28th of every month in 2011
+ for (date d = jan/day(28)/2011, e = dec/day(28)/2011; d <= e; d += months(1))
+ std::cout << d << '\n';
+ std::cout << '\n';
+
+ {
+ // How many days between may/1/2011 and jan/1/2011?
+ std::cout <<"How many days between may/1/2011 and jan/1/2011? "<< (may/day(01)/2011 - jan/day(01)/2011) << '\n'; // x == 120
+
+ std::cout << '\n';
+ }
+
+ {
+ date dt = aug/day(16)/2011;
+ int d = dt.get_day(); // d == 16
+ int m = dt.get_month(); // m == 8
+ int y = dt.get_year(); // y == 2011
+ std::cout << dt << '\n';
+ std::cout << y << " " << m << " " << d << '\n';
+ std::cout << '\n';
+ }
+
+ {
+ date dt = aug/day(16)/2011;
+ // ...
+ // Create date with the same month and year but on the 5th
+ date dt2 = dt.get_year()/dt.get_month()/5; // aug/5/2011
+ int d = dt.get_day(); // d == 5
+ int m = dt.get_month(); // m == 8
+ int y = dt.get_year(); // y == 2011
+ std::cout << dt << '\n';
+ std::cout << y << " " << m << " " << d << '\n';
+ std::cout << '\n';
+ }
+
+ {
+ date dt = aug/day(16)/2011;
+ // What day of the week is this?
+ int wd = dt.get_weekday(); // 2 (Tuesday)
+ std::cout << dt << '\n';
+ std::cout << wd << '\n';
+ }
+
+ {
+ std::cout << date_fmt("%a %b %e, %Y");
+ // Print the odd fridays of every month in 2011
+ for (date d = jan/day(28)/2011, e = dec/day(28)/2011; d <= e; d += months(1))
+ {
+ std::cout << d << '\n'; // first Friday of the month
+ }
+ }
+ {
+ Clock::time_point t0 = Clock::now();
+ for (date d = feb/day(28)/2010, e = feb/day(28)/2020; d != e; d += years(1))
+ ;
+ Clock::time_point t1 = Clock::now();
+ std::cout << " iterate: " << micros(t1 - t0) << "\n";
+ }
+
+ {
+ date d1 = jan/_2nd/2011; // jan/2/2011
+ date d2 = year(2011)/jan/_2nd; // jan/2/2011
+ date d3 = _2nd/jan/2011; // jan/2/2011
+ std::cout << d1 << '\n';
+ std::cout << d2 << '\n';
+ std::cout << d3 << '\n';
+ }
+
+ {
+ date d1 = last/jan/2011; // jan/31/2011
+ std::cout << d1 << '\n';
+ }
+
+ {
+// date MothersDay = _sun[2]/may/2011; // may/8/2011
+// date MothersDay2 = _sun[_2nd]/may/2011; // may/8/2011
+ date MothersDay2 = _2nd*sun/may/2011; // may/8/2011
+ std::cout <<"MothersDay "<< MothersDay2 << '\n';
+ }
+
+ {
+// date d1 = _fri[last]/may/2011; // may/27/2011
+ date d1 = last*fri/may/2011; // may/27/2011
+ std::cout << d1 << '\n';
+ }
+
+ {
+// int num_fri_in_may = (_fri[last]/may/2011).get_day() > 28 ? 5 : 4; // 4
+ int num_fri_in_may = (last*fri/may/2011).get_day() > 28 ? 5 : 4; // 4
+ std::cout <<"Number of fridays in May"<< num_fri_in_may << '\n';
+
+// date d1 = rel_weekday(5)[_1st]/may/2011;
+ //rel_date d1 = _1st_week*weekday(5)/may/2011;
+ rel_date d1 = _1st*fri/may/2011;
+ std::cout << d1 << '\n';
+ //date d2 = d1;
+ //std::cout << d2 << '\n';
+
+ }
+
+ {
+ // Print the last day in Feb. for each year in the decade
+ for (date d = feb/last/2010, e = feb/last/2020; d <= e; d += years(1))
+ std::cout << d << '\n';
+ std::cout << feb/last/2020 << '\n';
+ }
+
+// {
+// // Print last day of every month in 2011
+// for (date d = jan/last/2011, e = dec/last/2011; d <= e; d += months(1))
+// std::cout << d << '\n';
+// }
+
+ {
+ rel_date d1 = jan/_2nd/2011; // jan/2/2011
+ rel_date d2 = year(2011)/jan/_2nd; // jan/2/2011
+ rel_date d3 = _2nd/jan/2011; // jan/2/2011
+
+ std::cout << d1 << '\n';
+ std::cout << d2 << '\n';
+ std::cout << d3 << '\n';
+ }
+ {
+ rel_date d1 = last/jan/2011; // jan/31/2011
+ std::cout << d1 << '\n';
+ }
+ {
+ // Print the last day in Feb. for each year in the decade
+ for (rel_date d = feb/last/2010, e = feb/last/2020; d <= e; d += years(1))
+ {
+ std::cout << d << '\n';
+ }
+ std::cout << feb/last/2012 << '\n';
+ std::cout << feb/last/2016 << '\n';
+ std::cout << feb/last/2020 << '\n';
+ }
+ {
+ // Print the 29th of every month in 2011
+ for (rel_date d = last/jan/2011, e = last/dec/2011; d <= e; d += months(1))
+ {
+ if (d.get_day() >= 29)
+ std::cout << d.get_year()/d.get_month()/29 << '\n';
+ }
+ }
+ {
+ // Print the 2nd Tuesday of every odd month in 2011
+// for (rel_date d = _tue[2]/jan/2011, e = dec/last/2011; d <= e; d += months(2))
+ for (rel_date d = _2nd*tue/jan/2011, e = dec/last/2011; d <= e; d += months(2))
+ std::cout << d << '\n';
+ }
+ {
+ // Print out every monday between jan/1/2011 and mar/1/2011;
+ //for (date d = _mon[_1st]/jan/2011, e = mar/_1st/2011; d <= e; d += days(7))
+ for (date d = _1st*mon/jan/2011, e = mar/_1st/2011; d <= e; d += days(7))
+ std::cout << d << '\n';
+ }
+ {
+ // Print out the 1st and 3rd friday of the month from 1st/jan/2011 to last/dec/2011;
+ for (rel_date d1 = _1st*fri/jan/2011, d3 = _3rd*fri/jan/2011, e = last/dec/2011; d1 <= e; d1 += months(1), d3 += months(1))
+ {
+ std::cout << d1 << '\n';
+ std::cout << d3 << '\n';
+ }
+ }
+ {
+ date dt = aug/day(16)/2011;
+ // ...
+ // Get the date that is the first occurrence of the same day of the week
+ // in the same month of the next year
+ //rel_date dt2 = dt.get_weekday()[_1st]/dt.get_month()/(dt.get_year() + 1); // aug/7/2012, first Tuesday of Aug 2012
+ rel_date dt2 = _1st*dt.get_weekday()/dt.get_month()/(dt.get_year() + 1); // aug/7/2012, first Tuesday of Aug 2012
+ std::cout << dt << '\n';
+ std::cout << dt2 << '\n';
+ }
+ {
+ date ISO_week_start = mon <= jan/day(4)/2012;
+ std::cout << "ISO_week_start " << ISO_week_start << '\n';
+ }
+
+ {
+ // How many weeks until Christmas?
+ date dt = dec/day(25)/2011;
+ days d=dt- date::today();
+ std::cout << duration_cast<weeks>(d)<< '\n';
+ }
+ {
+ // How many average months until Christmas?
+ days d = (dec/day(25)/2011) - date::today();
+ std::cout << duration_cast<average_months>(d)<< '\n';
+ }
+ {
+ // How many weeks until Christmas?
+ days d=(dec/day(25)>date::today())- date::today();
+ std::cout << duration_cast<weeks>(d)<< '\n';
+ }
+ {
+ std::cout << __FILE__<<"["<<__LINE__ <<"] "<< "How many days until next 28th?" << '\n';
+ // How many days until next 28th?
+ days d=(nth(28)>date::today())- date::today();
+ std::cout << d << '\n';
+ }
+ {
+ day::rep r = day(2) -day(6);
+ std::cout << int(r) << '\n';
+ }
+ return 0;
+}

Added: sandbox/chrono_date/libs/date/example/julian.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/example/julian.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,268 @@
+// julian.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <algorithm>
+#include <ctime>
+#include "julian.hpp"
+#include <boost/chrono/date/detail/to_string.hpp>
+
+namespace julian
+{
+
+ const weekday sun(0);
+ const weekday mon(1);
+ const weekday tue(2);
+ const weekday wed(3);
+ const weekday thu(4);
+ const weekday fri(5);
+ const weekday sat(6);
+
+ const month jan(1);
+ const month feb(2);
+ const month mar(3);
+ const month apr(4);
+ const month may(5);
+ const month jun(6);
+ const month jul(7);
+ const month aug(8);
+ const month sep(9);
+ const month oct(10);
+ const month nov(11);
+ const month dec(12);
+
+ namespace detail
+ {
+ day_spec make_day_spec(uint8_t s)
+ {
+ return day_spec(s);
+ }
+ }
+ const detail::day_spec first = detail::make_day_spec(1);
+ const detail::day_spec second = detail::make_day_spec(2);
+ const detail::day_spec third = detail::make_day_spec(3);
+ const detail::day_spec fourth = detail::make_day_spec(4);
+ const detail::day_spec fifth = detail::make_day_spec(5);
+ const detail::day_spec last = detail::make_day_spec(6);
+
+ static
+ int db[2][13] =
+ {
+ { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
+ { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 } };
+
+ static
+ inline
+ bool is_civil_leap(int y)
+ {
+ return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
+ }
+
+ static
+ inline
+ bool is_leap(int y)
+ {
+ return y % 4 == 0;
+ }
+
+ year::year(int32_t v) :
+ y_(v)
+ {
+ if (!(-32768 <= v && v <= 32767))
+ throw bad_date("year " + boost::chrono::to_string(v) + " is out of range");
+ }
+
+ month::month(int v) :
+ m_(v)
+ {
+ if (!(1 <= v && v <= 12))
+ throw bad_date("month " + boost::chrono::to_string(v) + " is out of range");
+ }
+
+ day::day(int d) :
+ d_(d), n_(7), dow_(7)
+ {
+ if (d < 1 || d > 31)
+ throw bad_date("day " + boost::chrono::to_string(d) + " is out of range");
+ }
+
+ day::day(uint8_t d, uint8_t n, uint8_t dow) :
+ d_(d), n_(n), dow_(dow)
+ {
+ }
+
+ day::day(detail::day_spec s) :
+ d_(1), n_(s.s_), dow_(7)
+ {
+ }
+
+ weekday::weekday(int v) :
+ wd_(v)
+ {
+ if (v < 0 || v > 6)
+ throw bad_date("week day " + boost::chrono::to_string(v) + " is out of range");
+ }
+
+ day operator*(int n, weekday wd)
+ {
+ if (n < 1 || n > 5)
+ throw bad_date("week day multiplier " + boost::chrono::to_string(n)
+ + " is out of range");
+ return detail::day_spec(n) * wd;
+ }
+
+ date::date(boost::chrono::date d)
+ {
+ uint32_t by = d.get_year() + 32799;
+ int* year_data = db[is_civil_leap(by)];
+ x_ = by * 365 + by / 4 - by / 100 + by / 400 + 248 + year_data[d.get_month()
+ - 1] + d.get_day();
+ int y = static_cast<int> (static_cast<int64_t> (x_ + 1) * 4 / 1461);
+ int doy = x_ - (y * 365 + y / 4);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y * 365 + y / 4);
+ }
+ y_ = static_cast<int16_t> (y - 32799);
+ leap_ = is_leap(y_);
+ year_data = db[leap_];
+ m_
+ = static_cast<uint16_t> (std::lower_bound(year_data, year_data + 13, doy)
+ - year_data);
+ d_ = static_cast<uint16_t> (doy - year_data[m_ - 1]);
+ n_ = 7;
+ dow_ = 7;
+ }
+
+ date::operator boost::chrono::date() const
+ {
+ int y = static_cast<int> (static_cast<int64_t> (x_ + (-248 + 2)) * 400
+ / 146097);
+ int doy = x_ - 248 - (y * 365 + y / 4 - y / 100 + y / 400);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - 248 - (y * 365 + y / 4 - y / 100 + y / 400);
+ }
+ y -= 32799;
+ int* year_data = db[is_civil_leap(y)];
+ int m = std::lower_bound(year_data, year_data + 13, doy) - year_data;
+ int d = doy - year_data[m - 1];
+ return boost::chrono::year(y) / boost::chrono::month(m) / d;
+ }
+
+ date::date(julian::year y, julian::month m, julian::day d) :
+ y_(y.y_), m_(m.m_), d_(d.d_), n_(d.n_), dow_(d.dow_)
+ {
+ leap_ = is_leap(y_);
+ int* year_data = db[leap_];
+ if (n_ != 7) // if a detail::day_spec is involved
+
+ {
+ if (dow_ == 7) // if we want nth day of month
+
+ {
+ if (n_ == 6) // want last day of month
+ d_ = year_data[m_] - year_data[m_ - 1];
+ else
+ d_ = n_; // want nth day of month
+ } else // we want nth weekday of month
+
+ {
+ // dow_ = [0 - 6]
+ // n_ = [1 - 6] 6 means last
+ int32_t by = y.y_ + 32799;
+ int32_t fy = by * 365 + by / 4;
+ int n_days_in_month = year_data[m_] - year_data[m_ - 1];
+ int d;
+ if (n_ == 6)
+ {
+ int ldow = (fy + year_data[m_] + 1) % 7;
+ d = n_days_in_month;
+ if (dow_ < ldow)
+ d -= ldow - dow_;
+ else if (dow_ > ldow)
+ d -= 7 - (dow_ - ldow);
+ } else
+ {
+ int fdow = (fy + year_data[m_ - 1] + 2) % 7;
+ d = 1 + (n_ - 1) * 7;
+ if (dow_ < fdow)
+ d += 7 - (fdow - dow_);
+ else if (dow_ > fdow)
+ d += dow_ - fdow;
+ if (d > n_days_in_month)
+ throw bad_date("day " + boost::chrono::to_string(d) + " is out of range for "
+ + boost::chrono::to_string(y_) + '-' + boost::chrono::to_string(m_));
+ }
+ d_ = d;
+ x_ = fy + year_data[m_ - 1] + d_;
+ return;
+ }
+ }
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_ - 1]))
+ throw bad_date("day " + boost::chrono::to_string(d) + " is out of range for "
+ + boost::chrono::to_string(y_) + '-' + boost::chrono::to_string(m_));
+ int32_t by = y.y_ + 32799;
+ x_ = by * 365 + by / 4 + year_data[m_ - 1] + d_;
+ }
+
+ date&
+ date::operator+=(days d)
+ {
+ x_ += d.x_;
+ if (!(11322 <= x_ && x_ <= 23947853))
+ throw bad_date("year is out of range [-32768, 32767]");
+ int y = static_cast<int> (static_cast<int64_t> (x_ + 1) * 4 / 1461);
+ int doy = x_ - (y * 365 + y / 4);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y * 365 + y / 4);
+ }
+ y_ = static_cast<int16_t> (y - 32799);
+ leap_ = is_leap(y_);
+ int* year_data = db[leap_];
+ m_
+ = static_cast<uint16_t> (std::lower_bound(year_data, year_data + 13, doy)
+ - year_data);
+ d_ = static_cast<uint16_t> (doy - year_data[m_ - 1]);
+ n_ = 7;
+ dow_ = 7;
+ return *this;
+ }
+
+ date&
+ date::operator+=(months mn)
+ {
+ int32_t y = y_;
+ int32_t m = m_;
+ m += mn.x_;
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ } else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ *this = julian::day(d_, n_, dow_) / m / y;
+ return *this;
+ }
+
+ date&
+ date::operator+=(years yr)
+ {
+ *this = julian::day(d_, n_, dow_) / m_ / (y_ + yr.x_);
+ return *this;
+ }
+
+} // julian

Added: sandbox/chrono_date/libs/date/example/julian.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/example/julian.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,829 @@
+// julian
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+
+#ifndef BOOST_CHRONO_EXAMPLE_DATE_JULIAN_HPP
+#define BOOST_CHRONO_EXAMPLE_DATE_JULIAN_HPP
+
+/*
+ julian synopsis
+
+ namespace julian
+ {
+
+ // A date
+ class date
+ {
+ public:
+ // construction
+ explicit date(boost::chrono::date d);
+ explicit operator boost::chrono::date() const;
+
+ // obervers
+ day day() const;
+ month month() const;
+ year year() const;
+ weekday weekday();
+ bool is_leap_year() const;
+
+ // day arithmetic
+ date& operator+=(days d);
+ date& operator++();
+ date operator++(int);
+ date& operator-=(days d);
+ date& operator--();
+ date operator--(int);
+
+ // month arithmetic
+ date& operator+=(months m);
+ date& operator-=(months m);
+
+ // year arithmetic
+ date& operator+=(years y);
+ date& operator-=(years y);
+ };
+
+ // date relational
+ bool operator==(const date& x, const date& y);
+ bool operator!=(const date& x, const date& y);
+ bool operator< (const date& x, const date& y);
+ bool operator> (const date& x, const date& y);
+ bool operator<=(const date& x, const date& y);
+ bool operator>=(const date& x, const date& y);
+
+ // date day arithmetic
+ date operator+(date dt, days d);
+ date operator+(days d, date dt);
+ date operator-(date dt, days d);
+ days operator-(date x, date y);
+
+ // date month arithmetic
+ date operator+(date dt, months m);
+ date operator+(months m, date dt);
+ date operator-(date dt, months m);
+
+ // date year arithmetic
+ date operator+(date dt, years y);
+ date operator+(years y, date dt);
+ date operator-(date dt, years y);
+
+ // Specifiers
+
+ // A year specifier
+ class year
+ {
+ public:
+ explicit year(std::int16_t y);
+ operator int() const;
+ };
+
+ // A month specifier
+ class month
+ {
+ public:
+ explicit month(int);
+ operator int() const;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ // A day specifier
+ class day
+ {
+ public:
+ explicit day(int);
+ day(__unnamed);
+ operator int() const;
+ };
+
+ // A day of the week specifier
+ class weekday
+ {
+ public:
+ explicit weekday(int);
+ operator int() const;
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ // A year + month specifier
+ class year_month
+ {
+ // no public members
+ };
+
+ // A month + day specifier
+ class month_day
+ {
+ // no public members
+ };
+
+ class __unnamed
+ {
+ // no public members
+ };
+
+ extern const __unnamed first;
+ extern const __unnamed second;
+ extern const __unnamed third;
+ extern const __unnamed fourth;
+ extern const __unnamed fifth;
+ extern const __unnamed last;
+
+ // Date generation functions
+
+ date operator/(year_month, day); // year(2011)/month(8)/day(19)
+ date operator/(month_day, year); // month(8)/day(19)/year(2011)
+ // day(19)/month(8)/year(2011)
+ date operator/(year_month, int); // year(2011)/month(8)/19
+ date operator/(month_day, int); // month(8)/day(19)/2011
+ // day(19)/month(8)/2011
+
+ year_month operator/(year, month); // year(2011)/month(8)
+ year_month operator/(year, int m); // year(2011)/8
+
+ month_day operator/(day, month); // day(19)/month(8)
+ month_day operator/(month, day); // month(8)/day(19)
+ month_day operator/(day, int m); // day(19)/8
+ month_day operator/(month, int d); // month(8)/19
+ month_day operator/(int m, day); // 8/day(19)
+
+ day operator*(__unnamed, weekday); // last*fri -> last*fri/aug/2011
+ day operator*(int, weekday); // 2*tue -> 2*tue/aug/2011
+
+ // Date durations
+
+ class days
+ {
+ public:
+ typedef std::int32_t rep;
+ explicit days(rep x = rep());
+
+ rep count() const;
+
+ days operator+() const;
+ days operator-() const;
+
+ days& operator++();
+ days operator++(int);
+ days& operator--();
+ days operator--(int);
+
+ days& operator+=(const days& x);
+ days& operator-=(const days& x);
+
+ days& operator*=(const rep& rhs);
+ days& operator/=(const rep& rhs);
+ days& operator%=(const rep& rhs);
+ days& operator%=(const days& rhs);
+ };
+
+ days operator+(days x, days y);
+ days operator-(days x, days y);
+ days operator*(days x, days::rep y);
+ days operator*(days::rep x, days y);
+ days operator/(days x, days::rep y);
+ days::rep operator/(days x, days y);
+ days operator%(days x, days::rep y);
+ days operator%(days x, days y);
+
+ bool operator==(days x, days y);
+ bool operator!=(days x, days y);
+ bool operator< (days x, days y);
+ bool operator> (days x, days y);
+ bool operator<=(days x, days y);
+ bool operator>=(days x, days y);
+
+ class months
+ {
+ public:
+ typedef std::int32_t rep;
+ explicit months(rep x = rep());
+
+ rep count() const;
+
+ months operator+() const;
+ months operator-() const;
+
+ months& operator++();
+ months operator++(int);
+ months& operator--();
+ months operator--(int);
+
+ months& operator+=(const months& x);
+ months& operator-=(const months& x);
+
+ months& operator*=(const rep& rhs);
+ months& operator/=(const rep& rhs);
+ months& operator%=(const rep& rhs);
+ months& operator%=(const months& rhs);
+ };
+
+ months operator+(months x, months y);
+ months operator-(months x, months y);
+ months operator*(months x, months::rep y);
+ months operator*(months::rep x, months y);
+ months operator/(months x, months::rep y);
+ months::rep operator/(months x, months y);
+ months operator%(months x, months::rep y);
+ months operator%(months x, months y);
+
+ bool operator==(months x, months y);
+ bool operator!=(months x, months y);
+ bool operator< (months x, months y);
+ bool operator> (months x, months y);
+ bool operator<=(months x, months y);
+ bool operator>=(months x, months y);
+
+ class years
+ {
+ public:
+ typedef std::int32_t rep;
+ explicit years(rep x = rep());
+
+ rep count() const;
+
+ years operator+() const;
+ years operator-() const;
+
+ years& operator++();
+ years operator++(int);
+ years& operator--();
+ years operator--(int);
+
+ years& operator+=(const years& x);
+ years& operator-=(const years& x);
+
+ years& operator*=(const rep& rhs);
+ years& operator/=(const rep& rhs);
+ years& operator%=(const rep& rhs);
+ years& operator%=(const years& rhs);
+ };
+
+ years operator+(years x, years y);
+ years operator-(years x, years y);
+ years operator*(years x, years::rep y);
+ years operator*(years::rep x, years y);
+ years operator/(years x, years::rep y);
+ years::rep operator/(years x, years y);
+ years operator%(years x, years::rep y);
+ years operator%(years x, years y);
+
+ bool operator==(years x, years y);
+ bool operator!=(years x, years y);
+ bool operator< (years x, years y);
+ bool operator> (years x, years y);
+ bool operator<=(years x, years y);
+ bool operator>=(years x, years y);
+
+ class bad_date
+ : public std::exception
+ {
+ public:
+ virtual const char* what() const noexcpt();
+ };
+
+ template<class CharT>
+ unspecified
+ date_fmt(std::basic_string<CharT> fmt);
+
+ template<class CharT>
+ unspecified
+ date_fmt(const CharT* fmt);
+
+ template<class CharT, class Traits>
+ std::basic_istream<CharT,Traits>&
+ operator>>(std::basic_istream<CharT,Traits>& is, date& d);
+
+ template<class CharT, class Traits>
+ std::basic_ostream<CharT, Traits>&
+ operator<<(std::basic_ostream<CharT, Traits>& os, const date& d);
+
+ } // julian
+
+ */
+
+#include <exception>
+#include <istream>
+#include <ostream>
+#include <locale>
+#include <stdexcept>
+#include <boost/cstdint.hpp>
+#include <boost/chrono.hpp>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/date/relative_date.hpp>
+
+namespace julian
+{
+
+ class bad_date: public std::runtime_error
+ {
+ public:
+ explicit bad_date(const std::string& s) :
+ std::runtime_error(s)
+ {
+ }
+ explicit bad_date(const char* s) :
+ std::runtime_error(s)
+ {
+ }
+ };
+
+ class date;
+ class year;
+ class month;
+ class day;
+ class weekday;
+ class year_month;
+ class month_day;
+ namespace detail
+ {
+ class day_spec;
+ day operator*(detail::day_spec, weekday);
+
+ }
+ month_day operator/(day, month);
+ month_day operator/(day, int);
+ month_day operator/(month, day);
+ month_day operator/(int, day);
+ month_day operator/(month, int);
+ year_month operator/(year, month);
+ year_month operator/(year, int);
+
+ day operator*(int, weekday);
+
+ date operator/(year_month, day);
+ date operator/(year_month, int);
+ date operator/(month_day, year);
+ date operator/(month_day, int);
+
+ class year
+ {
+ int32_t y_;
+ public:
+ explicit year(int32_t y);
+ operator int() const
+ {
+ return y_;
+ }
+
+ friend date operator/(month_day, year);
+ friend class date;
+ };
+
+ class month
+ {
+ uint8_t m_;
+ public:
+ explicit month(int);
+ operator int() const
+ {
+ return m_;
+ }
+
+ friend class date;
+ };
+
+ extern const month jan;
+ extern const month feb;
+ extern const month mar;
+ extern const month apr;
+ extern const month may;
+ extern const month jun;
+ extern const month jul;
+ extern const month aug;
+ extern const month sep;
+ extern const month oct;
+ extern const month nov;
+ extern const month dec;
+
+ class day
+ {
+ uint16_t d_ :5;
+ uint16_t n_ :3;
+ uint16_t dow_ :3;
+
+ day(uint8_t, uint8_t, uint8_t);
+ public:
+ explicit day(int);
+ day(detail::day_spec);
+ operator int() const
+ {
+ return d_;
+ }
+
+ friend date operator/(year_month, day);
+ friend day detail::operator*(detail::day_spec, weekday);
+ friend day operator*(int, weekday);
+ friend class date;
+ };
+
+ class weekday
+ {
+ int wd_;
+
+ public:
+ explicit weekday(int);
+ operator int() const
+ {
+ return wd_;
+ }
+ int value() const BOOST_NOEXCEPT
+ {
+ return wd_;
+ }
+ friend day detail::operator*(detail::day_spec, weekday);
+ };
+
+ extern const weekday sun;
+ extern const weekday mon;
+ extern const weekday tue;
+ extern const weekday wed;
+ extern const weekday thu;
+ extern const weekday fri;
+ extern const weekday sat;
+
+ class year_month
+ {
+ year y_;
+ month m_;
+ year_month(year y, month m) :
+ y_(y), m_(m)
+ {
+ }
+
+ friend year_month operator/(year y, month m)
+ {
+ return year_month(y, m);
+ }
+ friend year_month operator/(year y, int m)
+ {
+ return year_month(y, month(m));
+ }
+ friend date operator/(year_month, day);
+ };
+
+ class month_day
+ {
+ month m_;
+ day d_;
+ month_day(month m, day d) :
+ m_(m), d_(d)
+ {
+ }
+
+ friend month_day operator/(month m, day d);
+ friend month_day operator/(int m, day d);
+ friend month_day operator/(month m, int d);
+ friend month_day operator/(day d, month m);
+ friend month_day operator/(day d, int m);
+ friend date operator/(month_day, year);
+ };
+
+ inline month_day operator/(month m, day d)
+ {
+ return month_day(m, d);
+ }
+ inline month_day operator/(int m, day d)
+ {
+ return month_day(month(m), d);
+ }
+ inline month_day operator/(month m, int d)
+ {
+ return month_day(m, day(d));
+ }
+ inline month_day operator/(day d, month m)
+ {
+ return month_day(m, d);
+ }
+ inline month_day operator/(day d, int m)
+ {
+ return month_day(month(m), d);
+ }
+ day operator*(int, weekday);
+
+ namespace detail
+ {
+ class day_spec
+ {
+ uint8_t s_;
+ day_spec(uint8_t s) :
+ s_(s)
+ {
+ }
+ int value() const BOOST_NOEXCEPT
+ {
+ return s_;
+ }
+ friend day detail::operator*(day_spec s, weekday wd);
+ friend day julian::operator*(int, weekday);
+ friend day_spec make_day_spec(uint8_t);
+ friend class julian::day;
+ };
+ inline day operator*(day_spec s, weekday wd)
+ {
+ return day(1, s.s_, wd.value());
+ }
+ }
+
+ extern const detail::day_spec last;
+ extern const detail::day_spec first;
+ extern const detail::day_spec second;
+ extern const detail::day_spec third;
+ extern const detail::day_spec fourth;
+ extern const detail::day_spec fifth;
+
+// inline day operator*(detail::day_spec s, weekday wd)
+// {
+// return day(1, s.s_, wd.wd_);
+// }
+
+ template<class T, int>
+ class duration_type
+ {
+ public:
+ typedef T rep;
+ private:
+ rep x_;
+ public:
+ explicit duration_type(rep x = rep()) :
+ x_(x)
+ {
+ }
+
+ rep count() const
+ {
+ return x_;
+ }
+
+ duration_type operator+() const
+ {
+ return *this;
+ }
+ duration_type operator-() const
+ {
+ return duration_type(-x_);
+ }
+
+ duration_type& operator++()
+ { ++x_; return *this;}
+ duration_type operator++(int)
+ { return duration_type(x_++);}
+ duration_type& operator--()
+ { --x_; return *this;}
+ duration_type operator--(int)
+ { return duration_type(x_--);}
+
+ duration_type& operator+=(const duration_type& d)
+ { x_ += d.x_; return *this;}
+ duration_type& operator-=(const duration_type& d)
+ { x_ -= d.x_; return *this;}
+
+ friend duration_type operator+(duration_type x, duration_type y)
+ { x += y; return x;}
+ friend duration_type operator-(duration_type x, duration_type y)
+ { x -= y; return x;}
+
+ duration_type& operator*=(const rep& rhs)
+ { x_ *= rhs; return *this;}
+ duration_type& operator/=(const rep& rhs)
+ { x_ /= rhs; return *this;}
+ duration_type& operator%=(const rep& rhs)
+ { x_ %= rhs; return *this;}
+ duration_type& operator%=(const duration_type& rhs)
+ { x_ %= rhs.x_; return *this;}
+
+ friend duration_type operator*(duration_type x, rep y)
+ { x *= y; return x;}
+ friend duration_type operator*(rep x, duration_type y)
+ { y *= x; return y;}
+ friend duration_type operator/(duration_type x, rep y)
+ { x /= y; return x;}
+ friend rep operator/(duration_type x, duration_type y)
+ { return x.x_ / y.x_;}
+ friend duration_type operator%(duration_type x, rep y)
+ { x %= y; return x;}
+ friend duration_type operator%(duration_type x, duration_type y)
+ { x %= y.x_; return x;}
+
+ friend bool operator==(duration_type x, duration_type y)
+ { return x.x_ == y.x_;}
+ friend bool operator!=(duration_type x, duration_type y)
+ { return !(x == y);}
+ friend bool operator< (duration_type x, duration_type y)
+ { return x.x_ < y.x_;}
+ friend bool operator> (duration_type x, duration_type y)
+ { return y < x;}
+ friend bool operator<=(duration_type x, duration_type y)
+ { return !(y < x);}
+ friend bool operator>=(duration_type x, duration_type y)
+ { return !(x < y);}
+
+ friend class date;
+ };
+
+ typedef duration_type<int32_t, 0> days;
+ typedef duration_type<int32_t, 1> months;
+ typedef duration_type<int32_t, 2> years;
+
+ class date
+ {
+ uint32_t x_;
+ int16_t y_;
+ uint16_t m_ : 4;
+ uint16_t d_ : 5;
+ uint16_t leap_ : 1;
+ uint16_t n_ : 3;
+ uint16_t dow_ : 3;
+
+ date(julian::year, julian::month, julian::day);
+
+ friend date operator/(year_month ym, day d);
+ friend date operator/(month_day md, year y);
+ public:
+
+ explicit date(boost::chrono::date d);
+ // explicit
+ operator boost::chrono::date() const;
+
+ julian::day get_day() const
+ { return julian::day(d_);}
+ julian::month get_month() const
+ { return julian::month(m_);}
+ julian::year get_year() const
+ { return julian::year(y_);}
+ bool is_leap_year() const
+ { return leap_;}
+ julian::weekday get_weekday() const
+ { return julian::weekday((x_+5) % 7);}
+
+ date& operator+=(days d);
+ date& operator++()
+ { return *this += days(1);}
+ date operator++(int)
+ { date tmp(*this); ++(*this); return tmp;}
+ date& operator-=(days d)
+ { return *this += days(-d.x_);}
+ date& operator--()
+ { return *this -= days(1);}
+ date operator--(int)
+ { date tmp(*this); --(*this); return tmp;}
+
+ friend date operator+(date dt, days d)
+ { dt += d; return dt;}
+ friend date operator+(days d, date dt)
+ { dt += d; return dt;}
+ friend date operator-(date dt, days d)
+ { dt -= d; return dt;}
+ friend days operator-(date x, date y)
+ { return days(x.x_ - y.x_);}
+
+ date& operator+=(months m);
+ date& operator-=(months m)
+ { return *this += months(-m.x_);}
+
+ friend date operator+(date dt, months m)
+ { dt += m; return dt;}
+ friend date operator+(months m, date dt)
+ { dt += m; return dt;}
+ friend date operator-(date dt, months m)
+ { dt -= m; return dt;}
+
+ date& operator+=(years y);
+ date& operator-=(years y)
+ { return *this += years(-y.x_);}
+
+ friend date operator+(date dt, years y)
+ { dt += y; return dt;}
+ friend date operator+(years y, date dt)
+ { dt += y; return dt;}
+ friend date operator-(date dt, years y)
+ { dt -= y; return dt;}
+
+ friend bool operator==(const date& x, const date& y)
+ { return x.x_ == y.x_;}
+ friend bool operator< (const date& x, const date& y)
+ { return x.x_ < y.x_;}
+ friend bool operator!=(const date& x, const date& y)
+ { return !(x == y);}
+ friend bool operator> (const date& x, const date& y)
+ { return y < x;}
+ friend bool operator<=(const date& x, const date& y)
+ { return !(y < x);}
+ friend bool operator>=(const date& x, const date& y)
+ { return !(x < y);}
+ };
+
+ inline date operator/(year_month ym, day d)
+ { return date(ym.y_, ym.m_, d);}
+ inline date operator/(month_day md, year y)
+ { return date(y, md.m_, md.d_);}
+ inline date operator/(year_month ym, int d)
+ { return ym / day(d);}
+ inline date operator/(month_day md, int y)
+ { return md / year(y);}
+
+ 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;
+ charT pattern[] =
+ { '%', 'F'};
+ const charT* pb = pattern;
+ const charT* pe = pb + 2;
+ typedef boost::chrono::datepunct<charT> F;
+ std::locale loc = is.getloc();
+ if (std::has_facet<F>(loc))
+ {
+ const F& f = std::use_facet<F>(loc);
+ pb = f.get().data();
+ pe = pb + f.get().size();
+ }
+ tg.get(is, 0, is, err, &t, pb, pe);
+ if (!(err & std::ios_base::failbit))
+ item = month(t.tm_mon+1) / t.tm_mday / year(t.tm_year+1900);
+ }
+ catch (...)
+ {
+ err |= std::ios_base::badbit | std::ios_base::failbit;
+ }
+ is.setstate(err);
+ }
+ return is;
+ }
+
+ template<class charT, class traits>
+ std::basic_ostream<charT, traits>&
+ operator <<(std::basic_ostream<charT, traits>& os, const date& item)
+ {
+ typename 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.get_day();
+ t.tm_mon = item.get_month() - 1;
+ t.tm_year = item.get_year() - 1900;
+ t.tm_wday = item.get_weekday();
+ charT pattern[] =
+ { '%', 'F'};
+ const charT* pb = pattern;
+ const charT* pe = pb + 2;
+ typedef boost::chrono::datepunct<charT> F;
+ std::locale loc = os.getloc();
+ if (std::has_facet<F>(loc))
+ {
+ const F& f = std::use_facet<F>(loc);
+ pb = f.fmt().data();
+ pe = pb + f.fmt().size();
+ }
+ failed = tp.put(os, os, os.fill(), &t, pb, pe).failed();
+ }
+ catch (...)
+ {
+ failed = true;
+ }
+ if (failed)
+ os.setstate(std::ios_base::failbit | std::ios_base::badbit);
+ }
+ return os;
+ }
+
+} // julian
+
+#endif // header

Added: sandbox/chrono_date/libs/date/example/week_based_year.hpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/example/week_based_year.hpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,53 @@
+// week_base_year.hpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#ifndef BOOST_CHRONO_EXAMPLE_DATE_WEEK_BASED_YEAR_HPP
+#define BOOST_CHRONO_EXAMPLE_DATE_WEEK_BASED_YEAR_HPP
+
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/date_generators.hpp>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/date/relative_date.hpp>
+#include <boost/tuple/tuple.hpp>
+
+inline boost::tuple<int, boost::chrono::weekday, boost::chrono::year>
+date_to_week(boost::chrono::date d)
+{
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< std::endl;
+ using namespace boost::chrono;
+ month_day jan4 = jan / day(4);
+ date start = mon <= jan4 / d.get_year();
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< start << std::endl;
+ if (d < start)
+ {
+ start = mon <= jan4 / (d.get_year() - 1);
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< start << std::endl;
+ } else
+ {
+ date next_start = mon <= jan4 / (start.get_year() + 1);
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< next_start << std::endl;
+ if (d >= next_start) {
+ start = next_start;
+ std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< start << std::endl;
+ }
+ }
+ return boost::tuple<int, weekday, year>(
+ (d - start).count() / 7 + 1,
+ d.get_weekday(),
+ (thu > start).get_year()
+ );
+}
+
+inline boost::chrono::date
+week_to_date(int weeknum, boost::chrono::weekday wd, boost::chrono::year y)
+{
+ using namespace boost::chrono;
+ return (mon <= jan / day(4) / y) + days((weeknum - 1) * 7 + (wd == 0 ? 6 : wd - 1));
+}
+
+#endif // header

Added: sandbox/chrono_date/libs/date/perf/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/perf/Jamfile.v2 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,171 @@
+# Boost Chrono Library test Jamfile
+
+# Copyright Beman Dawes 2008
+# Copyright Vicente J. Botet Escriba 2009-2010
+
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt
+
+# See library home page at http://www.boost.org/libs/chrono
+
+import os ;
+import feature ;
+
+project
+ : requirements
+ <target-os>freebsd:<linkflags>"-lrt"
+ <target-os>linux:<linkflags>"-lrt"
+ <toolset>pgi:<linkflags>"-lrt"
+ #<threading>single:<define>BOOST_CHRONO_THREAD_DISABLED
+ <toolset>msvc:<asynch-exceptions>on
+ <define>BOOST_CHRONO_USES_MPL_ASSERT
+ <define>BOOST_SYSTEM_NO_DEPRECATED
+ <toolset>sun:<define>BOOST_TYPEOF_EMULATION
+ <warnings>all
+ <toolset>gcc:<cxxflags>-Wextra
+ <toolset>gcc:<cxxflags>-pedantic
+ <toolset>gcc:<cxxflags>-Wno-long-long
+ <toolset>darwin:<cxxflags>-Wextra
+ <toolset>darwin:<cxxflags>-pedantic
+ <toolset>darwin:<cxxflags>-Wno-long-long
+ #<toolset>pathscale:<cxxflags>-Wextra
+ <toolset>pathscale:<cxxflags>-Wno-long-long
+ <toolset>pathscale:<cxxflags>-pedantic
+ <toolset>clang:<cxxflags>-Wextra
+ <toolset>clang:<cxxflags>-pedantic
+ <toolset>clang:<cxxflags>-Wno-long-long
+ <toolset>gcc-mingw-4.5.0:<cxxflags>-Wno-missing-field-initializers
+ <toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
+ <toolset>msvc:<cxxflags>/wd4127
+# Note: Some of the remarks from the Intel compiler are disabled
+# remark #304: access control not specified ("public" by default)
+# remark #383: value copied to temporary, reference to temporary used
+# remark #1418: external function definition with no prior declaration
+ <toolset>intel:<cxxflags>-wd304,383,1418
+ ;
+
+rule chrono-run ( sources )
+{
+ return
+ [ run $(sources) ../build//boost_chrono
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(sources[1]:B)_shared ]
+ [ run $(sources) ../build//boost_chrono/<link>static
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(sources[1]:B)_static ]
+ [ run $(sources)
+ : :
+ : <define>BOOST_CHRONO_HEADER_ONLY
+ # comment one of the following lines
+ #<define>BOOST_SYSTEM_INLINED
+ <library>/boost/system//boost_system
+ : $(sources[1]:B)_header ]
+ ;
+}
+rule chrono-run2 ( sources : name )
+{
+ return
+ [ run $(sources) ../build//boost_chrono
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(name)_shared ]
+ [ run $(sources) ../build//boost_chrono/<link>static
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(name)_static ]
+ [ run $(sources)
+ : :
+ : <define>BOOST_CHRONO_HEADER_ONLY
+ # comment one of the following lines
+ #<define>BOOST_SYSTEM_INLINED
+ <library>/boost/system//boost_system
+ : $(name)_header ]
+ ;
+}
+
+
+rule chrono-run-mt ( sources )
+{
+ return
+ [ run $(sources) ../build//boost_chrono
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(sources[1]:B)_shared ]
+ [ run $(sources) ../build//boost_chrono/<link>static
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(sources[1]:B)_static ]
+ [ run $(sources)
+ : :
+ : <define>BOOST_CHRONO_HEADER_ONLY
+ # comment one of the following lines
+ #<define>BOOST_SYSTEM_INLINED
+ <library>/boost/system//boost_system
+ : $(sources[1]:B)_header ]
+ ;
+}
+rule chrono-run2-mt ( sources : name )
+{
+ return
+ [ run $(sources) ../build//boost_chrono
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(name)_shared ]
+ [ run $(sources) ../build//boost_chrono/<link>static
+ : :
+ :
+ <library>/boost/system//boost_system
+ : $(name)_static ]
+ [ run $(sources)
+ : :
+ : <define>BOOST_CHRONO_HEADER_ONLY
+ # comment one of the following lines
+ #<define>BOOST_SYSTEM_INLINED
+ <library>/boost/system//boost_system
+ : $(name)_header ]
+ ;
+}
+rule chrono-compile ( sources )
+{
+ return
+ [ compile $(sources)
+ :
+ : $(sources[1]:B)_lib ]
+ [ compile $(sources)
+ : <define>BOOST_CHRONO_HEADER_ONLY
+ # comment the following line
+ <define>BOOST_SYSTEM_INLINED
+ : $(sources[1]:B)_header ]
+ ;
+}
+
+rule chrono-compile2 ( sources : name )
+{
+ return
+ [ compile $(sources)
+ :
+ : $(name)_lib ]
+ [ compile $(sources)
+ : <define>BOOST_CHRONO_HEADER_ONLY
+ # comment the following line
+ <define>BOOST_SYSTEM_INLINED
+ : $(name)_header ]
+ ;
+}
+
+ test-suite "perf"
+ :
+ [ chrono-run store_now_in_vector.cpp ]
+ [ chrono-run is_leap.cpp ]
+ [ chrono-run no_check.cpp ]
+ ;
+

Added: sandbox/chrono_date/libs/date/perf/no_check.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/perf/no_check.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,194 @@
+// Copyright 2011 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/chrono.hpp>
+#include <boost/chrono/chrono_io.hpp>
+#include <boost/chrono/date/date.hpp>
+
+using namespace boost::chrono;
+const int times = 100;
+int main()
+{
+ typedef boost::chrono::high_resolution_clock Clock;
+ typedef boost::chrono::duration<double> sec;
+ //////////////////////
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ cnt += y+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << "none: " << t1 - t0 << " " << cnt << "\n";
+ }
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y,no_check);
+ cnt += year(y,no_check)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << "no_check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y);
+ cnt += year(y)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << " check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ //////////////////////
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ cnt += y+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << "none: " << t1 - t0 << " " << cnt << "\n";
+ }
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y,no_check);
+ cnt += year(y,no_check)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << "no_check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y);
+ cnt += year(y)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << " check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ //////////////////////
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ cnt += y+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << "none: " << t1 - t0 << " " << cnt << "\n";
+ }
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y,no_check);
+ cnt += year(y,no_check)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << "no_check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y);
+ cnt += year(y)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ std::cout << " check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ Clock::duration none_d;
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ cnt += y+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ none_d=t1 - t0;
+ std::cout << "none: " << t1 - t0 << " " << cnt << "\n";
+ }
+ Clock::duration no_check_d;
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y,no_check);
+ cnt += year(y,no_check)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ no_check_d=t1 - t0;
+ std::cout << "no_check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ Clock::duration check_d;
+ {
+ int cnt = 0;
+ Clock::time_point t0 = Clock::now();
+ for (int x = 0; x < times; ++x)
+ for (int y = -32768; y <= 32767; ++y)
+ {
+ //year aYear(y);
+ cnt += year(y)+x;
+ //if (cnt %4096==0) std::cout << cnt << " ";
+ }
+ //std::cout << std::endl;
+ Clock::time_point t1 = Clock::now();
+ check_d=t1 - t0;
+ std::cout << " check: " << t1 - t0 << " " << cnt << "\n";
+ }
+ std::cout << " check-none: " << (check_d-none_d) << "\n";
+ std::cout << " no_check-none: " << (no_check_d-none_d) << "\n";
+
+ return 1;
+
+}

Added: sandbox/chrono_date/libs/date/src/conversions.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/src/conversions.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,148 @@
+// date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <algorithm>
+#include <boost/chrono/date/conversions.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+
+// year_month_day to_ymd2(days dt) BOOST_NOEXCEPT
+// {
+// days::rep x=dt.count();
+// year::rep y = static_cast<year::rep>(static_cast<int64_t> (x + 2) * 400 / 146097);
+// const year::rep ym1 = y - 1;
+// day_of_year::rep doy = x - days_before_year(y);
+// const day_of_year::rep doy1 = x - days_before_year(ym1);
+// const int N = std::numeric_limits<int>::digits - 1;
+// const int mask1 = doy >> N; // arithmetic rshift - not portable - but nearly universal
+// const int mask0 = ~mask1;
+// doy = (doy & mask0) | (doy1 & mask1);
+// y = (y & mask0) | (ym1 & mask1);
+// y += (year::first_-1);
+// const bool leap = is_leap(y);
+// const month::rep m = day_of_year_month(leap,doy);
+// const day::rep d = day_of_year_day_of_month(leap,doy);
+// return year_month_day(y, m, d, no_check);
+//
+// }
+// year_month_day_leap to_ymd_leap2(days dt) BOOST_NOEXCEPT
+// {
+// days::rep x=dt.count();
+// year::rep y = static_cast<year::rep>(static_cast<int64_t> (x + 2) * 400 / 146097);
+// const year::rep ym1 = y - 1;
+// day_of_year::rep doy = x - days_before_year(y);
+// const day_of_year::rep doy1 = x - days_before_year(ym1);
+// const int N = std::numeric_limits<int>::digits - 1;
+// const int mask1 = doy >> N; // arithmetic rshift - not portable - but nearly universal
+// const int mask0 = ~mask1;
+// doy = (doy & mask0) | (doy1 & mask1);
+// y = (y & mask0) | (ym1 & mask1);
+// y += (year::first_-1);
+// const bool leap = is_leap(y);
+// const month::rep m = day_of_year_month(leap,doy);
+// const day::rep d = day_of_year_day_of_month(leap,doy);
+// return year_month_day_leap(y, m, d, leap, no_check);
+//
+// }
+ year_month_day to_ymd(days dt) BOOST_NOEXCEPT
+ {
+ days::rep x_ = dt.count();
+// std::cout <<"days " << x_ << std::endl;
+ year::rep y = static_cast<year::rep>(static_cast<int64_t>(x_ + 2) * 400 / 146097);
+// std::cout <<"y " << y << std::endl;
+ int doy = x_ - days_before_year(y);
+// std::cout <<"doy " << doy << std::endl;
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - days_before_year(y);
+// std::cout <<"y " << y << std::endl;
+// std::cout <<"doy " << doy << std::endl;
+ }
+ //y += (year::first_-1);
+ y -= 32799;
+// std::cout <<"y " << y << std::endl;
+ const bool leap = is_leap(y);
+ const month::rep m = day_of_year_month(leap,doy+1);
+// std::cout <<"m " << int(m) << std::endl;
+ const day::rep d = day_of_year_day_of_month(leap,doy+1);
+// std::cout <<"d " << int(d) << std::endl;
+ return year_month_day(y, m, d, no_check);
+ }
+ year_month_day_leap to_ymd_leap(days dt) BOOST_NOEXCEPT
+ {
+ days::rep x_ = dt.count();
+ year::rep y = static_cast<year::rep>(static_cast<int64_t>(x_ + 2) * 400 / 146097);
+ int doy = x_ - days_before_year(y);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - days_before_year(y);
+ }
+ //y += (year::first_-1);
+ y -= 32799;
+ const bool leap = is_leap(y);
+ const month::rep m = day_of_year_month(leap,doy+1);
+ const day::rep d = day_of_year_day_of_month(leap,doy+1);
+ return year_month_day_leap(y, m, d, leap, no_check);
+ }
+
+ days to_days(year_month_day dt) BOOST_NOEXCEPT
+ {
+ bool leap = dt.get_year().is_leap();
+ //year::rep by = dt.get_year().value() - (year::first_-1);
+ year::rep by = dt.get_year().value() - 32799;
+ return days(days_before_year(by) +
+ days_in_year_before(leap,dt.get_month().value()-1) +
+ dt.get_day().value());
+ }
+
+ days to_days(year_day_of_year dt) BOOST_NOEXCEPT
+ {
+ return days(days_before_year(dt.get_year())+dt.get_day_of_year());
+ }
+
+ year_month_day to_ymd(year_day_of_year dt) BOOST_NOEXCEPT
+ {
+ bool leap=dt.get_year().is_leap();
+ return year_month_day(dt.get_year(), day_of_year_month(leap,dt.get_day_of_year()), day_of_year_day_of_month(leap,dt.get_day_of_year()), no_check);
+ }
+
+
+ year_day_of_year to_ydoy(days dt) BOOST_NOEXCEPT
+ {
+
+ days::rep x_=dt.count();
+ int y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (days_before_year(y));
+ }
+ y -= 32799;
+ return year_day_of_year(y, doy+1, no_check);
+ }
+
+
+ year_day_of_year to_ydoy(year_month_day dt) BOOST_NOEXCEPT
+ {
+ day_of_year::rep doy = month_day_to_day_of_year(dt.get_year().is_leap(),dt.get_month(),dt.get_day());
+ return year_day_of_year(dt.get_year(), doy+1, no_check);
+ }
+
+
+ } // chrono
+} // boost
+
+

Added: sandbox/chrono_date/libs/date/src/date.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/src/date.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,540 @@
+// date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <algorithm>
+#include <ctime>
+#include <string>
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/days_date.hpp>
+#include <boost/chrono/date/date.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/chrono/date/conversions.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+
+#if defined BOOST_CHRONO_DATE_DATE_DESIGN_BUG && BOOST_CHRONO_DATE_DATE_DESIGN == 2
+namespace boost
+{
+ namespace chrono
+ {
+
+
+
+
+
+// static
+// const int
+// is_leap_table_[400] =
+// { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0
, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 };
+// /**
+// * is_leap could be implemented by using a table indexed by the y % 400.
+// * This table could contain true for y such as
+// * y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)
+// *
+// * is_leap = is_leap_table[y%400]
+// */
+//
+// static
+// inline
+// bool
+// is_leap_table(int y)
+// BOOST_NOEXCEPT
+// {
+// return is_leap_table_[y%400];
+// }
+
+
+ /**
+ * from_ymd could be made more efficient by using a table
+ * day_count_table indexed by the y%400.
+ * This table could contain the day_count
+ * by*365 + by/4 - by/100 + by/400
+ *
+ * from_ymd = (by/400)*days_by_400_years+day_count_table[by%400] +
+ * days_in_year_before[is_leap_table[by%400]][m-1] + d;
+ */
+
+
+ days::rep from_ymd(int32_t y, int32_t m, int32_t d) BOOST_NOEXCEPT
+ {
+ //days::rep by = y + (-year::first_ +1) + 2;
+ days::rep by = y + 32799;
+ return days_before_year(by) + days_in_year_before(is_leap(by),m - 1) + d;
+ }
+
+ boost::tuple<year::rep, month::rep, day::rep> to_ymd(days::rep x) BOOST_NOEXCEPT
+ {
+ year::rep y = static_cast<year::rep> (static_cast<long long> (x + 2) * 400
+ / 146097);
+ const year::rep ym1 = y - 1;
+ day_of_year::rep doy = x - days_before_year(y);
+ const day_of_year::rep doy1 = x - days_before_year(ym1);
+ const int N = std::numeric_limits<int>::digits - 1;
+ const int mask1 = doy >> N; // arithmetic rshift - not portable - but nearly universal
+ const int mask0 = ~mask1;
+ doy = (doy & mask0) | (doy1 & mask1);
+ y = (y & mask0) | (ym1 & mask1);
+ //y += (year::first_-1);
+ y -= 32799);
+ const bool leap = is_leap(y);
+ const month::rep m = day_of_year_month(leap,doy);
+ const day::rep d = doy - days_in_year_before(leap,m - 1);
+ return boost::make_tuple(y, m, d);
+
+ }
+
+ static inline year::rep
+ year_of(days::rep x_) BOOST_NOEXCEPT
+ {
+ int y = to_average_year(x_);
+ int doy = x_ - days_before_year(y);
+ if (doy < 0)
+ {
+ --y;
+ }
+ y -= 32799;
+ return static_cast<year::rep>(y);
+ }
+
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1
+
+ date::date() BOOST_NOEXCEPT
+ : x_(11979588),
+ y_(0),
+ m_(1),
+ d_(1),
+ leap_(1)
+ {
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+
+ date::date() BOOST_NOEXCEPT
+ : x_(11979588)
+ {
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+
+ date::date() BOOST_NOEXCEPT
+ : y_(0),
+ m_(1),
+ d_(1),
+ leap_(1)
+ {
+ }
+
+#endif
+
+ date
+ date::today() BOOST_NOEXCEPT
+ {
+ time_t systime;
+ time(&systime);
+ tm now;
+ localtime_r(&systime, &now);
+ //return chrono::year(now.tm_year+1900,no_check)/chrono::month(now.tm_mon+1,no_check)/chrono::day(now.tm_mday,no_check);
+ return date(chrono::year(now.tm_year+1900),chrono::month(now.tm_mon+1),chrono::day(now.tm_mday));
+ }
+
+ date::date(boost::chrono::system_clock::time_point tp)
+ {
+ time_t systime = boost::chrono::system_clock::to_time_t(tp);
+ tm now;
+ gmtime_r(&systime, &now);
+ *this = date(chrono::year(now.tm_year + 1900)
+ , chrono::month(now.tm_mon + 1)
+ , chrono::day(now.tm_mday));
+// *this = chrono::year(now.tm_year + 1900, no_check)
+// / chrono::month(now.tm_mon + 1, no_check)
+// / chrono::day(now.tm_mday, no_check);
+ }
+
+ date::operator boost::chrono::system_clock::time_point() const
+ {
+ tm now =
+ { 0 };
+ now.tm_year = get_year() - 1900;
+ now.tm_mon = get_month() - 1;
+ now.tm_mday = get_day();
+ time_t t = timegm(&now);
+ return boost::chrono::system_clock::from_time_t(t);
+ }
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ bool date::is_valid() const BOOST_NOEXCEPT
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_ - 1]))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+
+ }
+#endif
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1
+ bool date::set_if_valid_date(year y,month m,day d) BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return false;
+ }
+ y_ = y.value();
+ m_ = m.value();
+ d_ = d.value();
+ leap_ = leap;
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+ return true;
+ }
+
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+ bool date::set_if_valid_date(year y,month m,day d) BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y.value());
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d.value() <= year_data[m.value()] - year_data[m.value()-1]))
+ {
+ return false;
+ }
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[m.value()-1] + d.value();
+ return true;
+
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+ bool date::set_if_valid_date(year y,month m,day d) BOOST_NOEXCEPT
+ {
+ bool leap = y.is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d <= year_data[m] - year_data[m-1]))
+ {
+ return false;
+ }
+ y_ = y.value();
+ m_ = m.value();
+ d_ = d.value();
+ leap_ = leap;
+ return true;
+
+ }
+
+#endif
+
+ optional_date make_valid_date(year y, month m, day d) BOOST_NOEXCEPT
+ {
+ date res;
+ if (res.set_if_valid_date(y,m,d)) return optional_date(res);
+ else return optional_date();
+
+ }
+
+ date::date(chrono::year y, chrono::month m, chrono::day d)
+ {
+ if (set_if_valid_date(y,m,d)) return;
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y) + '-' + to_string(m));
+ }
+ date::date(chrono::year y, chrono::month_day md)
+ {
+ if (set_if_valid_date(y,md.get_month(), md.get_day())) return;
+ throw bad_date("day " + to_string(md.get_day()) + " is out of range for "
+ + to_string(y) + '-' + to_string(md.get_month()));
+ }
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1
+
+ date::date(year::rep y, month::rep m, day::rep d, no_check_t) BOOST_NOEXCEPT
+ : y_(y), m_(m), d_(d)
+ {
+ leap_ = is_leap(y_);
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+
+ int32_t by = y_ + 32799;
+ x_ = days_before_year(by) + year_data[m_ - 1] + d_;
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+
+ date::date(year::rep y, month::rep m, day::rep d, no_check_t) BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ int32_t by = y + 32799;
+ x_ = days_before_year(by) + year_data[m-1] + d;
+ }
+
+ date::date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[m-1] + d;
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+
+ date::date(year::rep y, month::rep m, day::rep d, no_check_t) BOOST_NOEXCEPT
+ : y_(y),
+ m_(m),
+ d_(d),
+ leap_(is_leap(y_))
+ {
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1
+
+ date&
+ date::operator+=(days d)
+ {
+ x_ += d.count();
+ if (!(11322 <= x_ && x_ <= 23947853))
+ {
+ throw bad_date("year is out of range [-32768, 32767]");
+ }
+ year::rep y = to_average_year(x_);
+ int doy = x_ - days_before_year(y);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - days_before_year(y);
+ }
+ y_ = static_cast<int16_t> (y - 32799);
+ leap_ = is_leap(y_);
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ m_
+ = static_cast<uint16_t> (std::lower_bound(year_data, year_data + 13, doy)
+ - year_data);
+ d_ = static_cast<uint16_t> (doy - year_data[m_ - 1]);
+
+ return *this;
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+
+ date&
+ date::operator+=(days d)
+ {
+ x_ += d.count();
+ if (!(11322 <= x_ && x_ <= 23947853))
+ {
+ throw bad_date("year is out of range [-32768, 32767]");
+ }
+
+ return *this;
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 3
+
+ date&
+ date::operator+=(days d)
+ {
+ days::rep x = day_number_from_ymd() + d.count();
+ if (!(11322 <= x && x <= 23947853))
+ {
+ throw bad_date("year is out of range [-32768, 32767]");
+ }
+ year::rep y = to_average_year(x);
+ int doy = x - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x - (days_before_year(y));
+ }
+ y_ = static_cast<int16_t>(y - 32799);
+ leap_ = is_leap(y_);
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ m_ = static_cast<uint16_t>(std::lower_bound(year_data, year_data+13, doy)
+ - year_data);
+ d_ = static_cast<uint16_t>(doy - year_data[m_-1]);
+
+ return *this;
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_DATE_DESIGN == 3
+
+ date&
+ date::operator+=(months mn)
+ {
+ int32_t y = y_;
+ int32_t m = m_;
+ m += mn.count();
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ } else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ *this = chrono::day(d_) / chrono::month(m, no_check) / y;
+ return *this;
+ }
+
+ date&
+ date::operator+=(years yr)
+ {
+ *this = chrono::day(d_) / chrono::month(m_, no_check) / (y_ + yr.count());
+ return *this;
+ }
+
+#elif BOOST_CHRONO_DATE_DATE_DESIGN == 2
+
+ date&
+ date::operator+=(months mn)
+ {
+ int y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (days_before_year(y));
+ }
+ y -= 32799;
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ int m = std::lower_bound(year_data, year_data+13, doy) - year_data;
+ int d = doy - year_data[m-1];
+ m += mn.count();
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ }
+ else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ *this = chrono::day(d)/chrono::month(m)/y;
+ return *this;
+ }
+
+ date&
+ date::operator+=(years yr)
+ {
+ int y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (days_before_year(y));
+ }
+ y -= 32799;
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ int m = std::lower_bound(year_data, year_data+13, doy) - year_data;
+ int d = doy - year_data[m-1];
+ *this = date(y + yr.count(), m, d, no_check);
+ return *this;
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 2
+
+ day::rep
+ date::day_from_day_number() const BOOST_NOEXCEPT
+ {
+ year_day_of_year ydoy = to_ydoy(days(x_));
+ return day_of_year_day_of_month(is_leap(ydoy.get_year()),ydoy.get_day_of_year());
+// int m = std::lower_bound(year_data, year_data+13, ydoy.get_day_of_year()) - year_data;
+// return static_cast<uint16_t>(ydoy.get_day_of_year() - year_data[m-1]);
+
+// int y = to_average_year(x_);
+// int doy = x_ - (days_before_year(y));
+// if (doy < 0)
+// {
+// --y;
+// doy = x_ - (days_before_year(y));
+// }
+// y -= 32799;
+// const day_of_year::rep* year_data = days_in_year_before(is_leap(y));
+// int m = std::lower_bound(year_data, year_data+13, doy) - year_data;
+// return static_cast<uint16_t>(doy - year_data[m-1]);
+ }
+
+ month::rep
+ date::month_from_day_number() const BOOST_NOEXCEPT
+ {
+ year_day_of_year ydoy = to_ydoy(days(x_));
+ return day_of_year_month(is_leap(ydoy.get_year()),ydoy.get_day_of_year());
+
+// int y = to_average_year(x_);
+// int doy = x_ - (days_before_year(y));
+// if (doy < 0)
+// {
+// --y;
+// doy = x_ - (days_before_year(y));
+// }
+// y -= 32799;
+// const day_of_year::rep* year_data = days_in_year_before(is_leap(y));
+// return std::lower_bound(year_data, year_data+13, doy) - year_data;
+ }
+
+ year::rep
+ date::year_from_day_number() const BOOST_NOEXCEPT
+ {
+ int y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ }
+ y -= 32799;
+ return static_cast<int16_t>(y);
+ }
+
+ bool
+ date::leap_from_day_number() const BOOST_NOEXCEPT
+ {
+ return is_leap(year_from_day_number());
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_DATE_DESIGN == 3
+
+ days::rep
+ date::day_number_from_ymd() const BOOST_NOEXCEPT
+ {
+ days::rep by = y_ + 32799;
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ return days_before_year(by) + year_data[m_-1] + d_;
+ }
+
+#endif
+
+ } // chrono
+} // boost
+#endif
+
+

Added: sandbox/chrono_date/libs/date/src/days_date.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/src/days_date.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,260 @@
+// days_date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <algorithm>
+#include <ctime>
+#include <boost/chrono/date/days_date.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/chrono/date/conversions.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ days_date
+ days_date::today()
+ BOOST_NOEXCEPT
+ {
+ time_t systime;
+ time(&systime);
+ tm now;
+ localtime_r(&systime, &now);
+ return days_date(now.tm_year+1900,now.tm_mon+1, now.tm_mday, no_check);
+ }
+
+ days_date::days_date(boost::chrono::system_clock::time_point tp)
+ {
+ time_t systime = boost::chrono::system_clock::to_time_t(tp);
+ tm now;
+ gmtime_r(&systime, &now);
+ *this
+ = days_date(now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, no_check);
+ }
+
+ days_date::operator boost::chrono::system_clock::time_point() const
+ {
+ tm now = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ now.tm_year = get_year() - 1900;
+ now.tm_mon = get_month() - 1;
+ now.tm_mday = get_day();
+ time_t t = timegm(&now);
+ return boost::chrono::system_clock::from_time_t(t);
+ }
+
+ bool days_date::set_if_valid_date(year y, month m, day d)
+ BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y.value());
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d.value() <= year_data[m.value()] - year_data[m.value()-1]))
+ {
+ return false;
+ }
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[m.value()-1] + d.value();
+ return true;
+
+ }
+
+ days_date::days_date(chrono::year y, chrono::month m, chrono::day d)
+ {
+ if (set_if_valid_date(y, m, d))
+ return;
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y) + '-' + to_string(m));
+ }
+ days_date::days_date(chrono::year y, chrono::month_day md)
+ {
+ if (set_if_valid_date(y, md.get_month(), md.get_day()))
+ return;
+ throw bad_date("day " + to_string(md.get_day()) + " is out of range for "
+ + to_string(y) + '-' + to_string(md.get_month()));
+ }
+
+ days_date::days_date(year::rep y, chrono::month_day md, no_check_t)
+ BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[md.get_month()-1] + md.get_day();
+ }
+ days_date::days_date(year::rep y, month::rep m, day::rep d, no_check_t)
+ BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[m-1] + d;
+ }
+
+ days_date::days_date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t)
+ BOOST_NOEXCEPT
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[m-1] + d;
+ }
+
+ days_date::days_date(chrono::year y, chrono::day_of_year doy)
+ {
+ if (!y.is_leap() && doy == 366)
+ throw bad_date("doy " + to_string(doy) + " is out of range for year "
+ + to_string(y) );
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + doy - 1;
+ }
+ days_date::days_date(year::rep y, day_of_year::rep doy, no_check_t)
+ BOOST_NOEXCEPT
+ {
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + doy - 1;
+ }
+
+ days_date&
+ days_date::operator+=(days d)
+ {
+ x_ += d.count();
+ if (!(11322 <= x_ && x_ <= 23947853))
+ {
+ throw bad_date("year is out of range [-32768, 32767]");
+ }
+
+ return *this;
+ }
+
+ days_date&
+ days_date::operator+=(months mn)
+ {
+ //std::cout <<__FILE__<<"["<< __LINE__ <<"]"<< *this << '\n';
+ // to_ymd
+ int y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (days_before_year(y));
+ }
+ y -= 32799;
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ int m = std::lower_bound(year_data, year_data + 13, doy) - year_data;
+ int d = doy - year_data[m - 1];
+ // std::cout <<__FILE__<<"["<< __LINE__ <<":"<< y<<"]"<<m<<":"<<d << '\n';
+
+ // increase month
+ m += mn.count();
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ }
+ else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ // std::cout <<__FILE__<<"["<< __LINE__ <<"]"<< y<<":"<<m<<":"<<d << '\n';
+ // validity check and assignment
+ *this
+ = days_date(chrono::year(y), chrono::month(m, no_check), chrono::day(d, no_check));
+
+ return *this;
+ }
+
+ days_date&
+ days_date::operator+=(years yr)
+ {
+ int y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (days_before_year(y));
+ }
+ y -= 32799;
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ int m = std::lower_bound(year_data, year_data + 13, doy) - year_data;
+ int d = doy - year_data[m - 1];
+ // std::cout <<__FILE__<<"["<< __LINE__ <<"]"<< y<<":"<<m<<":"<<d << '\n';
+ *this
+ = days_date(chrono::year(y + yr.count()), chrono::month(m, no_check), chrono::day(d));
+ return *this;
+ }
+
+ day::rep
+ days_date::day_from_day_number() const
+ BOOST_NOEXCEPT
+ {
+ year_day_of_year ydoy = to_ydoy(days(x_));
+ return day_of_year_day_of_month(is_leap(ydoy.get_year()),ydoy.get_day_of_year());
+ // int y = to_average_year(x_);
+ // int doy = x_ - (days_before_year(y));
+ // if (doy < 0)
+ // {
+ // --y;
+ // doy = x_ - (days_before_year(y));
+ // }
+ // y -= 32799;
+ // const day_of_year::rep* year_data = days_in_year_before(is_leap(y));
+ // int m = std::lower_bound(year_data, year_data+13, doy) - year_data;
+ // return static_cast<uint16_t>(doy - year_data[m-1]);
+ }
+
+ month::rep
+ days_date::month_from_day_number() const
+ BOOST_NOEXCEPT
+ {
+ year_day_of_year ydoy = to_ydoy(days(x_));
+ return day_of_year_month(is_leap(ydoy.get_year()),ydoy.get_day_of_year());
+
+ // int y = to_average_year(x_);
+ // int doy = x_ - (days_before_year(y));
+ // if (doy < 0)
+ // {
+ // --y;
+ // doy = x_ - (days_before_year(y));
+ // }
+ // y -= 32799;
+ // const day_of_year::rep* year_data = days_in_year_before(is_leap(y));
+ // return std::lower_bound(year_data, year_data+13, doy) - year_data;
+ }
+
+ year::rep
+ days_date::year_from_day_number() const
+ BOOST_NOEXCEPT
+ {
+ int y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ }
+ y -= 32799;
+ return static_cast<int16_t>(y);
+ }
+
+ bool
+ days_date::leap_from_day_number() const
+BOOST_NOEXCEPT {
+ return is_leap(year_from_day_number());
+ }
+
+} // chrono
+} // boost
+
+

Added: sandbox/chrono_date/libs/date/src/rel_date.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/src/rel_date.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,1494 @@
+// date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <algorithm>
+#include <ctime>
+#include <string>
+#include <boost/chrono/date/date_generators.hpp>
+#include <boost/chrono/date/conversions.hpp>
+#include <boost/chrono/date/date.hpp>
+#include <boost/chrono/date/relative_date.hpp>
+#include <boost/chrono/date/detail/to_string.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ rel_date::rel_date()
+ BOOST_NOEXCEPT
+ : x_(11979588),
+ y_(0),
+ m_(1),
+ leap_(1),
+ dow_(weekday::not_applicable),
+ d_(1),
+ n_(nth_week::not_applicable)
+ {
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date::rel_date()
+ BOOST_NOEXCEPT
+ : x_(11979588),
+ n_(nth_week::not_applicable),
+ dow_(weekday::not_applicable)
+ {
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date::rel_date() BOOST_NOEXCEPT
+ : y_(0),
+ m_(1),
+ leap_(1),
+ dow_(weekday::not_applicable),
+ d_(1),
+ n_(nth_week::not_applicable)
+ {
+ }
+
+#endif
+#if BOOST_CHRONO_DATE_REL_DATE_IS_A_MODEL_OF_DATE
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::day d)
+ :
+ y_(y),
+ m_(m),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(d),
+ n_(nth_week::not_applicable)
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return throw bad_date("");
+ }
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::day d)
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return throw bad_date("");
+ }
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::day d)
+ :
+ y_(y),
+ m_(m),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(d),
+ n_(nth_week::not_applicable)
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return throw bad_date("bbbbbbbbbbbb");
+ }
+
+ }
+#endif
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ rel_date::rel_date(chrono::year::rep y, chrono::month::rep m, chrono::day::rep d, no_check_t) BOOST_NOEXCEPT
+ :
+ y_(y),
+ m_(m),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(d),
+ n_(nth_week::not_applicable)
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date::rel_date(chrono::year::rep y, chrono::month::rep m, chrono::day::rep d, no_check_t)BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date::rel_date(chrono::year::rep y, chrono::month::rep m, chrono::day::rep d, no_check_t)BOOST_NOEXCEPT
+ :
+ y_(y),
+ m_(m),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(d),
+ n_(nth_week::not_applicable)
+ {
+ }
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ rel_date::rel_date(chrono::year y, chrono::month_day md)
+ :
+ y_(y),
+ m_(md.get_month()),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(md.get_day()),
+ n_(nth_week::not_applicable)
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (!(md.get_day() <= year_data[md.get_month()] - year_data[md.get_month() - 1]))
+ {
+ return throw bad_date("");
+ }
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[md.get_month() - 1] + md.get_day();
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date::rel_date(chrono::year y, chrono::month_day md)
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ if (!(md.get_day() <= year_data[md.get_month()] - year_data[md.get_month() - 1]))
+ {
+ return throw bad_date("");
+ }
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[md.get_month() - 1] + md.get_day();
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date::rel_date(chrono::year y, chrono::month_day md)
+ :
+ y_(y),
+ m_(md.get_month()),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(md.get_day()),
+ n_(nth_week::not_applicable)
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (!(d_ <= year_data[m_] - year_data[m_ - 1]))
+ {
+ return throw bad_date("");
+ }
+
+ }
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ rel_date::rel_date(chrono::year::rep y, chrono::month_day md, no_check_t)
+ BOOST_NOEXCEPT :
+ y_(y),
+ m_(md.get_month()),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(md.get_day()),
+ n_(nth_week::not_applicable)
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[md.get_month() - 1] + md.get_day();
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date::rel_date(chrono::year::rep y, chrono::month_day md, no_check_t)
+ BOOST_NOEXCEPT {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[md.get_month() - 1] + md.get_day();
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date::rel_date(chrono::year::rep y, chrono::month_day md, no_check_t)
+ BOOST_NOEXCEPT :
+ y_(y),
+ m_(md.get_month()),
+ leap_(is_leap(y)),
+ dow_(weekday::not_applicable),
+ d_(md.get_day()),
+ n_(nth_week::not_applicable)
+ {
+ }
+#endif
+
+ rel_date::rel_date(chrono::days d)
+ {
+ if (set_if_valid_date(d))
+ return;
+ throw bad_date("days " + to_string(d.count()) + " is out of range");
+ }
+
+
+ rel_date::rel_date(chrono::year y, chrono::day_of_year doy)
+ {
+ if (set_if_valid_date(y, doy))
+ return;
+ throw bad_date("doy " + to_string(doy) + " is out of range for year "
+ + to_string(y) );
+ }
+
+//#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+//
+// rel_date::rel_date(year::rep y, day_of_year::rep d, no_check_t) // TODO
+// BOOST_NOEXCEPT
+// {
+//
+// }
+//
+//
+//
+//#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+//
+// rel_date::rel_date(year::rep y, day_of_year::rep d, no_check_t)// TODO
+// BOOST_NOEXCEPT
+// {
+//
+// }
+//
+//
+//#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+//
+// rel_date::rel_date(year::rep y, day_of_year::rep d, no_check_t)// TODO
+// BOOST_NOEXCEPT
+// {
+//
+// }
+//
+//
+//#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ bool rel_date::set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return false;
+ }
+ y_ = y.value();
+ m_ = m.value();
+ d_ = d.value();
+ leap_ = leap;
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return true;
+ }
+
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ bool rel_date::set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y.value());
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d.value() <= year_data[m.value()] - year_data[m.value()-1]))
+ {
+ return false;
+ }
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[m.value()-1] + d.value();
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return true;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ bool rel_date::set_if_valid_date(year y, month m, day d) BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return false;
+ }
+ y_ = y.value();
+ m_ = m.value();
+ d_ = d.value();
+ leap_ = leap;
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return true;
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ bool rel_date::set_if_valid_date(year y, day_of_year doy) BOOST_NOEXCEPT
+
+ {
+ bool leap = is_leap(y);
+ if (!leap && doy == 366)
+ return false;
+
+ y_ = y.value();
+ m_ = day_of_year_month(leap,doy);
+ d_ = day_of_year_day_of_month(leap,doy);
+ leap_ = leap;
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + doy -1;
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return true;
+ }
+
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ bool rel_date::set_if_valid_date(year y, day_of_year doy) BOOST_NOEXCEPT// TODO
+ {
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return false;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ bool rel_date::set_if_valid_date(year y, day_of_year doy) BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ if (!leap && doy == 366)
+ return false;
+
+ y_ = y.value();
+ m_ = day_of_year_month(leap,doy);
+ d_ = day_of_year_day_of_month(leap,doy);
+ leap_ = leap;
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return true;
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ bool rel_date::set_if_valid_date(days x) BOOST_NOEXCEPT
+ {
+ if (!(11322 <= x.count() && x.count() <= 23947853))
+ {
+ return false;
+ }
+ year_month_day_leap dt = to_ymd_leap(x);
+ y_=dt.get_year();
+ m_=dt.get_month();
+ d_=dt.get_day();
+ leap_=dt.is_leap_year();
+ x_=x.count();
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return true;
+
+ }
+
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ bool rel_date::set_if_valid_date(days x) BOOST_NOEXCEPT// TODO
+ {
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return false;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ bool rel_date::set_if_valid_date(days x) BOOST_NOEXCEPT
+ {
+ if (!(11322 <= x.count() && x.count() <= 23947853))
+ {
+ return false;
+ }
+ year_month_day_leap dt = to_ymd_leap(x);
+ y_=dt.get_year();
+ m_=dt.get_month();
+ d_=dt.get_day();
+ leap_=dt.is_leap_year();
+ dow_=weekday::not_applicable;
+ n_=nth_week::not_applicable;
+ return true;
+
+ }
+
+#endif
+
+
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ bool rel_date::is_valid() const BOOST_NOEXCEPT
+ {
+ return x_ >= 11322 && x_ <= 23947853;
+
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ bool rel_date::is_valid() const
+ BOOST_NOEXCEPT
+ {
+ return x_ >= 11322 && x_ <= 23947853;
+
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ bool rel_date::is_valid() const BOOST_NOEXCEPT
+ {
+ if (year(y_,no_check).is_valid() && month(m_,no_check).is_valid())
+ {
+ if (d_!=0 && day(d_, no_check).is_valid()) {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_ - 1]))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ } else return true;
+ }
+ return false;
+
+ }
+#endif
+
+ rel_date
+ rel_date::today()
+ BOOST_NOEXCEPT
+ {
+ time_t systime;
+ time(&systime);
+ tm now;
+ localtime_r(&systime, &now);
+ return rel_date(chrono::year(now.tm_year+1900,no_check),
+ chrono::month(now.tm_mon+1,no_check),
+ chrono::day(now.tm_mday,no_check));
+ }
+
+ rel_date::rel_date(boost::chrono::system_clock::time_point tp)
+ {
+ time_t systime = boost::chrono::system_clock::to_time_t(tp);
+ tm now;
+ gmtime_r(&systime, &now);
+ *this
+ = rel_date(chrono::year(now.tm_year + 1900, no_check), chrono::month(now.tm_mon
+ + 1, no_check), chrono::day(now.tm_mday, no_check));
+ }
+
+ rel_date::operator boost::chrono::system_clock::time_point() const
+ {
+ tm now =
+ { 0 };
+ now.tm_year = get_year() - 1900;
+ now.tm_mon = get_month() - 1;
+ now.tm_mday = get_day();
+ time_t t = timegm(&now);
+ return boost::chrono::system_clock::from_time_t(t);
+ }
+
+#endif //BOOST_CHRONO_DATE_REL_DATE_IS_A_MODEL_OF_DATE
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+// rel_date::rel_date(ymd_date dt) :
+// x_(dt.days_since_epoch().count()),
+// y_(dt.get_year().value()),
+// m_(dt.get_month().value()),
+// leap_(dt.is_leap_year()),
+// dow_(weekday::not_applicable),
+// d_(dt.get_day().value()),
+// n_(nth_week::not_applicable)
+// {
+//
+// }
+ rel_date::operator ymd_date() const
+ {
+ return date(x_, y_, m_, d_, leap_, no_check);
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+// rel_date::rel_date(ymd_date dt) :
+// x_(dt.days_since_epoch().count())
+// {
+//
+// }
+ rel_date::operator ymd_date() const
+ {
+ return date(x_, no_check);
+
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+// rel_date::rel_date(ymd_date dt) :
+// y_(dt.get_year().value()),
+// m_(dt.get_month().value()),
+// leap_(dt.is_leap_year()),
+// dow_(weekday::not_applicable),
+// d_(dt.get_day().value()),
+// n_(nth_week::not_applicable)
+// {
+//
+// }
+ rel_date::operator ymd_date() const
+ {
+ return date(y_,m_,d_,leap_,no_check);
+
+ }
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+// rel_date::rel_date(days_date dt) :
+// x_(dt.days_since_epoch().count()),
+// y_(dt.get_year().value()),
+// m_(dt.get_month().value()),
+// leap_(dt.is_leap_year()),
+// dow_(weekday::not_applicable),
+// d_(dt.get_day().value()),
+// n_(nth_week::not_applicable)
+// {
+//
+// }
+ rel_date::operator days_date() const
+ {
+ return date(x_, no_check);
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+// rel_date::rel_date(days_date dt) :
+// x_(dt.days_since_epoch().count())
+// {
+//
+// }
+ rel_date::operator days_date() const
+ {
+ return date(x_, no_check);
+
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+// rel_date::rel_date(days_date dt) :
+// y_(dt.get_year().value()),
+// m_(dt.get_month().value()),
+// leap_(dt.is_leap_year()),
+// dow_(weekday::not_applicable),
+// d_(dt.get_day().value()),
+// n_(nth_week::not_applicable)
+// {
+//
+// }
+ rel_date::operator days_date() const
+ {
+ return date(y_,m_,d_,leap_,no_check);
+
+ }
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+// rel_date::rel_date(ydoy_date dt) :
+// x_(dt.days_since_epoch().count()),
+// y_(dt.get_year().value()),
+// m_(dt.get_month().value()),
+// leap_(dt.is_leap_year()),
+// dow_(weekday::not_applicable),
+// d_(dt.get_day().value()),
+// n_(nth_week::not_applicable)
+// {
+//
+// }
+ rel_date::operator ydoy_date() const
+ {
+ return date(x_, y_, m_, d_, leap_, no_check);
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+// rel_date::rel_date(ydoy_date dt) :
+// x_(dt.days_since_epoch().count())
+// {
+//
+// }
+ rel_date::operator ydoy_date() const
+ {
+ return date(x_, no_check);
+
+ }
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+// rel_date::rel_date(ydoy_date dt) :
+// y_(dt.get_year().value()),
+// m_(dt.get_month().value()),
+// leap_(dt.is_leap_year()),
+// dow_(weekday::not_applicable),
+// d_(dt.get_day().value()),
+// n_(nth_week::not_applicable)
+// {
+//
+// }
+ rel_date::operator ydoy_date() const
+ {
+ return date(y_,m_,d_,leap_,no_check);
+
+ }
+#endif
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::nth_weekday d) :
+ y_(y.value()),
+ m_(m.value()),
+ dow_(d.get_weekday()),
+ d_(0),
+ n_(d.get_nth())
+ {
+ leap_ = year(y_).is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (n_ != nth_week::not_applicable) // if a nth is involved
+
+ {
+ if (dow_ == weekday::not_applicable) // if we want nth day of month
+
+ {
+ if (n_ == 6) // want last day of month
+
+ {
+ d_ = year_data[m_] - year_data[m_ - 1];
+ }
+ else
+ {
+ d_ = n_; // want nth day of month
+ }
+ }
+ else // we want nth weekday of month
+
+ {
+ // dow_ = [0 - 6]
+ // n_ = [1 - 6] 6 means last
+ int32_t by = y.value() + 32799;
+ int32_t fy = by * 365 + by / 4 - by / 100 + by / 400;
+ int n_days_in_month = year_data[m_] - year_data[m_ - 1];
+ int d;
+ if (n_ == 6)
+ {
+ int ldow = (fy + year_data[m_] + 1) % weekday::size;
+ d = n_days_in_month;
+ if (dow_ < ldow)
+ {
+ d -= ldow - dow_;
+ }
+ else if (dow_ > ldow)
+ {
+ d -= weekday::size - (dow_ - ldow);
+ }
+ }
+ else
+ {
+ int fdow = (fy + year_data[m_ - 1] + 2) % weekday::size;
+ d = 1 + (n_ - 1) * weekday::size;
+ if (dow_ < fdow)
+ {
+ d += weekday::size - (fdow - dow_);
+ }
+ else if (dow_ > fdow)
+ {
+ d += dow_ - fdow;
+ }
+ if (d > n_days_in_month)
+ {
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y_) + '-' + to_string(m_));
+ }
+ }
+ d_ = d;
+ x_ = fy + year_data[m_ - 1] + d_;
+ return;
+ }
+ }
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_ - 1]))
+ {
+ throw bad_date("day " + to_string(d_) + " is out of range for "
+ + to_string(y_) + '-' + to_string(m_));
+ }
+ int32_t by = y.value() + 32799;
+ x_ = by * 365 + by / 4 - by / 100 + by / 400 + year_data[m_ - 1] + d_;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::nth_weekday nwd) :
+ n_(nwd.get_nth()), dow_(nwd.get_weekday())
+ {
+ bool leap = y.is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ if (n_ != nth_week::not_applicable) // if a nth is involved
+
+ {
+ if (dow_ == weekday::not_applicable) // if we want nth day of month
+
+ {
+ int d;
+ if (n_ == 6) // want last day of month
+
+ {
+ d = year_data[m.value()] - year_data[m.value() - 1];
+ }
+ else
+ {
+ d = n_; // want nth day of month
+ }
+ if (!(1 <= d && d <= year_data[m.value()] - year_data[m.value() - 1]))
+ {
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y.value()) + '-' + to_string(m.value()));
+ }
+ int32_t by = y.value() + 32799;
+ x_ = by * 365 + by / 4 - by / 100 + by / 400 + year_data[m.value()
+ - 1] + d;
+ return;
+ }
+ else // we want nth weekday of month
+
+ {
+ // dow_ = [0 - 6]
+ // n_ = [1 - 6] 6 means last
+ int32_t by = y.value() + 32799;
+ int32_t fy = by * 365 + by / 4 - by / 100 + by / 400;
+ int n_days_in_month = year_data[m.value()] - year_data[m.value() - 1];
+ int d;
+ if (n_ == 6)
+ {
+ int ldow = (fy + year_data[m.value()] + 1) % weekday::size;
+ d = n_days_in_month;
+ if (dow_ < ldow)
+ {
+ d -= ldow - dow_;
+ }
+ else if (dow_ > ldow)
+ {
+ d -= weekday::size - (dow_ - ldow);
+ }
+ }
+ else
+ {
+ int fdow = (fy + year_data[m.value() - 1] + 2) % weekday::size;
+ d = 1 + (n_ - 1) * weekday::size;
+ if (dow_ < fdow)
+ {
+ d += weekday::size - (fdow - dow_);
+ }
+ else if (dow_ > fdow)
+ {
+ d += dow_ - fdow;
+ }
+ if (d > n_days_in_month)
+ {
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y.value()) + '-' + to_string(m.value()));
+ }
+ }
+ x_ = fy + year_data[m.value() - 1] + d;
+ return;
+ }
+ }
+ // if (!(1 <= d.d_ && d.d_ <= year_data[m.value()] - year_data[m.value()-1]))
+ // {
+ // throw bad_date("day " + to_string(d.d_) +
+ // " is out of range for " + to_string(y.value()) +
+ // '-' + to_string(m.value()));
+ // }
+ // int32_t by = y.value() + 32799;
+ // x_ = by*365 + by/4 - by/100 + by/400 + year_data[m.value()-1] + d.d_;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::nth_weekday rd)
+ : y_(y.value()),
+ m_(m.value()),
+ leap_(0),
+ dow_(rd.get_weekday()),
+ //d_(rd.d_),
+ d_(0),
+ n_(rd.get_nth())
+ {
+ std::cout <<" =========== d= "<< int(d_) << std::endl;
+
+ leap_ = year(y,no_check).is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (n_ != nth_week::not_applicable) // if a nth is involved
+
+ {
+ if (dow_ == weekday::not_applicable) // if we want nth day of month
+
+ {
+ if (n_ == 6) // want last day of month
+
+ {
+ d_ = year_data[m_] - year_data[m_-1];
+ std::cout <<" =========== d= "<< int(d_) << std::endl;
+ }
+ else
+ {
+ d_ = n_; // want nth day of month
+ std::cout <<" =========== d= "<< int(d_) << std::endl;
+ }
+ }
+ else // we want nth weekday of month
+
+ {
+ // dow_ = [0 - 6]
+ // n_ = [1 - 6] 6 means last
+ int32_t by = y.value() + 32799;
+ int32_t fy = by*365 + by/4 - by/100 + by/400;
+ int n_days_in_month = year_data[m_] - year_data[m_-1];
+ int d;
+ if (n_ == 6)
+ {
+ int ldow = (fy + year_data[m_] + 1) % weekday::size;
+ d = n_days_in_month;
+ if (dow_ < ldow)
+ {
+ d -= ldow - dow_;
+ }
+ else if (dow_ > ldow)
+ {
+ d -= weekday::size - (dow_ - ldow);
+ }
+ }
+ else
+ {
+ int fdow = (fy + year_data[m_-1] + 2) % weekday::size;
+ d = 1 + (n_-1) * weekday::size;
+ if (dow_ < fdow)
+ {
+ d += weekday::size - (fdow - dow_);
+ }
+ else if (dow_ > fdow)
+ {
+ d += dow_ - fdow;
+ }
+ if (d > n_days_in_month)
+ {
+ throw bad_date("day " + to_string(int(d)) +
+ " is out of range for " + to_string(y_) +
+ '-' + to_string(int(m_)));
+ }
+ }
+ d_ = d;
+ std::cout <<" =========== d= "<< int(d_) << std::endl;
+ }
+ }
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_-1]))
+ {
+ std::cout <<"===== ====== d= "<< int(d_) << std::endl;
+ throw bad_date("day " + to_string(int(d_)) +
+ " is out of range for " + to_string(y_) +
+ '-' + to_string(int(m_)));
+ }
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::nth n) :
+ y_(y.value()),
+ m_(m.value()),
+ dow_(weekday::not_applicable),
+ d_(0),
+ n_(n.value())
+ {
+ leap_ = year(y_).is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (n_ != nth::not_applicable) // if a nth is involved
+
+ {
+ if (dow_ == weekday::not_applicable) // if we want nth day of month
+
+ {
+ if (n_ == 6) // want last day of month
+
+ {
+ d_ = year_data[m_] - year_data[m_ - 1];
+ }
+ else
+ {
+ d_ = n_; // want nth day of month
+ }
+ }
+ else // we want nth weekday of month
+
+ {
+ // dow_ = [0 - 6]
+ // n_ = [1 - 6] 6 means last
+ int32_t by = y.value() + 32799;
+ int32_t fy = by * 365 + by / 4 - by / 100 + by / 400;
+ int n_days_in_month = year_data[m_] - year_data[m_ - 1];
+ int d;
+ if (n_ == 6)
+ {
+ int ldow = (fy + year_data[m_] + 1) % weekday::size;
+ d = n_days_in_month;
+ if (dow_ < ldow)
+ {
+ d -= ldow - dow_;
+ }
+ else if (dow_ > ldow)
+ {
+ d -= weekday::size - (dow_ - ldow);
+ }
+ }
+ else
+ {
+ int fdow = (fy + year_data[m_ - 1] + 2) % weekday::size;
+ d = 1 + (n_ - 1) * weekday::size;
+ if (dow_ < fdow)
+ {
+ d += weekday::size - (fdow - dow_);
+ }
+ else if (dow_ > fdow)
+ {
+ d += dow_ - fdow;
+ }
+ if (d > n_days_in_month)
+ {
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y_) + '-' + to_string(m_));
+ }
+ }
+ d_ = d;
+ x_ = fy + year_data[m_ - 1] + d_;
+ return;
+ }
+ }
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_ - 1]))
+ {
+ throw bad_date("day " + to_string(d_) + " is out of range for "
+ + to_string(y_) + '-' + to_string(m_));
+ }
+ int32_t by = y.value() + 32799;
+ x_ = by * 365 + by / 4 - by / 100 + by / 400 + year_data[m_ - 1] + d_;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::nth n) :
+ n_(n.value()), dow_(weekday::not_applicable)
+ {
+ bool leap = y.is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ if (n_ != nth::not_applicable) // if a nth is involved
+
+ {
+ if (dow_ == weekday::not_applicable) // if we want nth day of month
+
+ {
+ int d;
+ if (n_ == 6) // want last day of month
+
+ {
+ d = year_data[m.value()] - year_data[m.value() - 1];
+ }
+ else
+ {
+ d = n_; // want nth day of month
+ }
+ if (!(1 <= d && d <= year_data[m.value()] - year_data[m.value() - 1]))
+ {
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y.value()) + '-' + to_string(m.value()));
+ }
+ int32_t by = y.value() + 32799;
+ x_ = by * 365 + by / 4 - by / 100 + by / 400 + year_data[m.value()
+ - 1] + d;
+ return;
+ }
+ else // we want nth weekday of month
+
+ {
+ // dow_ = [0 - 6]
+ // n_ = [1 - 6] 6 means last
+ int32_t by = y.value() + 32799;
+ int32_t fy = by * 365 + by / 4 - by / 100 + by / 400;
+ int n_days_in_month = year_data[m.value()] - year_data[m.value() - 1];
+ int d;
+ if (n_ == 6)
+ {
+ int ldow = (fy + year_data[m.value()] + 1) % weekday::size;
+ d = n_days_in_month;
+ if (dow_ < ldow)
+ {
+ d -= ldow - dow_;
+ }
+ else if (dow_ > ldow)
+ {
+ d -= weekday::size - (dow_ - ldow);
+ }
+ }
+ else
+ {
+ int fdow = (fy + year_data[m.value() - 1] + 2) % weekday::size;
+ d = 1 + (n_ - 1) * weekday::size;
+ if (dow_ < fdow)
+ {
+ d += weekday::size - (fdow - dow_);
+ }
+ else if (dow_ > fdow)
+ {
+ d += dow_ - fdow;
+ }
+ if (d > n_days_in_month)
+ {
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y.value()) + '-' + to_string(m.value()));
+ }
+ }
+ x_ = fy + year_data[m.value() - 1] + d;
+ return;
+ }
+ }
+ // if (!(1 <= d.d_ && d.d_ <= year_data[m.value()] - year_data[m.value()-1]))
+ // {
+ // throw bad_date("day " + to_string(d.d_) +
+ // " is out of range for " + to_string(y.value()) +
+ // '-' + to_string(m.value()));
+ // }
+ // int32_t by = y.value() + 32799;
+ // x_ = by*365 + by/4 - by/100 + by/400 + year_data[m.value()-1] + d.d_;
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date::rel_date(chrono::year y, chrono::month m, chrono::nth n)
+ : y_(y.value()),
+ m_(m.value()),
+ leap_(0),
+ dow_(weekday::not_applicable),
+ //d_(rd.d_),
+ d_(0),
+ n_(n.value())
+ {
+ leap_ = year(y,no_check).is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ if (n_ != nth::not_applicable) // if a nth is involved
+
+ {
+ if (dow_ == weekday::not_applicable) // if we want nth day of month
+
+ {
+ if (n_ == 6) // want last day of month
+
+ {
+ d_ = year_data[m_] - year_data[m_-1];
+ }
+ else
+ {
+ d_ = n_; // want nth day of month
+ }
+ }
+ else // we want nth weekday of month
+
+ {
+ // dow_ = [0 - 6]
+ // n_ = [1 - 6] 6 means last
+ int32_t by = y.value() + 32799;
+ int32_t fy = by*365 + by/4 - by/100 + by/400;
+ int n_days_in_month = year_data[m_] - year_data[m_-1];
+ int d;
+ if (n_ == 6)
+ {
+ int ldow = (fy + year_data[m_] + 1) % weekday::size;
+ d = n_days_in_month;
+ if (dow_ < ldow)
+ {
+ d -= ldow - dow_;
+ }
+ else if (dow_ > ldow)
+ {
+ d -= weekday::size - (dow_ - ldow);
+ }
+ }
+ else
+ {
+ int fdow = (fy + year_data[m_-1] + 2) % weekday::size;
+ d = 1 + (n_-1) * weekday::size;
+ if (dow_ < fdow)
+ {
+ d += weekday::size - (fdow - dow_);
+ }
+ else if (dow_ > fdow)
+ {
+ d += dow_ - fdow;
+ }
+ if (d > n_days_in_month)
+ {
+ throw bad_date("day " + to_string(int(d)) +
+ " is out of range for " + to_string(y_) +
+ '-' + to_string(int(m_)));
+ }
+ }
+ d_ = d;
+ }
+ }
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_-1]))
+ {
+ throw bad_date("day " + to_string(int(d_)) +
+ " is out of range for " + to_string(y_) +
+ '-' + to_string(int(m_)));
+ }
+ }
+
+#endif
+
+//#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1
+//
+// rel_date&
+// rel_date::operator+=(days d)
+// {
+// x_ += d.count();
+// if (!(11322 <= x_ && x_ <= 23947853))
+// {
+// throw bad_date("year is out of range [-32768, 32767]");
+// }
+// year::rep y = to_average_year(x_);
+// int doy = x_ - (y * 365 + y / 4 - y / 100 + y / 400);
+// if (doy < 0)
+// {
+// --y;
+// doy = x_ - (y * 365 + y / 4 - y / 100 + y / 400);
+// }
+// y_ = static_cast<int16_t> (y - 32799);
+// leap_ = year(y, no_check).is_leap();
+// const day_of_year::rep* year_data = days_in_year_before(leap_);
+// m_ = static_cast<uint16_t> (std::lower_bound(year_data, year_data + 13, doy)
+// - year_data);
+// d_ = static_cast<uint16_t> (doy - year_data[m_ - 1]);
+// n_ = nth_week::not_applicable;
+// dow_ = weekday::not_applicable;
+// return *this;
+// }
+//
+//#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+//
+// rel_date&
+// rel_date::operator+=(days d)
+// {
+// x_ += d.count();
+// if (!(11322 <= x_ && x_ <= 23947853))
+// {
+// throw bad_date("year is out of range [-32768, 32767]");
+// }
+// n_ = nth_week::not_applicable;
+// dow_ = weekday::not_applicable;
+// return *this;
+// }
+//
+//#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+//
+// rel_date&
+// rel_date::operator+=(days d)
+// {
+// uint32_t x = day_number_from_ymd() + d.count();
+// if (!(11322 <= x && x <= 23947853))
+// {
+// throw bad_date("year is out of range [-32768, 32767]");
+// }
+//
+// year::rep y = to_average_year(x);
+// int doy = x - (y*365 + y/4 - y/100 + y/400);
+// if (doy < 0)
+// {
+// --y;
+// doy = x - (y*365 + y/4 - y/100 + y/400);
+// }
+// y_ = static_cast<int16_t>(y - 32799);
+// leap_ = year(y_).is_leap();
+// const day_of_year::rep* year_data = days_in_year_before(leap_);
+// m_ = static_cast<uint16_t>(std::lower_bound(year_data, year_data+13, doy)
+// - year_data);
+// d_ = static_cast<uint16_t>(doy - year_data[m_-1]);
+//
+//
+// n_ = nth_week::not_applicable;
+// dow_ = weekday::not_applicable;
+// return *this;
+// }
+//
+//#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 1 || BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ rel_date&
+ rel_date::operator+=(months mn)
+ {
+ int32_t y = y_;
+ int32_t m = m_;
+ m += mn.count();
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ }
+ else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ //if (d_==0)
+ *this = chrono::nth_weekday(nth_week(n_,no_check), weekday(dow_,no_check)) / chrono::month(m, no_check) / y;
+ //else
+ //*this = rel_date(year(y), chrono::month(m, no_check), chrono::day(d_,no_check));
+ return *this;
+ }
+
+ rel_date&
+ rel_date::operator+=(years yr)
+ {
+ //if (d_==0)
+ *this = chrono::nth_weekday(nth_week(n_,no_check), weekday(dow_,no_check)) / chrono::month(m_, no_check) / (y_ + yr.count());
+ //else
+ //*this = rel_date(year(y_+ yr.count()), chrono::month(m_, no_check), chrono::day(d_,no_check));
+ return *this;
+
+ }
+
+#elif BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ rel_date&
+ rel_date::operator+=(months mn)
+ {
+ year::rep y = to_average_year(x_);
+ int doy = x_ - (y * 365 + y / 4 - y / 100 + y / 400);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y * 365 + y / 4 - y / 100 + y / 400);
+ }
+ y -= 32799;
+ bool leap = year(y).is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ int m = std::lower_bound(year_data, year_data + 13, doy) - year_data;
+ m += mn.count();
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ }
+ else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ *this = chrono::nth_weekday(nth_week(n_), weekday(dow_, no_check))
+ / chrono::month(m, no_check) / y;
+ return *this;
+ }
+
+ rel_date&
+ rel_date::operator+=(years yr)
+ {
+ year::rep y = to_average_year(x_);
+ int doy = x_ - (y * 365 + y / 4 - y / 100 + y / 400);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y * 365 + y / 4 - y / 100 + y / 400);
+ }
+ y -= 32799;
+ bool leap = year(y).is_leap();
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ int m = std::lower_bound(year_data, year_data + 13, doy) - year_data;
+ *this = chrono::nth_weekday(nth_week(n_), weekday(dow_, no_check))
+ / chrono::month(m, no_check) / (y + yr.count());
+ return *this;
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 2
+
+ uint16_t
+ rel_date::day_from_day_number() const
+ BOOST_NOEXCEPT
+ {
+ year::rep y = to_average_year(x_);
+ int doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ }
+ y -= 32799;
+ const day_of_year::rep* year_data = days_in_year_before(year(y).is_leap());
+ int m = std::lower_bound(year_data, year_data+13, doy) - year_data;
+ return static_cast<uint16_t>(doy - year_data[m-1]);
+ }
+
+ uint16_t
+ rel_date::month_from_day_number() const
+ BOOST_NOEXCEPT
+ {
+ year::rep y = to_average_year(x_);
+ int doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ }
+ y -= 32799;
+ const day_of_year::rep* year_data = days_in_year_before(year(y).is_leap());
+ return std::lower_bound(year_data, year_data+13, doy) - year_data;
+ }
+
+ int16_t
+ rel_date::year_from_day_number() const
+ BOOST_NOEXCEPT
+ {
+ year::rep y = to_average_year(x_);
+ int doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ }
+ y -= 32799;
+ return static_cast<int16_t>(y);
+ }
+
+ bool
+ rel_date::leap_from_day_number() const
+ BOOST_NOEXCEPT
+ {
+ year::rep y = to_average_year(x_);
+ int doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (y*365 + y/4 - y/100 + y/400);
+ }
+ y -= 32799;
+ return year(y).is_leap();
+ }
+
+#endif
+
+#if BOOST_CHRONO_DATE_REL_DATE_DESIGN == 3
+
+ uint32_t
+ rel_date::day_number_from_ymd() const BOOST_NOEXCEPT
+ {
+ uint32_t by = y_ + 32799;
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ return by*365 + by/4 - by/100 + by/400 + year_data[m_-1] + d_;
+ }
+
+#endif
+
+ year_month_day to_ymd(year_week_weekday p)
+ BOOST_NOEXCEPT
+ {
+ date dt = (mon <= jan / day(4,no_check) / p.get_year()) + days((p.get_week().value() - 1) * weekday::size + (p.get_weekday().value() == 0 ? weekday::size-1 : p.get_weekday().value() - 1));
+ return year_month_day(dt.get_year(), dt.get_month(), dt.get_day(), no_check);
+ }
+
+ year_day_of_year to_ydoy(year_week_weekday dt)
+ BOOST_NOEXCEPT
+ {
+ return to_ydoy(to_ymd(dt));
+ }
+
+ days to_days(year_week_weekday dt)
+ BOOST_NOEXCEPT
+ {
+ return to_days(to_ymd(dt));
+ }
+
+ year_week_weekday to_ywwd(year_month_day ymd)
+ BOOST_NOEXCEPT
+ {
+ date dt(ymd.get_year(), ymd.get_month(), ymd.get_day(), no_check);
+ month_day jan4 = jan / day(4);
+ date start = mon <= jan4 / ymd.get_year();
+ if (dt < start)
+ {
+ start = mon <= jan4 / (ymd.get_year() - 1);
+ }
+ else
+ {
+ date next_start = mon <= jan4 / (start.get_year() + 1);
+ if (dt >= next_start)
+ start = next_start;
+ }
+ return year_week_weekday(
+ (thu > start).get_year(),
+ (dt - start).count() / weekday::size + 1,
+ dt.get_weekday(),
+ no_check
+ );
+ }
+
+ year_week_weekday to_ywwd(year_day_of_year dt)
+ BOOST_NOEXCEPT
+ {
+ return to_ywwd(to_ymd(dt));
+
+ }
+
+ year_week_weekday to_ywwd(days dt)
+BOOST_NOEXCEPT {
+ return to_ywwd(to_ymd(dt));
+
+ }
+
+} // chrono
+} // boost
+
+

Added: sandbox/chrono_date/libs/date/src/vars.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/src/vars.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,190 @@
+// date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <boost/chrono/date/weekday.hpp>
+#include <boost/chrono/date/month.hpp>
+#include <boost/chrono/date/nth_week.hpp>
+#include <boost/chrono/date/nth.hpp>
+#include <boost/chrono/date/month_nth.hpp>
+#include <boost/chrono/date/tuples.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ const weekday sun(0);
+ const weekday mon(1);
+ const weekday tue(2);
+ const weekday wed(3);
+ const weekday thu(4);
+ const weekday fri(5);
+ const weekday sat(6);
+
+ const month jan(1);
+ const month feb(2);
+ const month mar(3);
+ const month apr(4);
+ const month may(5);
+ const month jun(6);
+ const month jul(7);
+ const month aug(8);
+ const month sep(9);
+ const month oct(10);
+ const month nov(11);
+ const month dec(12);
+
+// const nth_week _1st_week(1);
+// const nth_week _2nd_week(2);
+// const nth_week _3rd_week(3);
+// const nth_week _4th_week(4);
+// const nth_week _5th_week(5);
+// const nth_week last_week(6);
+//
+// const nth _1st(1);
+// const nth _2nd(2);
+// const nth _3rd(3);
+// const nth _4th(4);
+// const nth _5th(5);
+// const nth last(6);
+
+ const month_nth jan_1st(1, 1, no_check);
+
+ const month_day jan_01(1, 1, no_check);
+ const month_day jan_02(1, 2, no_check);
+ const month_day jan_03(1, 3, no_check);
+ const month_day jan_04(1, 4, no_check);
+ const month_day jan_05(1, 5, no_check);
+ const month_day jan_06(1, 6, no_check);
+ const month_day jan_07(1, 7, no_check);
+ const month_day jan_08(1, 8, no_check);
+ const month_day jan_09(1, 9, no_check);
+ const month_day jan_10(1, 10, no_check);
+ const month_day jan_11(1, 11, no_check);
+ const month_day jan_12(1, 12, no_check);
+ const month_day jan_13(1, 13, no_check);
+ const month_day jan_14(1, 14, no_check);
+ const month_day jan_15(1, 15, no_check);
+ const month_day jan_16(1, 16, no_check);
+ const month_day jan_17(1, 17, no_check);
+ const month_day jan_18(1, 18, no_check);
+ const month_day jan_19(1, 19, no_check);
+ const month_day jan_20(1, 20, no_check);
+ const month_day jan_21(1, 21, no_check);
+ const month_day jan_22(1, 22, no_check);
+ const month_day jan_23(1, 23, no_check);
+ const month_day jan_24(1, 24, no_check);
+ const month_day jan_25(1, 25, no_check);
+ const month_day jan_26(1, 26, no_check);
+ const month_day jan_27(1, 27, no_check);
+ const month_day jan_28(1, 28, no_check);
+ const month_day jan_29(1, 29, no_check);
+ const month_day jan_30(1, 30, no_check);
+ const month_day jan_31(1, 31, no_check);
+
+
+ static const day::rep days_in_month_[2][13] =
+ {
+ { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ };
+
+
+ days year::days_in(month m) const BOOST_NOEXCEPT
+ {
+ return days(days_in_month_[is_leap()][m]);
+ }
+ day::rep days_in_month(bool leap, month::rep m) BOOST_NOEXCEPT
+ {
+ return days_in_month_[leap][m];
+ }
+
+
+ static const day_of_year::rep days_in_year_before_[2][13] =
+ {
+ { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
+ { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 } };
+
+ static const month::rep
+ day_of_year_month_[2][366] =
+ {
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1
1, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 },
+
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
+
+ } };
+
+ static const day::rep
+ day_of_year_day_of_month_[2][366] =
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 3
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0 // no leap years have 365 days
+ },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 2
9, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+
+ }
+
+ };
+
+ static const day_of_year::rep
+ month_day_to_day_of_year_[2][12][31] =
+ {
+ { // no_leap
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 },
+ { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 77, 58, 59, 0, 0, 0 },
+ { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90 },
+ { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 0 },
+ { 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151 },
+ { 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 0 },
+ { 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212 },
+ { 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243 },
+ { 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 0 },
+ { 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304 },
+ { 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 0 },
+ { 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365 } },
+ { // leap
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 },
+ { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 77, 58, 59, 60, 0, 0 },
+ { 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91 },
+ { 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 0 },
+ { 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152 },
+ { 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 0 },
+ { 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213 },
+ { 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244 },
+ { 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 0 },
+ { 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305 },
+ { 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 0 },
+ { 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366 } } };
+
+
+
+ day_of_year::rep days_in_year_before(bool b, month::rep m) BOOST_NOEXCEPT
+ {
+ return days_in_year_before_[b][m];
+ }
+ const day_of_year::rep* days_in_year_before(bool b) BOOST_NOEXCEPT
+ {
+ return days_in_year_before_[b];
+ }
+
+ month::rep day_of_year_month(bool b, day_of_year::rep d) BOOST_NOEXCEPT
+ {
+ return day_of_year_month_[b][d-1];
+ }
+
+ day::rep day_of_year_day_of_month(bool b, day_of_year::rep d) BOOST_NOEXCEPT
+ {
+ return day_of_year_day_of_month_[b][d-1];
+ }
+ day_of_year::rep month_day_to_day_of_year(bool b, month::rep m, day::rep d) BOOST_NOEXCEPT
+ {
+ return month_day_to_day_of_year_[b][m-1][d-1];
+ }
+} // boost
+ } // chrono
+
+

Added: sandbox/chrono_date/libs/date/src/ydoy_date.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/src/ydoy_date.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,276 @@
+// ydoy_date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <algorithm>
+#include <ctime>
+#include <boost/chrono/date/ydoy_date.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+#include <boost/chrono/date/conversions.hpp>
+
+namespace boost
+{
+ namespace chrono
+ {
+
+ ydoy_date::ydoy_date()
+ BOOST_NOEXCEPT
+ :
+ y_(0),
+ doy_(1),
+ leap_(1)
+ {
+ }
+
+ ydoy_date
+ ydoy_date::today()
+ BOOST_NOEXCEPT
+ {
+ time_t systime;
+ time(&systime);
+ tm now;
+ localtime_r(&systime, &now);
+ return ydoy_date(
+ chrono::year(now.tm_year+1900),
+ chrono::month(now.tm_mon+1),
+ chrono::day(now.tm_mday)
+ );
+ }
+
+ ydoy_date::ydoy_date(boost::chrono::system_clock::time_point tp)
+ {
+ time_t systime = boost::chrono::system_clock::to_time_t(tp);
+ tm now;
+ gmtime_r(&systime, &now);
+ *this
+ = ydoy_date(chrono::year(now.tm_year + 1900), chrono::month(now.tm_mon
+ + 1), chrono::day(now.tm_mday));
+ }
+
+ ydoy_date::operator boost::chrono::system_clock::time_point() const
+ {
+ tm now = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ now.tm_year = get_year() - 1900;
+ now.tm_mon = get_month() - 1;
+ now.tm_mday = get_day();
+ time_t t = timegm(&now);
+ return boost::chrono::system_clock::from_time_t(t);
+ }
+
+ bool ydoy_date::set_if_valid_date(year y, month m, day d)
+ BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return false;
+ }
+ y_ = y;
+ doy_ = month_day_to_day_of_year(leap,m,d);
+ leap_ = leap;
+ return true;
+ }
+
+// ydoy_date::ydoy_date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+// :
+// y_(y),
+// doy_(month_day_to_day_of_year(leap,m,d)),
+// leap_(leap)
+// {
+// }
+
+// optional_ydoy_date make_valid_ydoy_date(year y, month m, day d)
+// BOOST_NOEXCEPT
+// {
+// ydoy_date res;
+// if (res.set_if_valid_date(y,m,d)) return optional_ydoy_date(res);
+// else return optional_ydoy_date();
+//
+// }
+
+ ydoy_date::ydoy_date(chrono::year y, chrono::month m, chrono::day d)
+ {
+ if (set_if_valid_date(y, m, d))
+ return;
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y) + '-' + to_string(m));
+ }
+
+ ydoy_date::ydoy_date(chrono::year y, chrono::month_day md)
+ {
+ if (set_if_valid_date(y, md.get_month(), md.get_day()))
+ return;
+ throw bad_date("day " + to_string(md.get_day()) + " is out of range for "
+ + to_string(y) + '-' + to_string(md.get_month()));
+ }
+
+ ydoy_date::ydoy_date(year::rep y, month::rep m, day::rep d, no_check_t)
+ BOOST_NOEXCEPT
+ :
+ y_(y),
+ doy_(month_day_to_day_of_year(is_leap(y),m,d)),
+ leap_(is_leap(y))
+ {
+ }
+
+ ydoy_date::ydoy_date(year::rep y, month_day md, no_check_t)
+ BOOST_NOEXCEPT
+ :
+ y_(y),
+ doy_(month_day_to_day_of_year(is_leap(y),md.get_month(),md.get_month())),
+ leap_(is_leap(y))
+ {
+ }
+
+ ydoy_date::ydoy_date(ymd_date dt)
+ :
+ y_(dt.get_year()),
+ doy_(month_day_to_day_of_year(dt.is_leap_year(),dt.get_month(),dt.get_day())),
+ leap_(dt.is_leap_year())
+ {
+ //std::cout << __FILE__ <<"["<< __LINE__ <<"]"<<dt.get_year() << ":" << int(dt.get_month())<<":" <<int(dt.get_day()) << std::endl;
+ //std::cout << __FILE__ <<"["<< __LINE__ <<"]"<< y_ << ":" << doy_<<":" << std::endl;
+ }
+
+ ydoy_date::ydoy_date(days_date dt)
+ {
+ days::rep x = dt.days_since_epoch().count();
+ year::rep y = to_average_year(x);
+ int doy = x - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x - (days_before_year(y));
+ }
+ y -= 32799;
+ ++doy;
+ leap_=is_leap(y);
+ y_ = y;
+ doy_ = doy;
+ }
+
+ ydoy_date::ydoy_date(days d)
+ {
+ days::rep x = d.count();
+ if (!(11322 <= x && x <= 23947853))
+ {
+ throw bad_date("year is out of range [-32768, 32767]");
+ }
+ //std::cout << __LINE__ <<": "<<x<< std::endl;
+ year::rep y = to_average_year(x);
+ //std::cout << __LINE__ <<": "<<y<< std::endl;
+ int doy = x - (days_before_year(y));
+ //std::cout << __LINE__ <<": "<<doy<< std::endl;
+ if (doy < 0)
+ {
+ --y;
+ //std::cout << __LINE__ <<": "<<y<< std::endl;
+ doy = x - (days_before_year(y));
+ //std::cout << __LINE__ <<": "<<doy<< std::endl;
+ }
+ y -= 32799;
+ //std::cout << __LINE__ <<": "<<y<< std::endl;
+ ++doy;
+ //std::cout << __LINE__ <<": "<<doy<< std::endl;
+ leap_ = is_leap(y);
+ y_ = y;
+ doy_ = doy;
+ }
+
+ ydoy_date::ydoy_date(days::rep x, no_check_t) BOOST_NOEXCEPT
+ {
+ year::rep y = to_average_year(x);
+ int doy = x - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x - (days_before_year(y));
+ }
+ y -= 32799;
+ ++doy;
+ leap_=is_leap(y);
+ y_ = y;
+ doy_ = doy;
+ }
+
+ ydoy_date::ydoy_date(chrono::year y, chrono::day_of_year doy)
+ : y_(y),
+ doy_(doy),
+ leap_(is_leap(y_))
+ {
+ if (! leap_ && doy_==366)
+ throw bad_date("non leap years have no 366 days");
+ }
+
+ ydoy_date::ydoy_date(chrono::year::rep y, chrono::day_of_year::rep doy, no_check_t) BOOST_NOEXCEPT
+ : y_(y),
+ doy_(doy),
+ leap_(is_leap(y_))
+ {
+ }
+
+ ydoy_date&
+ ydoy_date::operator+=(days d)
+ {
+ days::rep x = (days_since_epoch() + d).count();
+ if (!(11322 <= x && x <= 23947853))
+ {
+ throw bad_date("year is out of range [-32768, 32767]");
+ }
+ year::rep y = to_average_year(x);
+ int doy = x - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x - (days_before_year(y));
+ }
+ y -= 32799;
+ ++doy;
+ y_ = y;
+ doy_ = doy;
+ leap_ = is_leap(y);
+ return *this;
+ }
+
+ ydoy_date&
+ ydoy_date::operator+=(months mn)
+ {
+ int32_t y = y_;
+ int32_t m = get_month();
+ std::cout << __LINE__ <<": "<<m<< std::endl;
+ m += mn.count();
+ std::cout << __LINE__ <<": "<<m<< std::endl;
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ } else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ std::cout << __LINE__ <<": "<<m<< std::endl;
+ *this = ydoy_date(chrono::year(y), month(m,no_check), get_day());
+ return *this;
+ }
+
+ ydoy_date&
+ ydoy_date::operator+=(years yr)
+ {
+ *this = ydoy_date(chrono::year(y_ + yr.count()), get_month(), get_day());
+ return *this;
+ }
+
+ } // chrono
+} // boost
+
+
+

Added: sandbox/chrono_date/libs/date/src/ymd_date.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/src/ymd_date.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,319 @@
+// ymd_date.cpp
+//
+// (C) Copyright Howard Hinnant
+// Copyright 2011 Vicente J. Botet Escriba
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+
+#include <algorithm>
+#include <ctime>
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/detail/helpers.hpp>
+#include <boost/chrono/date/conversions.hpp>
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN==2
+#else
+namespace boost
+{
+ namespace chrono
+ {
+
+// ymd_date::ymd_date()
+// BOOST_NOEXCEPT
+// :
+//#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+// x_(11979588),
+//#endif
+// y_(0),
+// m_(1),
+// d_(1),
+// leap_(1)
+// {
+// }
+
+ ymd_date
+ ymd_date::today()
+ BOOST_NOEXCEPT
+ {
+ time_t systime;
+ time(&systime);
+ tm now;
+ localtime_r(&systime, &now);
+ return ymd_date(
+ chrono::year(now.tm_year+1900),
+ chrono::month(now.tm_mon+1),
+ chrono::day(now.tm_mday)
+ );
+ }
+
+ ymd_date::ymd_date(boost::chrono::system_clock::time_point tp)
+ {
+ time_t systime = boost::chrono::system_clock::to_time_t(tp);
+ tm now;
+ gmtime_r(&systime, &now);
+ *this
+ = ymd_date(chrono::year(now.tm_year + 1900), chrono::month(now.tm_mon
+ + 1), chrono::day(now.tm_mday));
+ }
+
+ ymd_date::operator boost::chrono::system_clock::time_point() const
+ {
+ tm now = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ now.tm_year = get_year() - 1900;
+ now.tm_mon = get_month() - 1;
+ now.tm_mday = get_day();
+ time_t t = timegm(&now);
+ return boost::chrono::system_clock::from_time_t(t);
+ }
+
+ bool ymd_date::is_valid() const
+ BOOST_NOEXCEPT
+ {
+ if (year(y_,no_check).is_valid() && month(m_,no_check).is_valid() && day(d_, no_check).is_valid()) {
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+
+ if (!(1 <= d_ && d_ <= year_data[m_] - year_data[m_ - 1]))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ return false;
+
+
+ }
+
+ bool ymd_date::set_if_valid_date(year y, month m, day d)
+ BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+
+ if (!(d <= year_data[m] - year_data[m - 1]))
+ {
+ return false;
+ }
+ y_ = y.value();
+ m_ = m.value();
+ d_ = d.value();
+ leap_ = leap;
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+#endif
+ return true;
+ }
+
+ bool ymd_date::set_if_valid_date(chrono::year y, chrono::day_of_year doy)
+ BOOST_NOEXCEPT
+ {
+ bool leap = is_leap(y);
+ if (!leap && doy == 366)
+ return false;
+
+ y_ = y.value();
+ m_ = day_of_year_month(leap,doy);
+ d_ = day_of_year_day_of_month(leap,doy);
+ leap_ = leap;
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ year::rep by = y.value() + 32799;
+ x_ = days_before_year(by) + doy -1;
+#endif
+ return true;
+ }
+
+ bool ymd_date::set_if_valid_date(days x)
+ BOOST_NOEXCEPT
+ {
+ if (!(11322 <= x.count() && x.count() <= 23947853))
+ {
+ return false;
+ }
+ year_month_day_leap dt = to_ymd_leap(x);
+ y_=dt.get_year();
+ m_=dt.get_month();
+ d_=dt.get_day();
+ leap_=dt.is_leap_year();
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ x_=x.count();
+#endif
+ return true;
+ }
+
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ ymd_date::ymd_date(year::rep y, month::rep m, day::rep d, bool leap, no_check_t) BOOST_NOEXCEPT
+ :
+ y_(y),
+ m_(m),
+ d_(d),
+ leap_(leap)
+ {
+ const day_of_year::rep* year_data = days_in_year_before(leap);
+ year::rep by = y + 32799;
+ x_ = days_before_year(by) + year_data[m - 1] + d;
+ }
+#endif
+
+ ymd_date::ymd_date(chrono::year y, chrono::month m, chrono::day d)
+ {
+ if (set_if_valid_date(y, m, d))
+ return;
+ throw bad_date("day " + to_string(d) + " is out of range for "
+ + to_string(y) + '-' + to_string(m));
+ }
+
+ ymd_date::ymd_date(chrono::year y, chrono::month_day md)
+ {
+ if (set_if_valid_date(y, md.get_month(), md.get_day()))
+ return;
+ throw bad_date("day " + to_string(md.get_day()) + " is out of range for "
+ + to_string(y) + '-' + to_string(md.get_month()));
+ }
+
+ ymd_date::ymd_date(year::rep y, month::rep m, day::rep d, no_check_t)
+ BOOST_NOEXCEPT
+ : y_(y), m_(m), d_(d), leap_(is_leap(y_))
+ {
+
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+
+ int_least32_t by = y_ + 32799;
+ x_ = days_before_year(by) + year_data[m_ - 1] + d_;
+#endif
+ }
+ ymd_date::ymd_date(year::rep y, month_day md, no_check_t)
+ BOOST_NOEXCEPT
+ : y_(y), m_(md.get_month()), d_(md.get_day()), leap_(is_leap(y_))
+ {
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+
+ int_least32_t by = y_ + 32799;
+ x_ = days_before_year(by) + year_data[m_ - 1] + d_;
+#endif
+ }
+
+
+ ymd_date::ymd_date(chrono::year y, chrono::day_of_year doy)
+ {
+ if (set_if_valid_date(y, doy))
+ return;
+ throw bad_date("doy " + to_string(doy) + " is out of range for year "
+ + to_string(y) );
+ }
+
+ ymd_date::ymd_date(days d)
+ {
+ if (set_if_valid_date(d))
+ return;
+ throw bad_date("days " + to_string(d.count()) + " is out of range");
+ }
+ ymd_date::ymd_date(days::rep x, no_check_t) BOOST_NOEXCEPT
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ : x_(x)
+#endif
+ {
+ year_month_day_leap dt = to_ymd_leap(days(x));
+ y_=dt.get_year();
+ m_=dt.get_month();
+ d_=dt.get_day();
+ leap_=dt.is_leap_year();
+ }
+
+ ymd_date::ymd_date(days_date dt)
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ : x_(dt.days_since_epoch().count())
+#endif
+ {
+ y_=dt.get_year();
+ m_=dt.get_month();
+ d_=dt.get_day();
+ leap_=dt.is_leap_year();
+ }
+
+
+
+ ymd_date&
+ ymd_date::operator+=(days d)
+ {
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 1
+ x_ += d.count();
+#elif BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 3
+ days::rep x_ = day_number_from_ymd() + d.count();
+#endif
+ if (!(11322 <= x_ && x_ <= 23947853))
+ {
+ throw bad_date("year is out of range [-32768, 32767]");
+ }
+ year::rep y = to_average_year(x_);
+ int doy = x_ - (days_before_year(y));
+ if (doy < 0)
+ {
+ --y;
+ doy = x_ - (days_before_year(y));
+ }
+ y_ = static_cast<year::rep> (y - 32799);
+ leap_ = is_leap(y_);
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ m_
+ = static_cast<month::rep> (std::lower_bound(year_data, year_data + 13, doy)
+ - year_data);
+ d_ = static_cast<day::rep> (doy - year_data[m_ - 1]);
+
+ return *this;
+ }
+
+ ymd_date&
+ ymd_date::operator+=(months mn)
+ {
+ int_least32_t y = y_;
+ int32_t m = m_;
+ m += mn.count();
+ if (m < 1)
+ {
+ int dy = (12 - m) / 12;
+ y -= dy;
+ m += 12 * dy;
+ } else if (m > 12)
+ {
+ int dy = (m - 1) / 12;
+ y += dy;
+ m -= 12 * dy;
+ }
+ *this
+ = ymd_date(chrono::year(y), chrono::month(m, no_check), chrono::day(d_, no_check));
+ return *this;
+ }
+
+ ymd_date&
+ ymd_date::operator+=(years yr)
+ {
+ *this
+ = ymd_date(chrono::year(y_ + yr.count()), chrono::month(m_, no_check), chrono::day(d_, no_check));
+ return *this;
+ }
+
+#if BOOST_CHRONO_DATE_YMD_DATE_DESIGN == 3
+
+ days::rep
+ ymd_date::day_number_from_ymd() const BOOST_NOEXCEPT
+ {
+ days::rep by = y_ + 32799;
+ const day_of_year::rep* year_data = days_in_year_before(leap_);
+ return days_before_year(by) + year_data[m_-1] + d_;
+ }
+
+#endif
+
+ } // chrono
+} // boost
+
+#endif
+

Added: sandbox/chrono_date/libs/date/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/Jamfile.v2 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,103 @@
+# Boost Chrono.Date Library test Jamfile
+
+# Copyright Vicente J. Botet Escriba 2011
+
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt
+
+# See library home page at http://www.boost.org/libs/chrono
+
+import os ;
+import feature ;
+
+project
+ : requirements
+
+ <define>BOOST_CHRONO_DONT_PROVIDE_DEPRECATED_IO_V1
+ <define>BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
+ #<define>BOOST_CHRONO_HEADER_ONLY
+
+ <target-os>freebsd:<linkflags>"-lrt"
+ <target-os>linux:<linkflags>"-lrt"
+ <toolset>pgi:<linkflags>"-lrt"
+ #<threading>single:<define>BOOST_CHRONO_THREAD_DISABLED
+ <toolset>msvc:<asynch-exceptions>on
+ <define>BOOST_CHRONO_USES_MPL_ASSERT
+ <define>BOOST_SYSTEM_NO_DEPRECATED
+ <toolset>sun:<define>BOOST_TYPEOF_EMULATION
+ <warnings>all
+ <toolset>gcc:<cxxflags>-Wextra
+ <toolset>gcc:<cxxflags>-pedantic
+ <toolset>gcc:<cxxflags>-Wno-long-long
+ <toolset>darwin:<cxxflags>-Wextra
+ <toolset>darwin:<cxxflags>-pedantic
+ <toolset>darwin:<cxxflags>-Wno-long-long
+ #<toolset>pathscale:<cxxflags>-Wextra
+ <toolset>pathscale:<cxxflags>-Wno-long-long
+ <toolset>pathscale:<cxxflags>-pedantic
+ <toolset>clang:<cxxflags>-Wextra
+ <toolset>clang:<cxxflags>-pedantic
+ <toolset>clang:<cxxflags>-Wno-long-long
+ <toolset>gcc-mingw-4.5.0:<cxxflags>-Wno-missing-field-initializers
+ <toolset>gcc-mingw-4.5.0:<cxxflags>-fdiagnostics-show-option
+ <toolset>msvc:<cxxflags>/wd4127
+# Note: Some of the remarks from the Intel compiler are disabled
+# remark #304: access control not specified ("public" by default)
+# remark #383: value copied to temporary, reference to temporary used
+# remark #1418: external function definition with no prior declaration
+ <toolset>intel:<cxxflags>-wd304,383,1418
+ ;
+
+
+rule date-run ( sources + )
+{
+ return
+ [ run $(sources) ../build//boost_chrono_date
+ : :
+ :
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ : $(sources[1]:B)_shared ]
+ ;
+}
+
+rule date-run-2 ( sources + : name )
+{
+ return
+ [ run $(sources) ../build//boost_chrono_date
+ : :
+ :
+ <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ : $(name)_shared ]
+ ;
+}
+
+
+ test-suite "wrappers"
+ :
+ [ date-run-2 wrappers/day_pass.cpp : day_pass ]
+ [ date-run-2 wrappers/nth_pass.cpp : nth_pass ]
+ [ date-run-2 wrappers/weekday_pass.cpp : weekday_pass ]
+ [ date-run-2 wrappers/day_of_year_pass.cpp : day_of_year_pass ]
+ [ date-run-2 wrappers/nth_week_pass.cpp : nth_week_pass ]
+ [ date-run-2 wrappers/week_pass.cpp : week_pass ]
+ [ date-run-2 wrappers/month_pass.cpp : month_pass ]
+ [ date-run-2 wrappers/year_pass.cpp : year_pass ]
+ ;
+
+ test-suite "dates"
+ :
+ [ date-run-2 dates/days/days_date_pass.cpp : days_date_pass ]
+ [ date-run-2 dates/ymd/ymd_date_pass.cpp : ymd_date_pass ]
+ [ date-run-2 dates/ydoy/ydoy_date_pass.cpp : ydoy_date_pass ]
+ #[ date-run-2 dates/days/nth_days_date_pass.cpp : nth_days_date_pass ]
+ ;
+
+ test-suite "examples"
+ :
+ [ date-run ../example/hello_world.cpp ]
+ [ date-run ../example/ex_week_based_year.cpp ]
+ [ date-run-2 ../example/ex_julian.cpp ../example/julian.cpp : ex_julian ]
+ ;
+

Added: sandbox/chrono_date/libs/date/test/dates/days/days_date_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/dates/days/days_date_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,519 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/days_date.hpp>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/chrono_io.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+
+ using std::cout;
+ using namespace boost;
+ using namespace boost::chrono;
+
+ typedef boost::chrono::high_resolution_clock Clock;
+ typedef boost::chrono::duration<double, boost::micro> micros;
+
+ { // construct from ymd: 0/1/1
+ days_date dt(year(0),jan,day(1));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ }
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ days_date dt(0,0,0,no_check);
+ std::cout <<"0/0/0 days "<< dt.days_since_epoch().count() << std::endl;
+ BOOST_TEST( dt.is_valid());
+ }
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ days_date dt(40000,1,1,no_check);
+ BOOST_TEST( ! dt.is_valid());
+ }
+ { // bad construction from bad days: 0
+ try {
+ days_date dt(days(0));
+ BOOST_TEST( false );
+ } catch (...) {}
+ }
+ { // construct from days: 0/1/1
+ days_date dt(days(11979588));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // default constructor
+ days_date dt;
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // construct from ymd: 2011/oct/22
+ days_date dt(year(2011),oct,day(22));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ { // no_check construct from bad ymd: 2011/oct/22
+ days_date dt(2011,10,22, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ { // construct from ymd: 2011/jan_01
+ days_date dt(year(2011),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // no_check construct from ymd: 2011/jan_01
+ days_date dt(2011,jan_01, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // construct from ymd: first day: -32768/jan_01
+ days_date dt(year(-32768),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ BOOST_TEST(dt.days_since_epoch().count()==11322);
+
+ std::cout <<"-32768/jan/01 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from ymd: last day: 32767/dec/31
+ days_date dt(year(32767),dec,day(31));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ BOOST_TEST(dt.days_since_epoch().count()==23947853);
+ std::cout <<"32767/12/31 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from days: first day: -32768/jan_01
+ days_date dt(days(11322));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+
+ }
+ { // construct from days: last day: 32767/dec/31
+ days_date dt(days(23947853));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+
+ { // construct from year + doy:
+ days_date dt(year(2011), day_of_year(1));
+ std::cout << dt << '\n';
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+
+ { // construct from year + doy:
+ days_date dt(year(2011), day_of_year(365));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+ { // construct from year + doy:
+ BOOST_TEST( year(2012).is_leap());
+ days_date dt(year(2012), day_of_year(366));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // construct from bad (year + doy):
+ try {
+ days_date dt(year(2011), day_of_year(366));
+ BOOST_TEST( false );
+ } catch (...) {}
+ }
+
+ // TODO Add construct from year + week + weekday
+
+ { // construct from today
+ days_date dt = days_date::today();
+ BOOST_TEST( dt.is_valid());
+ }
+ { // conversions to/from system_clock::time_point
+ days_date dt(2011,10,22, no_check);
+ boost::chrono::system_clock::time_point tp=boost::chrono::system_clock::time_point(dt);
+ days_date dt2(tp);
+ BOOST_TEST( dt == dt2);
+ }
+ // is_leap_year
+ {
+ days_date dt(2011,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ days_date dt(0,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ days_date dt(4,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ days_date dt(400,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ days_date dt(100,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ days_date dt(200,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ days_date dt(300,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ // get_weekday
+ {
+ BOOST_TEST( days_date(2011,10,23, no_check).get_weekday()==sun);
+ BOOST_TEST( days_date(2011,10,24, no_check).get_weekday()==mon);
+ BOOST_TEST( days_date(2011,10,25, no_check).get_weekday()==tue);
+ BOOST_TEST( days_date(2011,10,26, no_check).get_weekday()==wed);
+ BOOST_TEST( days_date(2011,10,27, no_check).get_weekday()==thu);
+ BOOST_TEST( days_date(2011,10,28, no_check).get_weekday()==fri);
+ BOOST_TEST( days_date(2011,10,29, no_check).get_weekday()==sat);
+ }
+ // day based arithmetic
+ { //+=
+ days_date dt(days(1000000));
+ dt+=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000010));
+ }
+ { // += feb/28 no leap
+ days_date dt(year(2011),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += feb/28 leap
+ days_date dt(year(2012),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ { // += feb/29 leap
+ days_date dt(year(2012),feb,day(29));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month change
+ days_date dt(year(2011),oct,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month+year change
+ days_date dt(year(2011),dec,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // dt++
+ days_date dt(days(1000000));
+ days_date dt2= dt++;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // ++dt
+ days_date dt(days(1000000));
+ days_date dt2 = ++dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+
+ { // -=
+ days_date dt(days(1000010));
+ dt-=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ }
+ { // dt--
+ days_date dt(days(1000001));
+ days_date dt2= dt--;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+ { // --dt
+ days_date dt(days(1000001));
+ days_date dt2 = --dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // -= month + year change
+ days_date dt(year(2011),jan,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // -= month change
+ days_date dt(year(2011),oct,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==30);
+ }
+ {
+ days_date dt(year(2011),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==28);
+ }
+ {
+ days_date dt(year(2012),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+
+ {
+ days_date dt(days(1000000));
+ days_date dt2=dt+days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ days_date dt(days(1000000));
+ days_date dt2=days(10)+dt;
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ days_date dt(days(1000010));
+ days_date dt2=dt-days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ {
+ days_date dt(days(1000010));
+ days_date dt2(days(1000000));
+ BOOST_TEST( dt-dt2==days(10));
+ }
+ {
+ days_date dt(days(1000010));
+ days_date dt2(days(1000000));
+ BOOST_TEST( dt2-dt==days(-10));
+ }
+ // month based arithmetic
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt+=months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt = dt + months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt = months(1) + dt;
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt+=months(3);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2011),jan,day(29));
+ try {
+ dt+=months(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ days_date dt(year(2012),jan,day(29));
+ dt+=months(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()=feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt-=months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2012),mar,day(22));
+ dt-=months(3);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt= dt-months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+
+ // year based arithmetic
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt+=years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2012),feb,day(29));
+ dt+=years(4);
+ BOOST_TEST(dt.get_year()==2016);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ days_date dt(year(2012),feb,day(29));
+ try {
+ dt+=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt = dt + years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt = years(1) + dt;
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt-=years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ days_date dt(year(2012),feb,day(29));
+ dt-=years(4);
+ BOOST_TEST(dt.get_year()==2008);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ days_date dt(year(2012),feb,day(29));
+ try {
+ dt-=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ days_date dt(year(2011),oct,day(22));
+ dt = dt - years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ // TODO add exceptional cases bad result year
+
+ // Relational operators
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 == dt2 );
+ }
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt2 <= dt2 );
+ }
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 > dt2 );
+ }
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 <= dt1 );
+ }
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 < dt1 );
+ }
+ {
+ days_date dt1(year(2011),oct,day(22));
+ days_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 != dt2 );
+ }
+
+ // optional
+ {
+ optional<days_date> odt = make_optional<days_date>(year(2011),oct,day(22));
+ BOOST_TEST( odt );
+ }
+ {
+ optional<days_date> odt = make_optional<days_date>(year(2011),nov,day(31));
+ BOOST_TEST( ! odt );
+ }
+
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/dates/days/nth_days_date_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/dates/days/nth_days_date_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,539 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/relative_date.hpp>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/chrono_io.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+
+ using std::cout;
+ using namespace boost;
+ using namespace boost::chrono;
+
+ typedef boost::chrono::high_resolution_clock Clock;
+ typedef boost::chrono::duration<double, boost::micro> micros;
+
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // construct from ymd: 0/1/1
+ rel_date dt(year(0),jan,day(1));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ rel_date dt(0,0,0,no_check);
+ std::cout <<"0/0/0 days "<< dt.days_since_epoch().count() << std::endl;
+ //BOOST_TEST( dt.is_valid());
+ }
+ std::cout <<"***********"<< std::endl;
+
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ rel_date dt(40000,1,1,no_check);
+ //BOOST_TEST( ! dt.is_valid());
+ }
+ std::cout <<"***********"<< std::endl;
+ { // bad construction from bad days: 0
+ try {
+ rel_date dt(days(0));
+ BOOST_TEST( false );
+ } catch (...) {}
+ }
+ std::cout <<"***********"<< std::endl;
+ { // construct from days: 0/1/1
+ rel_date dt(days(11979588));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ std::cout <<"***********"<< std::endl;
+ { // default constructor
+ rel_date dt;
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ std::cout <<"***********"<< std::endl;
+ { // construct from ymd: 2011/oct/22
+ rel_date dt(year(2011),oct,day(22));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ std::cout <<"***********"<< std::endl;
+ { // no_check construct from bad ymd: 2011/oct/22
+ rel_date dt(2011,10,22, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+
+ { // construct from ymd: 2011/jan_01
+ rel_date dt(year(2011),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // no_check construct from ymd: 2011/jan_01
+ rel_date dt(2011,jan_01, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // construct from ymd: first day: -32768/jan_01
+ rel_date dt(year(-32768),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ BOOST_TEST(dt.days_since_epoch().count()==11322);
+
+ std::cout <<"-32768/jan/01 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from ymd: last day: 32767/dec/31
+ rel_date dt(year(32767),dec,day(31));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ BOOST_TEST(dt.days_since_epoch().count()==23947853);
+ std::cout <<"32767/12/31 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from days: first day: -32768/jan_01
+ rel_date dt(days(11322));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+
+ }
+ { // construct from days: last day: 32767/dec/31
+ rel_date dt(days(23947853));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+
+ { // construct from year + doy:
+ rel_date dt(year(2011), day_of_year(1));
+ std::cout << dt << '\n';
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+
+ { // construct from year + doy:
+ rel_date dt(year(2011), day_of_year(365));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+ { // construct from year + doy:
+ BOOST_TEST( year(2012).is_leap());
+ rel_date dt(year(2012), day_of_year(366));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // construct from bad (year + doy):
+ try {
+ rel_date dt(year(2011), day_of_year(366));
+ BOOST_TEST( false );
+ } catch (...) {}
+ }
+
+ // TODO Add construct from year + week + weekday
+
+ { // construct from today
+ rel_date dt = rel_date::today();
+ BOOST_TEST( dt.is_valid());
+ }
+ { // conversions to/from system_clock::time_point
+ rel_date dt(2011,10,22, no_check);
+ boost::chrono::system_clock::time_point tp=boost::chrono::system_clock::time_point(dt);
+ rel_date dt2(tp);
+ BOOST_TEST( dt == dt2);
+ }
+ // is_leap_year
+ {
+ rel_date dt(2011,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ rel_date dt(0,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ rel_date dt(4,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ rel_date dt(400,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ rel_date dt(100,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ rel_date dt(200,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ rel_date dt(300,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ // get_weekday
+ {
+ BOOST_TEST( rel_date(2011,10,23, no_check).get_weekday()==sun);
+ BOOST_TEST( rel_date(2011,10,24, no_check).get_weekday()==mon);
+ BOOST_TEST( rel_date(2011,10,25, no_check).get_weekday()==tue);
+ BOOST_TEST( rel_date(2011,10,26, no_check).get_weekday()==wed);
+ BOOST_TEST( rel_date(2011,10,27, no_check).get_weekday()==thu);
+ BOOST_TEST( rel_date(2011,10,28, no_check).get_weekday()==fri);
+ BOOST_TEST( rel_date(2011,10,29, no_check).get_weekday()==sat);
+ }
+ // day based arithmetic
+ { //+=
+ rel_date dt(days(1000000));
+ dt+=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000010));
+ }
+ { // += feb/28 no leap
+ rel_date dt(year(2011),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += feb/28 leap
+ rel_date dt(year(2012),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ { // += feb/29 leap
+ rel_date dt(year(2012),feb,day(29));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month change
+ rel_date dt(year(2011),oct,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month+year change
+ rel_date dt(year(2011),dec,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // dt++
+ rel_date dt(days(1000000));
+ rel_date dt2= dt++;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // ++dt
+ rel_date dt(days(1000000));
+ rel_date dt2 = ++dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+
+ { // -=
+ rel_date dt(days(1000010));
+ dt-=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ }
+ { // dt--
+ rel_date dt(days(1000001));
+ rel_date dt2= dt--;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+ { // --dt
+ rel_date dt(days(1000001));
+ rel_date dt2 = --dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // -= month + year change
+ rel_date dt(year(2011),jan,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // -= month change
+ rel_date dt(year(2011),oct,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==30);
+ }
+ {
+ rel_date dt(year(2011),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==28);
+ }
+ {
+ rel_date dt(year(2012),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+
+ {
+ rel_date dt(days(1000000));
+ rel_date dt2=dt+days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ rel_date dt(days(1000000));
+ rel_date dt2=days(10)+dt;
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ rel_date dt(days(1000010));
+ rel_date dt2=dt-days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ {
+ rel_date dt(days(1000010));
+ rel_date dt2(days(1000000));
+ BOOST_TEST( dt-dt2==days(10));
+ }
+ {
+ rel_date dt(days(1000010));
+ rel_date dt2(days(1000000));
+ BOOST_TEST( dt2-dt==days(-10));
+ }
+ std::cout <<"==========="<< std::endl;
+
+ // month based arithmetic
+ {
+ rel_date dt(year(2011),oct,day(22));
+ std::cout <<dt<< std::endl;
+ dt+=months(1);
+ std::cout <<dt<< std::endl;
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ std::cout <<"==========="<< std::endl;
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt = dt + months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ std::cout <<"==========="<< std::endl;
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt = months(1) + dt;
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt+=months(3);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ std::cout <<"/////////"<< std::endl;
+ {
+ rel_date dt(year(2011),jan,day(29));
+ try {
+ dt+=months(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ rel_date dt(year(2012),jan,day(29));
+ dt+=months(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()=feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ std::cout <<"/////////"<< std::endl;
+
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt-=months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ rel_date dt(year(2012),mar,day(22));
+ dt-=months(3);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt= dt-months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+
+ // year based arithmetic
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt+=years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ rel_date dt(year(2012),feb,day(29));
+ dt+=years(4);
+ BOOST_TEST(dt.get_year()==2016);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ rel_date dt(year(2012),feb,day(29));
+ try {
+ dt+=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt = dt + years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt = years(1) + dt;
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt-=years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ std::cout <<"/////////"<< std::endl;
+
+ {
+ rel_date dt(year(2012),feb,day(29));
+ dt-=years(4);
+ BOOST_TEST(dt.get_year()==2008);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ rel_date dt(year(2012),feb,day(29));
+ try {
+ dt-=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ rel_date dt(year(2011),oct,day(22));
+ dt = dt - years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ // TODO add exceptional cases bad result year
+
+ // Relational operators
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 == dt2 );
+ }
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt2 <= dt2 );
+ }
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 > dt2 );
+ }
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 <= dt1 );
+ }
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 < dt1 );
+ }
+ {
+ rel_date dt1(year(2011),oct,day(22));
+ rel_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 != dt2 );
+ }
+
+ // optional
+ {
+ optional<rel_date> odt = make_optional<rel_date>(year(2011),oct,day(22));
+ BOOST_TEST( odt );
+ }
+ {
+ optional<rel_date> odt = make_optional<rel_date>(year(2011),nov,day(31));
+ BOOST_TEST( ! odt );
+ }
+
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/dates/ydoy/ydoy_date_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/dates/ydoy/ydoy_date_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,758 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/ydoy_date.hpp>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/chrono_io.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+
+ using std::cout;
+ using namespace boost;
+ using namespace boost::chrono;
+
+ typedef boost::chrono::high_resolution_clock Clock;
+ typedef boost::chrono::duration<double, boost::micro> micros;
+
+ { // construct from ymd: 0/1/1
+ ydoy_date dt(year(0),jan,day(1));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ }
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ ydoy_date dt(0,0,0,no_check);
+ std::cout <<"0/0/0 days "<< dt.days_since_epoch().count() << std::endl;
+ BOOST_TEST( ! dt.is_valid());
+ }
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ ydoy_date dt(40000,1,1,no_check);
+ BOOST_TEST( ! year(40000,no_check).is_valid());
+ //BOOST_TEST( ! dt.is_valid());
+ }
+ { // bad construction from bad days: 0
+ try {
+ ydoy_date dt(days(0));
+ BOOST_TEST( false );
+ } catch (...) {}
+ }
+ std::cout <<"******* "<< std::endl;
+
+ { // construct from days: 0/1/1
+ ydoy_date dt(days(11979588));
+ std::cout <<dt<< std::endl;
+ std::cout <<"******* "<< std::endl;
+ std::cout <<dt.days_since_epoch().count()<< std::endl;
+
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // default constructor
+ ydoy_date dt;
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // construct from ymd: 2011/oct/22
+ ydoy_date dt(year(2011),oct,day(22));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ { // no_check construct from bad ymd: 2011/oct/22
+ ydoy_date dt(2011,10,22, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ { // construct from ymd: 2011/jan_01
+ ydoy_date dt(year(2011),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // no_check construct from ymd: 2011/jan_01
+ ydoy_date dt(2011,jan_01, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // construct from ymd: first day: -32768/jan_01
+ ydoy_date dt(year(-32768),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ BOOST_TEST(dt.days_since_epoch().count()==11322);
+
+ std::cout <<"-32768/jan/01 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from ymd: last day: 32767/dec/31
+ ydoy_date dt(year(32767),dec,day(31));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ BOOST_TEST(dt.days_since_epoch().count()==23947853);
+ std::cout <<"32767/12/31 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from days: first day: -32768/jan_01
+ ydoy_date dt(days(11322));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+
+ }
+ { // construct from days: last day: 32767/dec/31
+ ydoy_date dt(days(23947853));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+
+ { // construct from year + doy:
+ ydoy_date dt(year(2011), day_of_year(1));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+
+ { // construct from year + doy:
+ ydoy_date dt(year(2011), day_of_year(365));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+ { // construct from year + doy:
+ BOOST_TEST( year(2012).is_leap());
+ ydoy_date dt(year(2012), day_of_year(366));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // construct from bad (year + doy):
+ try {
+ ydoy_date dt(year(2011), day_of_year(366));
+ BOOST_TEST( false );
+ } catch (...) {}
+ }
+
+ // TODO Add construct from year + week + weekday
+
+ { // construct from today
+ ydoy_date dt = ydoy_date::today();
+ BOOST_TEST( dt.is_valid());
+ }
+ { // conversions to/from system_clock::time_point
+ ydoy_date dt(2011,10,22, no_check);
+ boost::chrono::system_clock::time_point tp=boost::chrono::system_clock::time_point(dt);
+ ydoy_date dt2(tp);
+ BOOST_TEST( dt == dt2);
+ }
+ // is_leap_year
+ {
+ ydoy_date dt(2011,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ ydoy_date dt(0,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ ydoy_date dt(4,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ ydoy_date dt(400,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ ydoy_date dt(100,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ ydoy_date dt(200,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ ydoy_date dt(300,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ // get_weekday
+ {
+ BOOST_TEST( ydoy_date(2011,10,23, no_check).get_weekday()==sun);
+ BOOST_TEST( ydoy_date(2011,10,24, no_check).get_weekday()==mon);
+ BOOST_TEST( ydoy_date(2011,10,25, no_check).get_weekday()==tue);
+ BOOST_TEST( ydoy_date(2011,10,26, no_check).get_weekday()==wed);
+ BOOST_TEST( ydoy_date(2011,10,27, no_check).get_weekday()==thu);
+ BOOST_TEST( ydoy_date(2011,10,28, no_check).get_weekday()==fri);
+ BOOST_TEST( ydoy_date(2011,10,29, no_check).get_weekday()==sat);
+ }
+ // day based arithmetic
+ { //+=
+ ydoy_date dt(days(1000000));
+ dt+=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000010));
+ }
+ { // += feb/28 no leap
+ ydoy_date dt(year(2011),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += feb/28 leap
+ ydoy_date dt(year(2012),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ { // += feb/29 leap
+ ydoy_date dt(year(2012),feb,day(29));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month change
+ ydoy_date dt(year(2011),oct,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month+year change
+ ydoy_date dt(year(2011),dec,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // dt++
+ ydoy_date dt(days(1000000));
+ ydoy_date dt2= dt++;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // ++dt
+ ydoy_date dt(days(1000000));
+ ydoy_date dt2 = ++dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+
+ { // -=
+ ydoy_date dt(days(1000010));
+ dt-=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ }
+ { // dt--
+ ydoy_date dt(days(1000001));
+ ydoy_date dt2= dt--;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+ { // --dt
+ ydoy_date dt(days(1000001));
+ ydoy_date dt2 = --dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // -= month + year change
+ ydoy_date dt(year(2011),jan,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // -= month change
+ ydoy_date dt(year(2011),oct,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==30);
+ }
+ {
+ ydoy_date dt(year(2011),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==28);
+ }
+ {
+ ydoy_date dt(year(2012),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+
+ {
+ ydoy_date dt(days(1000000));
+ ydoy_date dt2=dt+days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ ydoy_date dt(days(1000000));
+ ydoy_date dt2=days(10)+dt;
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ ydoy_date dt(days(1000010));
+ ydoy_date dt2=dt-days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ {
+ ydoy_date dt(days(1000010));
+ ydoy_date dt2(days(1000000));
+ BOOST_TEST( dt-dt2==days(10));
+ }
+ {
+ ydoy_date dt(days(1000010));
+ ydoy_date dt2(days(1000000));
+ BOOST_TEST( dt2-dt==days(-10));
+ }
+ // month based arithmetic
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt+=months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt = dt + months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt = months(1) + dt;
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt+=months(3);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2011),jan,day(29));
+ try {
+ dt+=months(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ ydoy_date dt(year(2012),jan,day(29));
+ dt+=months(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()=feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt-=months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2012),mar,day(22));
+ dt-=months(3);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt= dt-months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+
+ // year based arithmetic
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt+=years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2012),feb,day(29));
+ dt+=years(4);
+ BOOST_TEST(dt.get_year()==2016);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ ydoy_date dt(year(2012),feb,day(29));
+ try {
+ dt+=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt = dt + years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt = years(1) + dt;
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt-=years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ydoy_date dt(year(2012),feb,day(29));
+ dt-=years(4);
+ BOOST_TEST(dt.get_year()==2008);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ ydoy_date dt(year(2012),feb,day(29));
+ try {
+ dt-=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ ydoy_date dt(year(2011),oct,day(22));
+ dt = dt - years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ // TODO add exceptional cases bad result year
+
+ // Relational operators
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 == dt2 );
+ }
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt2 <= dt2 );
+ }
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 > dt2 );
+ }
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 <= dt1 );
+ }
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 < dt1 );
+ }
+ {
+ ydoy_date dt1(year(2011),oct,day(22));
+ ydoy_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 != dt2 );
+ }
+
+ // optional
+ {
+ optional<ydoy_date> odt = make_optional<ydoy_date>(year(2011),oct,day(22));
+ BOOST_TEST( odt );
+ }
+ {
+ optional<ydoy_date> odt = make_optional<ydoy_date>(year(2011),nov,day(31));
+ BOOST_TEST( ! odt );
+ }
+
+
+#if 0
+ std::cout << jan / day(2) / 2011 << '\n'; // 2011-01-02
+ std::cout << month(1, no_check) / day(2) / 2011 << '\n'; // 2011-01-02
+ std::cout << ydoy_date(2011, 1, 2, no_check) << '\n'; // 2011-01-02
+ std::cout << '\n';
+
+ std::cout << jan / day(1) / 2011 << '\n'; // 2011-01-02
+ std::cout << jan / day(2) / 2011 << '\n'; // 2011-01-02
+ std::cout << feb / day(1) / 2011 << '\n'; // 2011-01-02
+
+ // Print Feb. 28 for each year in the decade
+ for (ydoy_date d = feb / day(28) / 2010, e = feb / day(28) / 2020; d <= e; d
+ += years(1))
+ std::cout << d << '\n';
+ std::cout << '\n';
+
+ // Print the day after Feb. 28 for each year in the decade
+ for (ydoy_date d = feb / day(28) / 2010, e = feb / day(28) / 2020; d <= e; d
+ += years(1))
+ std::cout << d + days(1) << '\n';
+ std::cout << '\n';
+
+ // Print the 28th of every month in 2011
+ for (ydoy_date d = jan / day(28) / 2011, e = dec / day(28) / 2011; d <= e; d
+ += months(1))
+ std::cout << d << '\n';
+ std::cout << '\n';
+
+ {
+ // How many days between may/1/2011 and jan/1/2011?
+ std::cout << "How many days between may/1/2011 and jan/1/2011? " << (may
+ / day(01) / 2011 - jan / day(01) / 2011) << '\n'; // x == 120
+
+ std::cout << '\n';
+ }
+
+ {
+ ydoy_date dt = aug / day(16) / 2011;
+ int d = dt.get_day(); // d == 16
+ int m = dt.get_month(); // m == 8
+ int y = dt.get_year(); // y == 2011
+ std::cout << dt << '\n';
+ std::cout << y << " " << m << " " << d << '\n';
+ std::cout << '\n';
+ }
+
+ {
+ ydoy_date dt = aug / day(16) / 2011;
+ // ...
+ // Create ydoy_date with the same month and year but on the 5th
+ ydoy_date dt2 = dt.get_year() / dt.get_month() / 5; // aug/5/2011
+ int d = dt.get_day(); // d == 5
+ int m = dt.get_month(); // m == 8
+ int y = dt.get_year(); // y == 2011
+ std::cout << dt << '\n';
+ std::cout << y << " " << m << " " << d << '\n';
+ std::cout << '\n';
+ }
+
+ {
+ ydoy_date dt = aug / day(16) / 2011;
+ // What day of the week is this?
+ int wd = dt.get_weekday(); // 2 (Tuesday)
+ std::cout << dt << '\n';
+ std::cout << wd << '\n';
+ }
+
+ {
+ std::cout << date_fmt("%a %b %e, %Y");
+ // Print the odd fridays of every month in 2011
+ for (ydoy_date d = jan / day(28) / 2011, e = dec / day(28) / 2011; d <= e; d
+ += months(1))
+ {
+ std::cout << d << '\n'; // first Friday of the month
+ }
+ }
+ {
+ Clock::time_point t0 = Clock::now();
+ for (ydoy_date d = feb / day(28) / 2010, e = feb / day(28) / 2020; d != e; d
+ += years(1))
+ ;
+ Clock::time_point t1 = Clock::now();
+ std::cout << " iterate: " << micros(t1 - t0) << "\n";
+ }
+
+ {
+ ydoy_date d1 = jan / _2nd / 2011; // jan/2/2011
+ ydoy_date d2 = year(2011) / jan / _2nd; // jan/2/2011
+ ydoy_date d3 = _2nd / jan / 2011; // jan/2/2011
+ std::cout << d1 << '\n';
+ std::cout << d2 << '\n';
+ std::cout << d3 << '\n';
+ }
+
+ {
+ ydoy_date d1 = last / jan / 2011; // jan/31/2011
+ std::cout << d1 << '\n';
+ }
+
+ {
+ // ydoy_date MothersDay = _sun[2]/may/2011; // may/8/2011
+ // ydoy_date MothersDay2 = _sun[_2nd]/may/2011; // may/8/2011
+ ydoy_date MothersDay2 = _2nd_week * sun / may / 2011; // may/8/2011
+ std::cout << "MothersDay " << MothersDay2 << '\n';
+ }
+
+ {
+ // ydoy_date d1 = _fri[last]/may/2011; // may/27/2011
+ ydoy_date d1 = last_week * fri / may / 2011; // may/27/2011
+ std::cout << d1 << '\n';
+ }
+
+ {
+ // int num_fri_in_may = (_fri[last]/may/2011).get_day() > 28 ? 5 : 4; // 4
+ int num_fri_in_may = (last_week * fri / may / 2011).get_day() > 28 ? 5 : 4; // 4
+ std::cout << "Number of fridays in May" << num_fri_in_may << '\n';
+
+ // ydoy_date d1 = rel_weekday(5)[_1st]/may/2011;
+ ydoy_date d1 = _1st_week * weekday(5) / may / 2011;
+ std::cout << d1 << '\n';
+
+ }
+
+ {
+ // Print the last day in Feb. for each year in the decade
+ for (ydoy_date d = feb / last / 2010, e = feb / last / 2020; d <= e; d
+ += years(1))
+ std::cout << d << '\n';
+ std::cout << feb / last / 2020 << '\n';
+ }
+
+ // {
+ // // Print last day of every month in 2011
+ // for (ydoy_date d = jan/last/2011, e = dec/last/2011; d <= e; d += months(1))
+ // std::cout << d << '\n';
+ // }
+ ////////////////////////
+ std::cout << "***************" << '\n';
+
+ {
+ rel_date d1 = jan / _2nd / 2011; // jan/2/2011
+ rel_date d2 = year(2011) / jan / _2nd; // jan/2/2011
+ rel_date d3 = _2nd / jan / 2011; // jan/2/2011
+
+ std::cout << d1 << '\n';
+ std::cout << d2 << '\n';
+ std::cout << d3 << '\n';
+ }
+ {
+ rel_date d1 = last / jan / 2011; // jan/31/2011
+ std::cout << d1 << '\n';
+ }
+ {
+ int i = 0;
+ // Print the last day in Feb. for each year in the decade
+ for (rel_date d = feb / last / 2010, e = feb / last / 2020; i < 20 && d
+ <= e; d += years(1))
+ {
+ std::cout << d << '\n';
+ ++i;
+ }
+ std::cout << feb / last / 2012 << '\n';
+ std::cout << feb / last / 2016 << '\n';
+ std::cout << feb / last / 2020 << '\n';
+ }
+ {
+ int i = 0;
+ // Print the 29th of every month in 2011
+ for (rel_date d = last / jan / 2011, e = last / dec / 2011; i < 20 && d
+ <= e; d += months(1))
+ {
+ if (d.get_day() >= 29)
+ std::cout << d.get_year() / d.get_month() / 29 << '\n';
+ ++i;
+ }
+ }
+ {
+ // Print the 2nd Tuesday of every odd month in 2011
+ // for (rel_date d = _tue[2]/jan/2011, e = dec/last/2011; d <= e; d += months(2))
+ for (rel_date d = _2nd_week * tue / jan / 2011, e = dec / last / 2011; d
+ <= e; d += months(2))
+ std::cout << d << '\n';
+ }
+ {
+ // Print out every monday between jan/1/2011 and mar/1/2011;
+ //for (ydoy_date d = _mon[_1st]/jan/2011, e = mar/_1st/2011; d <= e; d += days(7))
+ for (ydoy_date d = _1st_week * mon / jan / 2011, e = mar / _1st / 2011; d <= e; d
+ += days(7))
+ std::cout << d << '\n';
+ }
+ {
+ ydoy_date dt = aug / day(16) / 2011;
+ // ...
+ // Get the ydoy_date that is the first occurrence of the same day of the week
+ // in the same month of the next year
+ //rel_date dt2 = dt.get_weekday()[_1st]/dt.get_month()/(dt.get_year() + 1); // aug/7/2012, first Tuesday of Aug 2012
+ rel_date dt2 = _1st_week * dt.get_weekday() / dt.get_month()
+ / (dt.get_year() + 1); // aug/7/2012, first Tuesday of Aug 2012
+ std::cout << dt << '\n';
+ std::cout << dt2 << '\n';
+ }
+ {
+ ydoy_date ISO_week_start = mon <= jan / _4th / 2012;
+ std::cout << "ISO_week_start " << ISO_week_start << '\n';
+ }
+
+ {
+ // How many weeks until Christmas?
+ ydoy_date dt = dec / day(25) / 2011;
+ days d = dt - ydoy_date::today();
+ std::cout << duration_cast<weeks> (d) << '\n';
+ }
+ {
+ // How many average months until Christmas?
+ days d = (dec / day(25) / 2011) - ydoy_date::today();
+ std::cout << duration_cast<average_months> (d) << '\n';
+ }
+ {
+ // How many weeks until Christmas?
+ days d = (dec / day(25) > ydoy_date::today()) - ydoy_date::today();
+ std::cout << duration_cast<weeks> (d) << '\n';
+ }
+ {
+ // How many days until next 28th?
+ days d = (nth(28) > ydoy_date::today()) - ydoy_date::today();
+ std::cout << d << '\n';
+ }
+ {
+ day::rep r = day(2) - day(6);
+ std::cout << int(r) << '\n';
+ }
+#endif
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/dates/ymd/ymd_date_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/dates/ymd/ymd_date_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,763 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/ymd_date.hpp>
+#include <boost/chrono/date/date_io.hpp>
+#include <boost/chrono/chrono_io.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+
+ using std::cout;
+ using namespace boost;
+ using namespace boost::chrono;
+
+ typedef boost::chrono::high_resolution_clock Clock;
+ typedef boost::chrono::duration<double, boost::micro> micros;
+
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // construct from ymd: 0/1/1
+ ymd_date dt(year(0),jan,day(1));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ ymd_date dt(0,0,0,no_check);
+ std::cout <<"0/0/0 days "<< dt.days_since_epoch().count() << std::endl;
+ BOOST_TEST( ! dt.is_valid());
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // unchecked construct from bad ymd: 0/0/0 results in valid date
+ ymd_date dt(40000,1,1,no_check);
+ BOOST_TEST( ! year(40000,no_check).is_valid());
+ //BOOST_TEST( ! dt.is_valid());
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // bad construction from bad days: 0
+ try {
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ days dd(0);
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ ymd_date dt(days(0));
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ BOOST_TEST( false );
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ } catch (...) {}
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // construct from days: 0/1/1
+ ymd_date dt(days(11979588));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.days_since_epoch().count()==11979588);
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ { // default constructor
+ ymd_date dt;
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==0);
+ BOOST_TEST(dt.get_month()==1);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // construct from ymd: 2011/oct/22
+ ymd_date dt(year(2011),oct,day(22));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ { // no_check construct from bad ymd: 2011/oct/22
+ ymd_date dt(2011,10,22, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ { // construct from ymd: 2011/jan_01
+ ymd_date dt(year(2011),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // no_check construct from ymd: 2011/jan_01
+ ymd_date dt(2011,jan_01, no_check);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // construct from ymd: first day: -32768/jan_01
+ ymd_date dt(year(-32768),jan_01);
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ BOOST_TEST(dt.days_since_epoch().count()==11322);
+
+ std::cout <<"-32768/jan/01 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from ymd: last day: 32767/dec/31
+ ymd_date dt(year(32767),dec,day(31));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ BOOST_TEST(dt.days_since_epoch().count()==23947853);
+ std::cout <<"32767/12/31 days "<< dt.days_since_epoch().count() << std::endl;
+ }
+ { // construct from days: first day: -32768/jan_01
+ ymd_date dt(days(11322));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==-32768);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+
+ }
+ { // construct from days: last day: 32767/dec/31
+ ymd_date dt(days(23947853));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==32767);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+
+ { // construct from year + doy:
+ ymd_date dt(year(2011), day_of_year(1));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+
+ { // construct from year + doy:
+ ymd_date dt(year(2011), day_of_year(365));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+ { // construct from year + doy:
+ BOOST_TEST( year(2012).is_leap());
+ ymd_date dt(year(2012), day_of_year(366));
+ BOOST_TEST( dt.is_valid());
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // construct from bad (year + doy):
+ try {
+ ymd_date dt(year(2011), day_of_year(366));
+ BOOST_TEST( false );
+ } catch (...) {}
+ }
+
+ // TODO Add construct from year + week + weekday
+
+ { // construct from today
+ ymd_date dt = ymd_date::today();
+ BOOST_TEST( dt.is_valid());
+ }
+ { // conversions to/from system_clock::time_point
+ ymd_date dt(2011,10,22, no_check);
+ boost::chrono::system_clock::time_point tp=boost::chrono::system_clock::time_point(dt);
+ ymd_date dt2(tp);
+ BOOST_TEST( dt == dt2);
+ }
+ // is_leap_year
+ {
+ ymd_date dt(2011,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ ymd_date dt(0,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ ymd_date dt(4,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ ymd_date dt(400,10,22, no_check);
+ BOOST_TEST( dt.is_leap_year());
+ }
+ {
+ ymd_date dt(100,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ ymd_date dt(200,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ {
+ ymd_date dt(300,10,22, no_check);
+ BOOST_TEST( ! dt.is_leap_year());
+ }
+ // get_weekday
+ {
+ BOOST_TEST( ymd_date(2011,10,23, no_check).get_weekday()==sun);
+ BOOST_TEST( ymd_date(2011,10,24, no_check).get_weekday()==mon);
+ BOOST_TEST( ymd_date(2011,10,25, no_check).get_weekday()==tue);
+ BOOST_TEST( ymd_date(2011,10,26, no_check).get_weekday()==wed);
+ BOOST_TEST( ymd_date(2011,10,27, no_check).get_weekday()==thu);
+ BOOST_TEST( ymd_date(2011,10,28, no_check).get_weekday()==fri);
+ BOOST_TEST( ymd_date(2011,10,29, no_check).get_weekday()==sat);
+ }
+ // day based arithmetic
+ { //+=
+ ymd_date dt(days(1000000));
+ dt+=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000010));
+ }
+ { // += feb/28 no leap
+ ymd_date dt(year(2011),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += feb/28 leap
+ ymd_date dt(year(2012),feb,day(28));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ { // += feb/29 leap
+ ymd_date dt(year(2012),feb,day(29));
+ dt+=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==mar);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month change
+ ymd_date dt(year(2011),oct,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // += month+year change
+ ymd_date dt(year(2011),dec,day(22));
+ dt+=days(10);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==1);
+ }
+ { // dt++
+ ymd_date dt(days(1000000));
+ ymd_date dt2= dt++;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // ++dt
+ ymd_date dt(days(1000000));
+ ymd_date dt2 = ++dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000001));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+
+ { // -=
+ ymd_date dt(days(1000010));
+ dt-=days(10);
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ }
+ { // dt--
+ ymd_date dt(days(1000001));
+ ymd_date dt2= dt--;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000001));
+ }
+ { // --dt
+ ymd_date dt(days(1000001));
+ ymd_date dt2 = --dt;
+ BOOST_TEST( dt.days_since_epoch()==days(1000000));
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ { // -= month + year change
+ ymd_date dt(year(2011),jan,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==31);
+ }
+
+ { // -= month change
+ ymd_date dt(year(2011),oct,day(10));
+ dt-=days(10);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==30);
+ }
+ {
+ ymd_date dt(year(2011),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==28);
+ }
+ {
+ ymd_date dt(year(2012),mar,day(1));
+ dt-=days(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+
+ {
+ ymd_date dt(days(1000000));
+ ymd_date dt2=dt+days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ ymd_date dt(days(1000000));
+ ymd_date dt2=days(10)+dt;
+ BOOST_TEST( dt2.days_since_epoch()==days(1000010));
+ }
+ {
+ ymd_date dt(days(1000010));
+ ymd_date dt2=dt-days(10);
+ BOOST_TEST( dt2.days_since_epoch()==days(1000000));
+ }
+ {
+ ymd_date dt(days(1000010));
+ ymd_date dt2(days(1000000));
+ BOOST_TEST( dt-dt2==days(10));
+ }
+ {
+ ymd_date dt(days(1000010));
+ ymd_date dt2(days(1000000));
+ BOOST_TEST( dt2-dt==days(-10));
+ }
+ // month based arithmetic
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt+=months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt = dt + months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt = months(1) + dt;
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==nov);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt+=months(3);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==jan);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2011),jan,day(29));
+ try {
+ dt+=months(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ ymd_date dt(year(2012),jan,day(29));
+ dt+=months(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()=feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt-=months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2012),mar,day(22));
+ dt-=months(3);
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==dec);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt= dt-months(1);
+
+ BOOST_TEST(dt.get_year()==2011);
+ BOOST_TEST(dt.get_month()==sep);
+ BOOST_TEST(dt.get_day()==22);
+ }
+
+ // year based arithmetic
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt+=years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2012),feb,day(29));
+ dt+=years(4);
+ BOOST_TEST(dt.get_year()==2016);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ ymd_date dt(year(2012),feb,day(29));
+ try {
+ dt+=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt = dt + years(1);
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt = years(1) + dt;
+ BOOST_TEST(dt.get_year()==2012);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt-=years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ {
+ ymd_date dt(year(2012),feb,day(29));
+ dt-=years(4);
+ BOOST_TEST(dt.get_year()==2008);
+ BOOST_TEST(dt.get_month()==feb);
+ BOOST_TEST(dt.get_day()==29);
+ }
+ {
+ ymd_date dt(year(2012),feb,day(29));
+ try {
+ dt-=years(1);
+ BOOST_TEST(false);
+ } catch (...) {}
+ }
+ {
+ ymd_date dt(year(2011),oct,day(22));
+ dt = dt - years(1);
+ BOOST_TEST(dt.get_year()==2010);
+ BOOST_TEST(dt.get_month()==oct);
+ BOOST_TEST(dt.get_day()==22);
+ }
+ // TODO add exceptional cases bad result year
+
+ // Relational operators
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 == dt2 );
+ }
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),oct,day(22));
+ BOOST_TEST( dt2 <= dt2 );
+ }
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 >= dt2 );
+ }
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 > dt2 );
+ }
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 <= dt1 );
+ }
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt2 < dt1 );
+ }
+ {
+ ymd_date dt1(year(2011),oct,day(22));
+ ymd_date dt2(year(2011),sep,day(22));
+ BOOST_TEST( dt1 != dt2 );
+ }
+
+ // optional
+ {
+ optional<ymd_date> odt = make_optional<ymd_date>(year(2011),oct,day(22));
+ BOOST_TEST( odt );
+ }
+ {
+ optional<ymd_date> odt = make_optional<ymd_date>(year(2011),nov,day(31));
+ BOOST_TEST( ! odt );
+ }
+
+
+#if 0
+ std::cout << jan / day(2) / 2011 << '\n'; // 2011-01-02
+ std::cout << month(1, no_check) / day(2) / 2011 << '\n'; // 2011-01-02
+ std::cout << ymd_date(2011, 1, 2, no_check) << '\n'; // 2011-01-02
+ std::cout << '\n';
+
+ std::cout << jan / day(1) / 2011 << '\n'; // 2011-01-02
+ std::cout << jan / day(2) / 2011 << '\n'; // 2011-01-02
+ std::cout << feb / day(1) / 2011 << '\n'; // 2011-01-02
+
+ // Print Feb. 28 for each year in the decade
+ for (ymd_date d = feb / day(28) / 2010, e = feb / day(28) / 2020; d <= e; d
+ += years(1))
+ std::cout << d << '\n';
+ std::cout << '\n';
+
+ // Print the day after Feb. 28 for each year in the decade
+ for (ymd_date d = feb / day(28) / 2010, e = feb / day(28) / 2020; d <= e; d
+ += years(1))
+ std::cout << d + days(1) << '\n';
+ std::cout << '\n';
+
+ // Print the 28th of every month in 2011
+ for (ymd_date d = jan / day(28) / 2011, e = dec / day(28) / 2011; d <= e; d
+ += months(1))
+ std::cout << d << '\n';
+ std::cout << '\n';
+
+ {
+ // How many days between may/1/2011 and jan/1/2011?
+ std::cout << "How many days between may/1/2011 and jan/1/2011? " << (may
+ / day(01) / 2011 - jan / day(01) / 2011) << '\n'; // x == 120
+
+ std::cout << '\n';
+ }
+
+ {
+ ymd_date dt = aug / day(16) / 2011;
+ int d = dt.get_day(); // d == 16
+ int m = dt.get_month(); // m == 8
+ int y = dt.get_year(); // y == 2011
+ std::cout << dt << '\n';
+ std::cout << y << " " << m << " " << d << '\n';
+ std::cout << '\n';
+ }
+
+ {
+ ymd_date dt = aug / day(16) / 2011;
+ // ...
+ // Create ymd_date with the same month and year but on the 5th
+ ymd_date dt2 = dt.get_year() / dt.get_month() / 5; // aug/5/2011
+ int d = dt.get_day(); // d == 5
+ int m = dt.get_month(); // m == 8
+ int y = dt.get_year(); // y == 2011
+ std::cout << dt << '\n';
+ std::cout << y << " " << m << " " << d << '\n';
+ std::cout << '\n';
+ }
+
+ {
+ ymd_date dt = aug / day(16) / 2011;
+ // What day of the week is this?
+ int wd = dt.get_weekday(); // 2 (Tuesday)
+ std::cout << dt << '\n';
+ std::cout << wd << '\n';
+ }
+
+ {
+ std::cout << date_fmt("%a %b %e, %Y");
+ // Print the odd fridays of every month in 2011
+ for (ymd_date d = jan / day(28) / 2011, e = dec / day(28) / 2011; d <= e; d
+ += months(1))
+ {
+ std::cout << d << '\n'; // first Friday of the month
+ }
+ }
+ {
+ Clock::time_point t0 = Clock::now();
+ for (ymd_date d = feb / day(28) / 2010, e = feb / day(28) / 2020; d != e; d
+ += years(1))
+ ;
+ Clock::time_point t1 = Clock::now();
+ std::cout << " iterate: " << micros(t1 - t0) << "\n";
+ }
+
+ {
+ ymd_date d1 = jan / _2nd / 2011; // jan/2/2011
+ ymd_date d2 = year(2011) / jan / _2nd; // jan/2/2011
+ ymd_date d3 = _2nd / jan / 2011; // jan/2/2011
+ std::cout << d1 << '\n';
+ std::cout << d2 << '\n';
+ std::cout << d3 << '\n';
+ }
+
+ {
+ ymd_date d1 = last / jan / 2011; // jan/31/2011
+ std::cout << d1 << '\n';
+ }
+
+ {
+ // ymd_date MothersDay = _sun[2]/may/2011; // may/8/2011
+ // ymd_date MothersDay2 = _sun[_2nd]/may/2011; // may/8/2011
+ ymd_date MothersDay2 = _2nd_week * sun / may / 2011; // may/8/2011
+ std::cout << "MothersDay " << MothersDay2 << '\n';
+ }
+
+ {
+ // ymd_date d1 = _fri[last]/may/2011; // may/27/2011
+ ymd_date d1 = last_week * fri / may / 2011; // may/27/2011
+ std::cout << d1 << '\n';
+ }
+
+ {
+ // int num_fri_in_may = (_fri[last]/may/2011).get_day() > 28 ? 5 : 4; // 4
+ int num_fri_in_may = (last_week * fri / may / 2011).get_day() > 28 ? 5 : 4; // 4
+ std::cout << "Number of fridays in May" << num_fri_in_may << '\n';
+
+ // ymd_date d1 = rel_weekday(5)[_1st]/may/2011;
+ ymd_date d1 = _1st_week * weekday(5) / may / 2011;
+ std::cout << d1 << '\n';
+
+ }
+
+ {
+ // Print the last day in Feb. for each year in the decade
+ for (ymd_date d = feb / last / 2010, e = feb / last / 2020; d <= e; d
+ += years(1))
+ std::cout << d << '\n';
+ std::cout << feb / last / 2020 << '\n';
+ }
+
+ // {
+ // // Print last day of every month in 2011
+ // for (ymd_date d = jan/last/2011, e = dec/last/2011; d <= e; d += months(1))
+ // std::cout << d << '\n';
+ // }
+ ////////////////////////
+ std::cout << "***************" << '\n';
+
+ {
+ rel_date d1 = jan / _2nd / 2011; // jan/2/2011
+ rel_date d2 = year(2011) / jan / _2nd; // jan/2/2011
+ rel_date d3 = _2nd / jan / 2011; // jan/2/2011
+
+ std::cout << d1 << '\n';
+ std::cout << d2 << '\n';
+ std::cout << d3 << '\n';
+ }
+ {
+ rel_date d1 = last / jan / 2011; // jan/31/2011
+ std::cout << d1 << '\n';
+ }
+ {
+ int i = 0;
+ // Print the last day in Feb. for each year in the decade
+ for (rel_date d = feb / last / 2010, e = feb / last / 2020; i < 20 && d
+ <= e; d += years(1))
+ {
+ std::cout << d << '\n';
+ ++i;
+ }
+ std::cout << feb / last / 2012 << '\n';
+ std::cout << feb / last / 2016 << '\n';
+ std::cout << feb / last / 2020 << '\n';
+ }
+ {
+ int i = 0;
+ // Print the 29th of every month in 2011
+ for (rel_date d = last / jan / 2011, e = last / dec / 2011; i < 20 && d
+ <= e; d += months(1))
+ {
+ if (d.get_day() >= 29)
+ std::cout << d.get_year() / d.get_month() / 29 << '\n';
+ ++i;
+ }
+ }
+ {
+ // Print the 2nd Tuesday of every odd month in 2011
+ // for (rel_date d = _tue[2]/jan/2011, e = dec/last/2011; d <= e; d += months(2))
+ for (rel_date d = _2nd_week * tue / jan / 2011, e = dec / last / 2011; d
+ <= e; d += months(2))
+ std::cout << d << '\n';
+ }
+ {
+ // Print out every monday between jan/1/2011 and mar/1/2011;
+ //for (ymd_date d = _mon[_1st]/jan/2011, e = mar/_1st/2011; d <= e; d += days(7))
+ for (ymd_date d = _1st_week * mon / jan / 2011, e = mar / _1st / 2011; d <= e; d
+ += days(7))
+ std::cout << d << '\n';
+ }
+ {
+ ymd_date dt = aug / day(16) / 2011;
+ // ...
+ // Get the ymd_date that is the first occurrence of the same day of the week
+ // in the same month of the next year
+ //rel_date dt2 = dt.get_weekday()[_1st]/dt.get_month()/(dt.get_year() + 1); // aug/7/2012, first Tuesday of Aug 2012
+ rel_date dt2 = _1st_week * dt.get_weekday() / dt.get_month()
+ / (dt.get_year() + 1); // aug/7/2012, first Tuesday of Aug 2012
+ std::cout << dt << '\n';
+ std::cout << dt2 << '\n';
+ }
+ {
+ ymd_date ISO_week_start = mon <= jan / _4th / 2012;
+ std::cout << "ISO_week_start " << ISO_week_start << '\n';
+ }
+
+ {
+ // How many weeks until Christmas?
+ ymd_date dt = dec / day(25) / 2011;
+ days d = dt - ymd_date::today();
+ std::cout << duration_cast<weeks> (d) << '\n';
+ }
+ {
+ // How many average months until Christmas?
+ days d = (dec / day(25) / 2011) - ymd_date::today();
+ std::cout << duration_cast<average_months> (d) << '\n';
+ }
+ {
+ // How many weeks until Christmas?
+ days d = (dec / day(25) > ymd_date::today()) - ymd_date::today();
+ std::cout << duration_cast<weeks> (d) << '\n';
+ }
+ {
+ // How many days until next 28th?
+ days d = (nth(28) > ymd_date::today()) - ymd_date::today();
+ std::cout << d << '\n';
+ }
+ {
+ day::rep r = day(2) - day(6);
+ std::cout << int(r) << '\n';
+ }
+#endif
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/day_of_year_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/day_of_year_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,66 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/day_of_year.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::chrono;
+
+ {
+ try
+ {
+ day_of_year doy(0);
+ BOOST_TEST(false && "0 is not a valid day of year");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ try
+ {
+ day_of_year doy(367);
+ BOOST_TEST(false && "367 is not a valid day of year");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ day_of_year doy(0, no_check);
+ BOOST_TEST(!doy.is_valid() && "0 is not a valid day of year");
+ }
+ {
+ day_of_year doy(367, no_check);
+ BOOST_TEST(!doy.is_valid() && "367 is not a valid day of year");
+ }
+ {
+ day_of_year doy(-1, no_check);
+ BOOST_TEST(!doy.is_valid() && "-1 is not a valid day of year");
+ }
+ {
+ day_of_year doy(1);
+ BOOST_TEST(doy.is_valid() && "1 is a valid day of year");
+ }
+ {
+ day_of_year doy(366);
+ BOOST_TEST(doy.is_valid() && "366 is a valid day of year");
+ }
+ {
+ day_of_year doy(2);
+ BOOST_TEST(doy.is_valid() && "2 is a valid day of year");
+ day_of_year::rep i = doy;
+ BOOST_TEST(i==2);
+ }
+ {
+ day_of_year doy(3);
+ BOOST_TEST(doy.is_valid() && "2 is a valid day of year");
+ day_of_year::rep i = doy.value();
+ BOOST_TEST(i==3);
+ }
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/day_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/day_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,66 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/day.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::chrono;
+
+ {
+ try
+ {
+ day d(0);
+ BOOST_TEST(false && "0 is not a valid day");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ try
+ {
+ day d(32);
+ BOOST_TEST(false && "32 is not a valid day");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ day d(0, no_check);
+ BOOST_TEST(!d.is_valid() && "0 is not a valid day");
+ }
+ {
+ day d(32, no_check);
+ BOOST_TEST(!d.is_valid() && "32 is not a valid day");
+ }
+ {
+ day d(-1, no_check);
+ BOOST_TEST(!d.is_valid() && "-1 is not a valid day");
+ }
+ {
+ day d(1);
+ BOOST_TEST(d.is_valid() && "1 is a valid day");
+ }
+ {
+ day d(31);
+ BOOST_TEST(d.is_valid() );
+ }
+ {
+ day d(2);
+ BOOST_TEST(d.is_valid() && "2 is a valid day");
+ day::rep i = d;
+ BOOST_TEST(i==2);
+ }
+ {
+ day d(3);
+ BOOST_TEST(d.is_valid() && "2 is a valid day");
+ day::rep i = d.value();
+ BOOST_TEST(i==3);
+ }
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/month_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/month_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,66 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/month.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::chrono;
+
+ {
+ try
+ {
+ month d(0);
+ BOOST_TEST(false && "0 is not a valid month");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ try
+ {
+ month d(13);
+ BOOST_TEST(false && "13 is not a valid month");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ month d(0, no_check);
+ BOOST_TEST(!d.is_valid() && "0 is not a valid month");
+ }
+ {
+ month d(13, no_check);
+ BOOST_TEST(!d.is_valid() && "13 is not a valid month");
+ }
+ {
+ month d(-1, no_check);
+ BOOST_TEST(!d.is_valid() && "-1 is not a valid month");
+ }
+ {
+ month d(1);
+ BOOST_TEST(d.is_valid() && "1 is a valid month");
+ }
+ {
+ month d(12);
+ BOOST_TEST(d.is_valid() );
+ }
+ {
+ month d(2);
+ BOOST_TEST(d.is_valid() && "2 is a valid month");
+ month::rep i = d;
+ BOOST_TEST(i==2);
+ }
+ {
+ month d(3);
+ BOOST_TEST(d.is_valid() && "2 is a valid month");
+ month::rep i = d.value();
+ BOOST_TEST(i==3);
+ }
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/nth_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/nth_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,96 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/nth.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+#if 0
+ using namespace boost::chrono;
+
+ {
+ try
+ {
+ nth d(0);
+ BOOST_TEST(false && "0 is not a valid nth");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ try
+ {
+ nth d(7);
+ BOOST_TEST(false && "7 is not a valid nth");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ nth d(0, no_check);
+ BOOST_TEST(!d.is_valid() && "0 is not a valid nth");
+ }
+ {
+ nth d(7, no_check);
+ BOOST_TEST(!d.is_valid() && "7 is not a valid nth");
+ }
+ {
+ nth d(-1, no_check);
+ BOOST_TEST(!d.is_valid() && "-1 is not a valid nth");
+ }
+ {
+ nth d(1);
+ BOOST_TEST(d.is_valid() && "1 is a valid nth");
+ }
+ {
+ nth d(5);
+ BOOST_TEST(d.is_valid() );
+ }
+ {
+ nth d(6);
+ BOOST_TEST(d.is_valid() );
+ }
+ {
+ nth d(2);
+ BOOST_TEST(d.is_valid() && "2 is a valid nth");
+ nth::rep i = d;
+ BOOST_TEST(i==2);
+ }
+ {
+ nth d(3);
+ BOOST_TEST(d.is_valid() && "3 is a valid nth");
+ nth::rep i = d.value();
+ BOOST_TEST(i==3);
+ }
+#endif
+// {
+// BOOST_TEST(_1st.is_valid() );
+// BOOST_TEST(_1st==nth(1));
+// }
+// {
+// BOOST_TEST(_2nd.is_valid() );
+// BOOST_TEST(_2nd==nth(2));
+// }
+// {
+// BOOST_TEST(_3rd.is_valid() );
+// BOOST_TEST(_3rd==nth(3));
+// }
+// {
+// BOOST_TEST(_4th.is_valid() );
+// BOOST_TEST(_4th==nth(4));
+// }
+// {
+// BOOST_TEST(_5th.is_valid() );
+// BOOST_TEST(_5th==nth(5));
+// }
+// {
+// BOOST_TEST(last.is_valid() );
+// BOOST_TEST(last==nth(6));
+// }
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/nth_week_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/nth_week_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,109 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/nth_week.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::chrono;
+
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ try
+ {
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ nth_week d(0);
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ BOOST_TEST(false && "0 is not a valid nth_week");
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ }
+ catch (...)
+ {
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ }
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ try
+ {
+ nth_week d(7);
+ BOOST_TEST(false && "7 is not a valid nth_week");
+ }
+ catch (...)
+ {
+ }
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(0, no_check);
+ BOOST_TEST(!d.is_valid() && "0 is not a valid nth_week");
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(7, no_check);
+ BOOST_TEST(!d.is_valid() && "7 is not a valid nth_week");
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(-1, no_check);
+ BOOST_TEST(!d.is_valid() && "-1 is not a valid nth_week");
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(1);
+ BOOST_TEST(d.is_valid() && "1 is a valid nth_week");
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(5);
+ BOOST_TEST(d.is_valid() );
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(6);
+ BOOST_TEST(d.is_valid() );
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(2);
+ BOOST_TEST(d.is_valid() && "2 is a valid nth_week");
+ nth_week::rep i = d;
+ BOOST_TEST(i==2);
+ }
+ std::cerr << __FILE__ << ":" << __LINE__ << " " << std::endl;
+ {
+ nth_week d(3);
+ BOOST_TEST(d.is_valid() && "3 is a valid nth_week");
+ nth_week::rep i = d.value();
+ BOOST_TEST(i==3);
+ }
+// {
+// BOOST_TEST(_1st_week.is_valid() );
+// BOOST_TEST(_1st_week==nth_week(1));
+// }
+// {
+// BOOST_TEST(_2nd_week.is_valid() );
+// BOOST_TEST(_2nd_week==nth_week(2));
+// }
+// {
+// BOOST_TEST(_3rd_week.is_valid() );
+// BOOST_TEST(_3rd_week==nth_week(3));
+// }
+// {
+// BOOST_TEST(_4th_week.is_valid() );
+// BOOST_TEST(_4th_week==nth_week(4));
+// }
+// {
+// BOOST_TEST(_5th_week.is_valid() );
+// BOOST_TEST(_5th_week==nth_week(5));
+// }
+// {
+// BOOST_TEST(last_week.is_valid() );
+// BOOST_TEST(last_week==nth_week(6));
+// }
+
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/week_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/week_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,66 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/week.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::chrono;
+
+ {
+ try
+ {
+ week d(0);
+ BOOST_TEST(false && "0 is not a valid week");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ try
+ {
+ week d(54);
+ BOOST_TEST(false && "54 is not a valid week");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ week d(0, no_check);
+ BOOST_TEST(!d.is_valid() && "0 is not a valid week");
+ }
+ {
+ week d(54, no_check);
+ BOOST_TEST(!d.is_valid() && "54 is not a valid week");
+ }
+ {
+ week d(-1, no_check);
+ BOOST_TEST(!d.is_valid() && "-1 is not a valid week");
+ }
+ {
+ week d(1);
+ BOOST_TEST(d.is_valid() && "1 is a valid week");
+ }
+ {
+ week d(53);
+ BOOST_TEST(d.is_valid() );
+ }
+ {
+ week d(2);
+ BOOST_TEST(d.is_valid() && "2 is a valid week");
+ week::rep i = d;
+ BOOST_TEST(i==2);
+ }
+ {
+ week d(3);
+ BOOST_TEST(d.is_valid() && "2 is a valid week");
+ week::rep i = d.value();
+ BOOST_TEST(i==3);
+ }
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/weekday_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/weekday_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,94 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/weekday.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::chrono;
+
+ {
+ try
+ {
+ weekday d(-1);
+ BOOST_TEST(false && "-1 is not a valid weekday");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ try
+ {
+ weekday d(7);
+ BOOST_TEST(false && "7 is not a valid weekday");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ weekday d(-1, no_check);
+ BOOST_TEST(!d.is_valid() && "-1 is not a valid weekday");
+ }
+ {
+ weekday d(7, no_check);
+ BOOST_TEST(!d.is_valid() && "7 is not a valid weekday");
+ }
+ {
+ weekday d(1);
+ BOOST_TEST(d.is_valid() && "1 is a valid weekday");
+ }
+ {
+ weekday d(5);
+ BOOST_TEST(d.is_valid() );
+ }
+ {
+ weekday d(6);
+ BOOST_TEST(d.is_valid() );
+ }
+ {
+ weekday d(2);
+ BOOST_TEST(d.is_valid() && "2 is a valid weekday");
+ weekday::rep i = d;
+ BOOST_TEST(i==2);
+ }
+ {
+ weekday d(3);
+ BOOST_TEST(d.is_valid() && "3 is a valid weekday");
+ weekday::rep i = d.value();
+ BOOST_TEST(i==3);
+ }
+ {
+ BOOST_TEST(sun.is_valid() );
+ BOOST_TEST(sun==weekday(0));
+ }
+ {
+ BOOST_TEST(mon.is_valid() );
+ BOOST_TEST(mon==weekday(1));
+ }
+ {
+ BOOST_TEST(tue.is_valid() );
+ BOOST_TEST(tue==weekday(2));
+ }
+ {
+ BOOST_TEST(wed.is_valid() );
+ BOOST_TEST(wed==weekday(3));
+ }
+ {
+ BOOST_TEST(thu.is_valid() );
+ BOOST_TEST(thu==weekday(4));
+ }
+ {
+ BOOST_TEST(fri.is_valid() );
+ BOOST_TEST(fri==weekday(5));
+ }
+ {
+ BOOST_TEST(sat.is_valid() );
+ BOOST_TEST(sat==weekday(6));
+ }
+ return boost::report_errors();
+}

Added: sandbox/chrono_date/libs/date/test/wrappers/year_pass.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono_date/libs/date/test/wrappers/year_pass.cpp 2011-11-09 18:17:27 EST (Wed, 09 Nov 2011)
@@ -0,0 +1,62 @@
+// Copyright 2010 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/chrono/date/year.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ using namespace boost::chrono;
+
+ {
+ try
+ {
+ year d(-32769);
+ BOOST_TEST(false && "-32769 is not a valid year");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ try
+ {
+ year d(32768);
+ BOOST_TEST(false && "32768 is not a valid year");
+ }
+ catch (...)
+ {
+ }
+ }
+ {
+ year d(-32769, no_check);
+ BOOST_TEST(!d.is_valid() && "-32769 is not a valid year");
+ }
+ {
+ year d(32768, no_check);
+ BOOST_TEST(!d.is_valid() && "32768 is not a valid year");
+ }
+ {
+ year d(0);
+ BOOST_TEST(d.is_valid() && "0 is a valid year");
+ }
+ {
+ year d(1);
+ BOOST_TEST(d.is_valid() && "1 is a valid year");
+ }
+ {
+ year d(2);
+ BOOST_TEST(d.is_valid() && "2 is a valid year");
+ year::rep i = d;
+ BOOST_TEST(i==2);
+ }
+ {
+ year d(3);
+ BOOST_TEST(d.is_valid() && "2 is a valid year");
+ year::rep i = d.value();
+ BOOST_TEST(i==3);
+ }
+ return boost::report_errors();
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk