Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/date_time/period.hpp @ 30

Last change on this file since 30 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 10.2 KB
Line 
1#ifndef DATE_TIME_PERIOD_HPP___
2#define DATE_TIME_PERIOD_HPP___
3
4/*    Copyright (c) 2002,2003 CrystalClear Software, Inc.
5 *
6 * Distributed under the Boost Software License, Version 1.0.
7 *     (See accompanying file LICENSE_1_0.txt or copy at
8 *           http://www.boost.org/LICENSE_1_0.txt)
9 *
10 *
11 * Author: Jeff Garland, Bart Garst
12 * $Date: 2006/07/17 03:56:05 $
13 */
14
15/*! \file period.hpp
16  This file contain the implementation of the period abstraction. This is
17  basically the same idea as a range.  Although this class is intended for
18  use in the time library, it is pretty close to general enough for other
19  numeric uses.
20
21*/
22
23#include "boost/operators.hpp"
24
25
26namespace boost {
27namespace date_time {
28  //!Provides generalized period type useful in date-time systems
29  /*!This template uses a class to represent a time point within the period
30    and another class to represent a duration.  As a result, this class is
31    not appropriate for use when the number and duration representation
32    are the same (eg: in the regular number domain).
33   
34    A period can be specified by providing either the begining point and
35    a duration or the begining point and the end point( end is NOT part
36    of the period but 1 unit past it. A period will be "invalid" if either
37    end_point <= begin_point or the given duration is <= 0. Any valid period
38    will return false for is_null().
39   
40    Zero length periods are also considered invalid. Zero length periods are
41    periods where the begining and end points are the same, or, the given
42    duration is zero. For a zero length period, the last point will be one
43    unit less than the begining point.
44
45    In the case that the begin and last are the same, the period has a
46    length of one unit.
47   
48    The best way to handle periods is usually to provide a begining point and
49    a duration.  So, day1 + 7 days is a week period which includes all of the
50    first day and 6 more days (eg: Sun to Sat).
51
52   */
53  template<class point_rep, class duration_rep>
54  class period : private
55      boost::less_than_comparable<period<point_rep, duration_rep> 
56    , boost::equality_comparable< period<point_rep, duration_rep> 
57    > >
58  {
59  public:
60    typedef point_rep point_type;
61    typedef duration_rep duration_type;
62
63    period(point_rep first_point, point_rep end_point);
64    period(point_rep first_point, duration_rep len);
65    point_rep begin() const;
66    point_rep end() const;
67    point_rep last() const;
68    duration_rep length() const;
69    bool is_null() const;
70    bool operator==(const period& rhs) const;
71    bool operator<(const period& rhs) const;
72    void shift(const duration_rep& d);
73    bool contains(const point_rep& point) const;
74    bool contains(const period& other) const;
75    bool intersects(const period& other) const;
76    bool is_adjacent(const period& other) const;
77    bool is_before(const point_rep& point) const;
78    bool is_after(const point_rep& point) const;
79    period intersection(const period& other) const;
80    period merge(const period& other) const;
81    period span(const period& other) const;
82  private:
83    point_rep begin_;
84    point_rep last_;
85  };
86
87  //! create a period from begin to last eg: [begin,end)
88  /*! If end <= begin then the period will be invalid
89   */
90  template<class point_rep, class duration_rep>
91  inline
92  period<point_rep,duration_rep>::period(point_rep first_point, 
93                                         point_rep end_point) : 
94    begin_(first_point), 
95    last_(end_point - duration_rep::unit())
96  {}
97
98  //! create a period as [begin, begin+len)
99  /*! If len is <= 0 then the period will be invalid
100   */
101  template<class point_rep, class duration_rep>
102  inline
103  period<point_rep,duration_rep>::period(point_rep first_point, duration_rep len) :
104    begin_(first_point), 
105    last_(first_point + len-duration_rep::unit())
106  { }
107
108
109  //! Return the first element in the period
110  template<class point_rep, class duration_rep>
111  inline
112  point_rep period<point_rep,duration_rep>::begin() const 
113  {
114    return begin_;
115  }
116
117  //! Return one past the last element
118  template<class point_rep, class duration_rep>
119  inline
120  point_rep period<point_rep,duration_rep>::end() const 
121  {
122    return last_ + duration_rep::unit();
123  }
124
125  //! Return the last item in the period
126  template<class point_rep, class duration_rep>
127  inline
128  point_rep period<point_rep,duration_rep>::last() const 
129  {
130    return last_;
131  }
132
133  //! True if period is ill formed (length is zero or less)
134  template<class point_rep, class duration_rep>
135  inline
136  bool period<point_rep,duration_rep>::is_null() const 
137  {
138    return end() <= begin_;
139  }
140
141  //! Return the length of the period
142  template<class point_rep, class duration_rep>
143  inline
144  duration_rep period<point_rep,duration_rep>::length() const
145  {
146    if(last_ < begin_){ // invalid period
147      return last_+duration_rep::unit() - begin_;
148    }
149    else{
150      return end() - begin_; // normal case
151    }
152  }
153
154  //! Equality operator
155  template<class point_rep, class duration_rep>
156  inline
157  bool period<point_rep,duration_rep>::operator==(const period& rhs) const 
158  {
159    return  ((begin_ == rhs.begin_) && 
160             (last_ == rhs.last_));
161  }
162
163  //! Strict as defined by rhs.last <= lhs.last
164  template<class point_rep, class duration_rep>
165  inline
166  bool period<point_rep,duration_rep>::operator<(const period& rhs) const 
167  {
168    return (last_ < rhs.begin_);
169  } 
170
171
172  //! Shift the start and end by the specified amount
173  template<class point_rep, class duration_rep>
174  inline
175  void period<point_rep,duration_rep>::shift(const duration_rep& d)
176  {
177    begin_ = begin_ + d;
178    last_  = last_  + d;
179  }
180
181  //! True if the point is inside the period, zero length periods contain no points
182  template<class point_rep, class duration_rep>
183  inline
184  bool period<point_rep,duration_rep>::contains(const point_rep& point) const 
185  {
186    return ((point >= begin_) &&
187            (point <= last_));
188  }
189
190
191  //! True if this period fully contains (or equals) the other period
192  template<class point_rep, class duration_rep>
193  inline
194  bool period<point_rep,duration_rep>::contains(const period<point_rep,duration_rep>& other) const
195  {
196    return ((begin_ <= other.begin_) && (last_ >= other.last_));
197  }
198
199
200  //! True if periods are next to each other without a gap.
201  /* In the example below, p1 and p2 are adjacent, but p3 is not adjacent
202   * with either of p1 or p2.
203   *@code
204   *   [-p1-)
205   *        [-p2-)
206   *          [-p3-)
207   *@endcode
208   */
209  template<class point_rep, class duration_rep>
210  inline
211  bool 
212  period<point_rep,duration_rep>::is_adjacent(const period<point_rep,duration_rep>& other) const 
213  {
214    return (other.begin() == end() ||
215            begin_ == other.end());
216  }
217
218
219  //! True if all of the period is prior or t < start
220  /* In the example below only point 1 would evaluate to true.
221   *@code
222   *     [---------])
223   * ^   ^    ^     ^   ^
224   * 1   2    3     4   5
225   *
226   *@endcode
227   */
228  template<class point_rep, class duration_rep>
229  inline
230  bool 
231  period<point_rep,duration_rep>::is_after(const point_rep& t) const 
232  { 
233    if (is_null()) 
234    {
235      return false; //null period isn't after
236    }
237   
238    return t < begin_;
239  }
240
241  //! True if all of the period is prior to the passed point or end <= t
242  /* In the example below points 4 and 5 return true.
243   *@code
244   *     [---------])
245   * ^   ^    ^     ^   ^
246   * 1   2    3     4   5
247   *
248   *@endcode
249   */
250  template<class point_rep, class duration_rep>
251  inline
252  bool 
253  period<point_rep,duration_rep>::is_before(const point_rep& t) const 
254  { 
255    if (is_null()) 
256    {
257      return false;  //null period isn't before anything
258    }
259   
260    return last_ < t;
261  }
262
263
264  //! True if the periods overlap in any way
265  /* In the example below p1 intersects with p2, p4, and p6.
266   *@code
267   *       [---p1---)
268   *             [---p2---)
269   *                [---p3---)
270   *  [---p4---)
271   * [-p5-)
272   *         [-p6-)
273   *@endcode
274   */
275  template<class point_rep, class duration_rep>
276  inline
277  bool period<point_rep,duration_rep>::intersects(const period<point_rep,duration_rep>& other) const 
278  { 
279    return ( contains(other.begin_) ||
280             other.contains(begin_) ||
281             ((other.begin_ < begin_) && (other.last_ >= begin_)));
282  }
283
284  //! Returns the period of intersection or invalid range no intersection
285  template<class point_rep, class duration_rep>
286  inline
287  period<point_rep,duration_rep>
288  period<point_rep,duration_rep>::intersection(const period<point_rep,duration_rep>& other) const 
289  {
290    if (begin_ > other.begin_) {
291      if (last_ <= other.last_) { //case2
292        return *this; 
293      }
294      //case 1
295      return period<point_rep,duration_rep>(begin_, other.end());
296    }
297    else {
298      if (last_ <= other.last_) { //case3
299        return period<point_rep,duration_rep>(other.begin_, this->end());
300      }
301      //case4
302      return other;
303    }
304    //unreachable
305  }
306
307  //! Returns the union of intersecting periods -- or null period
308  /*!
309   */
310  template<class point_rep, class duration_rep>
311  inline
312  period<point_rep,duration_rep>
313  period<point_rep,duration_rep>::merge(const period<point_rep,duration_rep>& other) const 
314  {
315    if (this->intersects(other)) {     
316      if (begin_ < other.begin_) {
317        return period<point_rep,duration_rep>(begin_, last_ > other.last_ ? this->end() : other.end());
318      }
319     
320      return period<point_rep,duration_rep>(other.begin_, last_ > other.last_ ? this->end() : other.end());
321     
322    }
323    return period<point_rep,duration_rep>(begin_,begin_); // no intersect return null
324  }
325
326  //! Combine two periods with earliest start and latest end.
327  /*! Combines two periods and any gap between them such that
328   *  start = minimum(p1.start, p2.start)
329   *  end   = maximum(p1.end  , p2.end)
330   *@code
331   *        [---p1---)
332   *                       [---p2---)
333   * result:
334   *        [-----------p3----------)
335   *@endcode
336   */
337  template<class point_rep, class duration_rep>
338  inline
339  period<point_rep,duration_rep>
340  period<point_rep,duration_rep>::span(const period<point_rep,duration_rep>& other) const 
341  {
342    point_rep start((begin_ < other.begin_) ? begin() : other.begin());
343    point_rep newend((last_  < other.last_)  ? other.end() : this->end());
344    return period<point_rep,duration_rep>(start, newend);
345  }
346
347
348} } //namespace date_time
349
350
351
352#endif
Note: See TracBrowser for help on using the repository browser.