1 #ifndef DATE_TIME_DATE_HPP___
2 #define DATE_TIME_DATE_HPP___
3 
4 /* Copyright (c) 2002,2003 CrystalClear Software, Inc.
5  * Use, modification and distribution is subject to the
6  * Boost Software License, Version 1.0. (See accompanying
7  * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
8  * Author: Jeff Garland, Bart Garst
9  * $Date$
10  */
11 
12 #include <boost/operators.hpp>
13 #include <boost/date_time/compiler_config.hpp>
14 #include <boost/date_time/year_month_day.hpp>
15 #include <boost/date_time/special_defs.hpp>
16 
17 namespace boost {
18 namespace date_time {
19 
20   //!Representation of timepoint at the one day level resolution.
21   /*!
22     The date template represents an interface shell for a date class
23     that is based on a year-month-day system such as the gregorian
24     or iso systems.  It provides basic operations to enable calculation
25     and comparisons.
26 
27     <b>Theory</b>
28 
29     This date representation fundamentally departs from the C tm struct
30     approach.  The goal for this type is to provide efficient date
31     operations (add, subtract) and storage (minimize space to represent)
32     in a concrete class.  Thus, the date uses a count internally to
33     represent a particular date.  The calendar parameter defines
34     the policies for converting the the year-month-day and internal
35     counted form here.  Applications that need to perform heavy
36     formatting of the same date repeatedly will perform better
37     by using the year-month-day representation.
38 
39     Internally the date uses a day number to represent the date.
40     This is a monotonic time representation. This representation
41     allows for fast comparison as well as simplifying
42     the creation of writing numeric operations.  Essentially, the
43     internal day number is like adjusted julian day.  The adjustment
44     is determined by the Epoch date which is represented as day 1 of
45     the calendar.  Day 0 is reserved for negative infinity so that
46     any actual date is automatically greater than negative infinity.
47     When a date is constructed from a date or formatted for output,
48     the appropriate conversions are applied to create the year, month,
49     day representations.
50   */
51 
52 
53   template<class T, class calendar, class duration_type_>
54   class BOOST_SYMBOL_VISIBLE date : private
55        boost::less_than_comparable<T
56      , boost::equality_comparable<T
57     > >
58   {
59   public:
60     typedef T date_type;
61     typedef calendar calendar_type;
62     typedef typename calendar::date_traits_type traits_type;
63     typedef duration_type_ duration_type;
64     typedef typename calendar::year_type year_type;
65     typedef typename calendar::month_type month_type;
66     typedef typename calendar::day_type day_type;
67     typedef typename calendar::ymd_type ymd_type;
68     typedef typename calendar::date_rep_type date_rep_type;
69     typedef typename calendar::date_int_type date_int_type;
70     typedef typename calendar::day_of_week_type day_of_week_type;
date(year_type y,month_type m,day_type d)71     BOOST_CXX14_CONSTEXPR date(year_type y, month_type m, day_type d)
72       : days_(calendar::day_number(ymd_type(y, m, d)))
73     {}
date(const ymd_type & ymd)74     BOOST_CXX14_CONSTEXPR date(const ymd_type& ymd)
75       : days_(calendar::day_number(ymd))
76     {}
77     //let the compiler write copy, assignment, and destructor
year() const78     BOOST_CXX14_CONSTEXPR year_type        year() const
79     {
80       ymd_type ymd = calendar::from_day_number(days_);
81       return ymd.year;
82     }
month() const83     BOOST_CXX14_CONSTEXPR month_type       month() const
84     {
85       ymd_type ymd = calendar::from_day_number(days_);
86       return ymd.month;
87     }
day() const88     BOOST_CXX14_CONSTEXPR day_type         day() const
89     {
90       ymd_type ymd = calendar::from_day_number(days_);
91       return ymd.day;
92     }
day_of_week() const93     BOOST_CXX14_CONSTEXPR day_of_week_type day_of_week() const
94     {
95       ymd_type ymd = calendar::from_day_number(days_);
96       return calendar::day_of_week(ymd);
97     }
year_month_day() const98     BOOST_CXX14_CONSTEXPR ymd_type         year_month_day() const
99     {
100       return calendar::from_day_number(days_);
101     }
operator <(const date_type & rhs) const102     BOOST_CONSTEXPR bool operator<(const date_type& rhs)  const
103     {
104       return days_ < rhs.days_;
105     }
operator ==(const date_type & rhs) const106     BOOST_CONSTEXPR bool operator==(const date_type& rhs) const
107     {
108       return days_ == rhs.days_;
109     }
110     //! check to see if date is a special value
is_special() const111     BOOST_CONSTEXPR bool is_special()const
112     {
113       return(is_not_a_date() || is_infinity());
114     }
115     //! check to see if date is not a value
is_not_a_date() const116     BOOST_CONSTEXPR bool is_not_a_date()  const
117     {
118       return traits_type::is_not_a_number(days_);
119     }
120     //! check to see if date is one of the infinity values
is_infinity() const121     BOOST_CONSTEXPR bool is_infinity()  const
122     {
123       return traits_type::is_inf(days_);
124     }
125     //! check to see if date is greater than all possible dates
is_pos_infinity() const126     BOOST_CONSTEXPR bool is_pos_infinity()  const
127     {
128       return traits_type::is_pos_inf(days_);
129     }
130     //! check to see if date is greater than all possible dates
is_neg_infinity() const131     BOOST_CONSTEXPR bool is_neg_infinity()  const
132     {
133       return traits_type::is_neg_inf(days_);
134     }
135     //! return as a special value or a not_special if a normal date
as_special() const136     BOOST_CXX14_CONSTEXPR special_values as_special()  const
137     {
138       return traits_type::to_special(days_);
139     }
operator -(const date_type & d) const140     BOOST_CXX14_CONSTEXPR duration_type operator-(const date_type& d) const
141     {
142       if (!this->is_special() && !d.is_special())
143       {
144         // The duration underlying type may be wider than the date underlying type.
145         // Thus we calculate the difference in terms of two durations from some common fixed base date.
146         typedef typename duration_type::duration_rep_type duration_rep_type;
147         return duration_type(static_cast< duration_rep_type >(days_) - static_cast< duration_rep_type >(d.days_));
148       }
149       else
150       {
151         // In this case the difference will be a special value, too
152         date_rep_type val = date_rep_type(days_) - date_rep_type(d.days_);
153         return duration_type(val.as_special());
154       }
155     }
156 
operator -(const duration_type & dd) const157     BOOST_CXX14_CONSTEXPR date_type operator-(const duration_type& dd) const
158     {
159       if(dd.is_special())
160       {
161         return date_type(date_rep_type(days_) - dd.get_rep());
162       }
163       return date_type(date_rep_type(days_) - static_cast<date_int_type>(dd.days()));
164     }
operator -=(const duration_type & dd)165     BOOST_CXX14_CONSTEXPR date_type operator-=(const duration_type& dd)
166     {
167       *this = *this - dd;
168       return date_type(days_);
169     }
day_count() const170     BOOST_CONSTEXPR date_rep_type day_count() const
171     {
172       return days_;
173     }
174     //allow internal access from operators
operator +(const duration_type & dd) const175     BOOST_CXX14_CONSTEXPR date_type operator+(const duration_type& dd) const
176     {
177       if(dd.is_special())
178       {
179         return date_type(date_rep_type(days_) + dd.get_rep());
180       }
181       return date_type(date_rep_type(days_) + static_cast<date_int_type>(dd.days()));
182     }
operator +=(const duration_type & dd)183     BOOST_CXX14_CONSTEXPR date_type operator+=(const duration_type& dd)
184     {
185       *this = *this + dd;
186       return date_type(days_);
187     }
188 
189     //see reference
190   protected:
191     /*! This is a private constructor which allows for the creation of new
192       dates.  It is not exposed to users since that would require class
193       users to understand the inner workings of the date class.
194     */
date(date_int_type days)195     BOOST_CONSTEXPR explicit date(date_int_type days) : days_(days) {}
date(date_rep_type days)196     BOOST_CXX14_CONSTEXPR explicit date(date_rep_type days) : days_(days.as_number()) {}
197     date_int_type days_;
198 
199   };
200 
201 
202 
203 
204 } } // namespace date_time
205 
206 
207 
208 
209 #endif
210