Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:24

0001 #ifndef DATE_TIME_PERIOD_HPP___
0002 #define DATE_TIME_PERIOD_HPP___
0003 
0004 /* Copyright (c) 2002,2003 CrystalClear Software, Inc.
0005  * Use, modification and distribution is subject to the 
0006  * Boost Software License, Version 1.0. (See accompanying
0007  * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
0008  * Author: Jeff Garland, Bart Garst 
0009  * $Date$
0010  */
0011 
0012 /*! \file period.hpp
0013   This file contain the implementation of the period abstraction. This is
0014   basically the same idea as a range.  Although this class is intended for
0015   use in the time library, it is pretty close to general enough for other
0016   numeric uses.
0017 
0018 */
0019 
0020 #include <boost/operators.hpp>
0021 #include <boost/date_time/compiler_config.hpp>
0022 
0023 
0024 namespace boost {
0025 namespace date_time {
0026   //!Provides generalized period type useful in date-time systems
0027   /*!This template uses a class to represent a time point within the period
0028     and another class to represent a duration.  As a result, this class is
0029     not appropriate for use when the number and duration representation 
0030     are the same (eg: in the regular number domain).
0031     
0032     A period can be specified by providing either the begining point and 
0033     a duration or the begining point and the end point( end is NOT part 
0034     of the period but 1 unit past it. A period will be "invalid" if either
0035     end_point <= begin_point or the given duration is <= 0. Any valid period 
0036     will return false for is_null().
0037     
0038     Zero length periods are also considered invalid. Zero length periods are
0039     periods where the begining and end points are the same, or, the given 
0040     duration is zero. For a zero length period, the last point will be one 
0041     unit less than the begining point.
0042 
0043     In the case that the begin and last are the same, the period has a 
0044     length of one unit.
0045     
0046     The best way to handle periods is usually to provide a begining point and
0047     a duration.  So, day1 + 7 days is a week period which includes all of the
0048     first day and 6 more days (eg: Sun to Sat).
0049 
0050    */
0051   template<class point_rep, class duration_rep>
0052   class BOOST_SYMBOL_VISIBLE period : private
0053       boost::less_than_comparable<period<point_rep, duration_rep> 
0054     , boost::equality_comparable< period<point_rep, duration_rep> 
0055     > >
0056   {
0057   public:
0058     typedef point_rep point_type;
0059     typedef duration_rep duration_type;
0060 
0061     BOOST_CXX14_CONSTEXPR period(point_rep first_point, point_rep end_point);
0062     BOOST_CXX14_CONSTEXPR period(point_rep first_point, duration_rep len);
0063     BOOST_CXX14_CONSTEXPR point_rep begin() const;
0064     BOOST_CXX14_CONSTEXPR point_rep end() const;
0065     BOOST_CXX14_CONSTEXPR point_rep last() const;
0066     BOOST_CXX14_CONSTEXPR duration_rep length() const;
0067     BOOST_CXX14_CONSTEXPR bool is_null() const;
0068     BOOST_CXX14_CONSTEXPR bool operator==(const period& rhs) const;
0069     BOOST_CXX14_CONSTEXPR bool operator<(const period& rhs) const;
0070     BOOST_CXX14_CONSTEXPR void shift(const duration_rep& d);
0071     BOOST_CXX14_CONSTEXPR void expand(const duration_rep& d);
0072     BOOST_CXX14_CONSTEXPR bool contains(const point_rep& point) const;
0073     BOOST_CXX14_CONSTEXPR bool contains(const period& other) const;
0074     BOOST_CXX14_CONSTEXPR bool intersects(const period& other) const;
0075     BOOST_CXX14_CONSTEXPR bool is_adjacent(const period& other) const;
0076     BOOST_CXX14_CONSTEXPR bool is_before(const point_rep& point) const;
0077     BOOST_CXX14_CONSTEXPR bool is_after(const point_rep& point) const;
0078     BOOST_CXX14_CONSTEXPR period intersection(const period& other) const;
0079     BOOST_CXX14_CONSTEXPR period merge(const period& other) const;
0080     BOOST_CXX14_CONSTEXPR period span(const period& other) const;
0081   private:
0082     point_rep begin_;
0083     point_rep last_;
0084   };
0085 
0086   //! create a period from begin to last eg: [begin,end)
0087   /*! If end <= begin then the period will be invalid
0088    */
0089   template<class point_rep, class duration_rep>
0090   inline BOOST_CXX14_CONSTEXPR
0091   period<point_rep,duration_rep>::period(point_rep first_point, 
0092                                          point_rep end_point) : 
0093     begin_(first_point), 
0094     last_(end_point - duration_rep::unit())
0095   {}
0096 
0097   //! create a period as [begin, begin+len)
0098   /*! If len is <= 0 then the period will be invalid
0099    */
0100   template<class point_rep, class duration_rep>
0101   inline BOOST_CXX14_CONSTEXPR
0102   period<point_rep,duration_rep>::period(point_rep first_point, duration_rep len) :
0103     begin_(first_point), 
0104     last_(first_point + len-duration_rep::unit())
0105   { }
0106 
0107 
0108   //! Return the first element in the period
0109   template<class point_rep, class duration_rep>
0110   inline BOOST_CXX14_CONSTEXPR
0111   point_rep period<point_rep,duration_rep>::begin() const 
0112   {
0113     return begin_;
0114   }
0115 
0116   //! Return one past the last element 
0117   template<class point_rep, class duration_rep>
0118   inline BOOST_CXX14_CONSTEXPR
0119   point_rep period<point_rep,duration_rep>::end() const 
0120   {
0121     return last_ + duration_rep::unit();
0122   }
0123 
0124   //! Return the last item in the period
0125   template<class point_rep, class duration_rep>
0126   inline BOOST_CXX14_CONSTEXPR
0127   point_rep period<point_rep,duration_rep>::last() const 
0128   {
0129     return last_;
0130   }
0131 
0132   //! True if period is ill formed (length is zero or less)
0133   template<class point_rep, class duration_rep>
0134   inline BOOST_CXX14_CONSTEXPR
0135   bool period<point_rep,duration_rep>::is_null() const 
0136   {
0137     return end() <= begin_;
0138   }
0139 
0140   //! Return the length of the period
0141   template<class point_rep, class duration_rep>
0142   inline BOOST_CXX14_CONSTEXPR
0143   duration_rep period<point_rep,duration_rep>::length() const
0144   {
0145     if(last_ < begin_){ // invalid period
0146       return last_+duration_rep::unit() - begin_;
0147     }
0148     else{
0149       return end() - begin_; // normal case
0150     }
0151   }
0152 
0153   //! Equality operator
0154   template<class point_rep, class duration_rep>
0155   inline BOOST_CXX14_CONSTEXPR
0156   bool period<point_rep,duration_rep>::operator==(const period& rhs) const 
0157   {
0158     return  ((begin_ == rhs.begin_) && 
0159              (last_ == rhs.last_));
0160   }
0161 
0162   //! Strict as defined by rhs.last <= lhs.last
0163   template<class point_rep, class duration_rep>
0164   inline BOOST_CXX14_CONSTEXPR
0165   bool period<point_rep,duration_rep>::operator<(const period& rhs) const 
0166   {
0167     return (last_ < rhs.begin_);
0168   } 
0169 
0170 
0171   //! Shift the start and end by the specified amount
0172   template<class point_rep, class duration_rep>
0173   inline BOOST_CXX14_CONSTEXPR
0174   void period<point_rep,duration_rep>::shift(const duration_rep& d)
0175   {
0176     begin_ = begin_ + d;
0177     last_  = last_  + d;
0178   }
0179 
0180   /** Expands the size of the period by the duration on both ends.
0181    *
0182    *So before expand 
0183    *@code
0184    *
0185    *         [-------]
0186    * ^   ^   ^   ^   ^   ^  ^
0187    * 1   2   3   4   5   6  7
0188    * 
0189    *@endcode
0190    * After expand(2)
0191    *@code
0192    *
0193    * [----------------------]
0194    * ^   ^   ^   ^   ^   ^  ^
0195    * 1   2   3   4   5   6  7
0196    * 
0197    *@endcode
0198    */
0199   template<class point_rep, class duration_rep>
0200   inline BOOST_CXX14_CONSTEXPR
0201   void period<point_rep,duration_rep>::expand(const duration_rep& d)
0202   {
0203     begin_ = begin_ - d;
0204     last_  = last_  + d;
0205   }
0206 
0207   //! True if the point is inside the period, zero length periods contain no points
0208   template<class point_rep, class duration_rep>
0209   inline BOOST_CXX14_CONSTEXPR
0210   bool period<point_rep,duration_rep>::contains(const point_rep& point) const 
0211   {
0212     return ((point >= begin_) &&
0213             (point <= last_));
0214   }
0215 
0216 
0217   //! True if this period fully contains (or equals) the other period
0218   template<class point_rep, class duration_rep>
0219   inline BOOST_CXX14_CONSTEXPR
0220   bool period<point_rep,duration_rep>::contains(const period<point_rep,duration_rep>& other) const
0221   {
0222     return ((begin_ <= other.begin_) && (last_ >= other.last_));
0223   }
0224 
0225 
0226   //! True if periods are next to each other without a gap.
0227   /* In the example below, p1 and p2 are adjacent, but p3 is not adjacent
0228    * with either of p1 or p2.
0229    *@code
0230    *   [-p1-)
0231    *        [-p2-)
0232    *          [-p3-) 
0233    *@endcode
0234    */
0235   template<class point_rep, class duration_rep>
0236   inline BOOST_CXX14_CONSTEXPR
0237   bool period<point_rep,duration_rep>::is_adjacent(const period<point_rep,duration_rep>& other) const
0238   {
0239     return (other.begin() == end() ||
0240             begin_ == other.end());
0241   }
0242 
0243 
0244   //! True if all of the period is prior or t < start
0245   /* In the example below only point 1 would evaluate to true.
0246    *@code
0247    *     [---------])
0248    * ^   ^    ^     ^   ^
0249    * 1   2    3     4   5
0250    * 
0251    *@endcode
0252    */
0253   template<class point_rep, class duration_rep>
0254   inline BOOST_CXX14_CONSTEXPR
0255   bool period<point_rep,duration_rep>::is_after(const point_rep& t) const
0256   { 
0257     if (is_null()) 
0258     {
0259       return false; //null period isn't after
0260     }
0261     
0262     return t < begin_;
0263   }
0264 
0265   //! True if all of the period is prior to the passed point or end <= t
0266   /* In the example below points 4 and 5 return true.
0267    *@code
0268    *     [---------])
0269    * ^   ^    ^     ^   ^
0270    * 1   2    3     4   5
0271    * 
0272    *@endcode
0273    */
0274   template<class point_rep, class duration_rep>
0275   inline BOOST_CXX14_CONSTEXPR
0276   bool period<point_rep,duration_rep>::is_before(const point_rep& t) const
0277   { 
0278     if (is_null()) 
0279     {
0280       return false;  //null period isn't before anything
0281     }
0282     
0283     return last_ < t;
0284   }
0285 
0286 
0287   //! True if the periods overlap in any way
0288   /* In the example below p1 intersects with p2, p4, and p6.
0289    *@code
0290    *       [---p1---)
0291    *             [---p2---)
0292    *                [---p3---) 
0293    *  [---p4---) 
0294    * [-p5-) 
0295    *         [-p6-) 
0296    *@endcode
0297    */
0298   template<class point_rep, class duration_rep>
0299   inline BOOST_CXX14_CONSTEXPR
0300   bool period<point_rep,duration_rep>::intersects(const period<point_rep,duration_rep>& other) const
0301   { 
0302     return ( contains(other.begin_) ||
0303              other.contains(begin_) ||
0304              ((other.begin_ < begin_) && (other.last_ >= begin_)));
0305   }
0306 
0307   //! Returns the period of intersection or invalid range no intersection
0308   template<class point_rep, class duration_rep>
0309   inline BOOST_CXX14_CONSTEXPR
0310   period<point_rep,duration_rep>
0311   period<point_rep,duration_rep>::intersection(const period<point_rep,duration_rep>& other) const 
0312   {
0313     if (begin_ > other.begin_) {
0314       if (last_ <= other.last_) { //case2
0315         return *this;  
0316       }
0317       //case 1
0318       return period<point_rep,duration_rep>(begin_, other.end());
0319     }
0320     else {
0321       if (last_ <= other.last_) { //case3
0322         return period<point_rep,duration_rep>(other.begin_, this->end());
0323       }
0324       //case4
0325       return other;
0326     }
0327     //unreachable
0328   }
0329 
0330   //! Returns the union of intersecting periods -- or null period
0331   /*! 
0332    */
0333   template<class point_rep, class duration_rep>
0334   inline BOOST_CXX14_CONSTEXPR
0335   period<point_rep,duration_rep>
0336   period<point_rep,duration_rep>::merge(const period<point_rep,duration_rep>& other) const 
0337   {
0338     if (this->intersects(other)) {      
0339       if (begin_ < other.begin_) {
0340         return period<point_rep,duration_rep>(begin_, last_ > other.last_ ? this->end() : other.end());
0341       }
0342       
0343       return period<point_rep,duration_rep>(other.begin_, last_ > other.last_ ? this->end() : other.end());
0344       
0345     }
0346     return period<point_rep,duration_rep>(begin_,begin_); // no intersect return null
0347   }
0348 
0349   //! Combine two periods with earliest start and latest end.
0350   /*! Combines two periods and any gap between them such that 
0351    *  start = min(p1.start, p2.start)
0352    *  end   = max(p1.end  , p2.end)
0353    *@code
0354    *        [---p1---)
0355    *                       [---p2---)
0356    * result:
0357    *        [-----------p3----------) 
0358    *@endcode
0359    */
0360   template<class point_rep, class duration_rep>
0361   inline BOOST_CXX14_CONSTEXPR
0362   period<point_rep,duration_rep>
0363   period<point_rep,duration_rep>::span(const period<point_rep,duration_rep>& other) const 
0364   {
0365     point_rep start((begin_ < other.begin_) ? begin() : other.begin());
0366     point_rep newend((last_  < other.last_)  ? other.end() : this->end());
0367     return period<point_rep,duration_rep>(start, newend);
0368   }
0369 
0370 
0371 } } //namespace date_time
0372 
0373 
0374 
0375 #endif