Chris@16
|
1 #ifndef DATE_TIME_TIME_DURATION_HPP___
|
Chris@16
|
2 #define DATE_TIME_TIME_DURATION_HPP___
|
Chris@16
|
3
|
Chris@16
|
4 /* Copyright (c) 2002,2003 CrystalClear Software, Inc.
|
Chris@16
|
5 * Use, modification and distribution is subject to the
|
Chris@16
|
6 * Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
7 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 * Author: Jeff Garland, Bart Garst
|
Chris@101
|
9 * $Date$
|
Chris@16
|
10 */
|
Chris@16
|
11
|
Chris@16
|
12 #include <boost/cstdint.hpp>
|
Chris@16
|
13 #include <boost/operators.hpp>
|
Chris@16
|
14 #include <boost/static_assert.hpp>
|
Chris@16
|
15 #include <boost/date_time/time_defs.hpp>
|
Chris@16
|
16 #include <boost/date_time/special_defs.hpp>
|
Chris@16
|
17 #include <boost/date_time/compiler_config.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 namespace boost {
|
Chris@16
|
20 namespace date_time {
|
Chris@16
|
21
|
Chris@16
|
22
|
Chris@16
|
23 //! Represents some amount of elapsed time measure to a given resolution
|
Chris@16
|
24 /*! This class represents a standard set of capabilities for all
|
Chris@16
|
25 counted time durations. Time duration implementations should derive
|
Chris@16
|
26 from this class passing their type as the first template parameter.
|
Chris@16
|
27 This design allows the subclass duration types to provide custom
|
Chris@16
|
28 construction policies or other custom features not provided here.
|
Chris@16
|
29
|
Chris@16
|
30 @param T The subclass type
|
Chris@16
|
31 @param rep_type The time resolution traits for this duration type.
|
Chris@16
|
32 */
|
Chris@16
|
33 template<class T, typename rep_type>
|
Chris@16
|
34 class time_duration : private
|
Chris@16
|
35 boost::less_than_comparable<T
|
Chris@16
|
36 , boost::equality_comparable<T
|
Chris@16
|
37 > >
|
Chris@16
|
38 /* dividable, addable, and subtractable operator templates
|
Chris@16
|
39 * won't work with this class (MSVC++ 6.0). return type
|
Chris@16
|
40 * from '+=' is different than expected return type
|
Chris@16
|
41 * from '+'. multipliable probably wont work
|
Chris@16
|
42 * either (haven't tried) */
|
Chris@16
|
43 {
|
Chris@16
|
44 public:
|
Chris@101
|
45 // A tag for type categorization. Can be used to detect Boost.DateTime duration types in generic code.
|
Chris@101
|
46 typedef void _is_boost_date_time_duration;
|
Chris@16
|
47 typedef T duration_type; //the subclass
|
Chris@16
|
48 typedef rep_type traits_type;
|
Chris@16
|
49 typedef typename rep_type::day_type day_type;
|
Chris@16
|
50 typedef typename rep_type::hour_type hour_type;
|
Chris@16
|
51 typedef typename rep_type::min_type min_type;
|
Chris@16
|
52 typedef typename rep_type::sec_type sec_type;
|
Chris@16
|
53 typedef typename rep_type::fractional_seconds_type fractional_seconds_type;
|
Chris@16
|
54 typedef typename rep_type::tick_type tick_type;
|
Chris@16
|
55 typedef typename rep_type::impl_type impl_type;
|
Chris@16
|
56
|
Chris@16
|
57 time_duration() : ticks_(0) {}
|
Chris@16
|
58 time_duration(hour_type hours_in,
|
Chris@16
|
59 min_type minutes_in,
|
Chris@16
|
60 sec_type seconds_in=0,
|
Chris@16
|
61 fractional_seconds_type frac_sec_in = 0) :
|
Chris@16
|
62 ticks_(rep_type::to_tick_count(hours_in,minutes_in,seconds_in,frac_sec_in))
|
Chris@16
|
63 {}
|
Chris@16
|
64 // copy constructor required for dividable<>
|
Chris@16
|
65 //! Construct from another time_duration (Copy constructor)
|
Chris@16
|
66 time_duration(const time_duration<T, rep_type>& other)
|
Chris@16
|
67 : ticks_(other.ticks_)
|
Chris@16
|
68 {}
|
Chris@16
|
69 //! Construct from special_values
|
Chris@16
|
70 time_duration(special_values sv) : ticks_(impl_type::from_special(sv))
|
Chris@16
|
71 {}
|
Chris@16
|
72 //! Returns smallest representable duration
|
Chris@16
|
73 static duration_type unit()
|
Chris@16
|
74 {
|
Chris@16
|
75 return duration_type(0,0,0,1);
|
Chris@16
|
76 }
|
Chris@16
|
77 //! Return the number of ticks in a second
|
Chris@16
|
78 static tick_type ticks_per_second()
|
Chris@16
|
79 {
|
Chris@16
|
80 return rep_type::res_adjust();
|
Chris@16
|
81 }
|
Chris@16
|
82 //! Provide the resolution of this duration type
|
Chris@16
|
83 static time_resolutions resolution()
|
Chris@16
|
84 {
|
Chris@16
|
85 return rep_type::resolution();
|
Chris@16
|
86 }
|
Chris@16
|
87 //! Returns number of hours in the duration
|
Chris@16
|
88 hour_type hours() const
|
Chris@16
|
89 {
|
Chris@16
|
90 return static_cast<hour_type>(ticks() / (3600*ticks_per_second()));
|
Chris@16
|
91 }
|
Chris@16
|
92 //! Returns normalized number of minutes
|
Chris@16
|
93 min_type minutes() const
|
Chris@16
|
94 {
|
Chris@16
|
95 return static_cast<min_type>((ticks() / (60*ticks_per_second())) % 60);
|
Chris@16
|
96 }
|
Chris@16
|
97 //! Returns normalized number of seconds (0..60)
|
Chris@16
|
98 sec_type seconds() const
|
Chris@16
|
99 {
|
Chris@16
|
100 return static_cast<sec_type>((ticks()/ticks_per_second()) % 60);
|
Chris@16
|
101 }
|
Chris@16
|
102 //! Returns total number of seconds truncating any fractional seconds
|
Chris@16
|
103 sec_type total_seconds() const
|
Chris@16
|
104 {
|
Chris@16
|
105 return static_cast<sec_type>(ticks() / ticks_per_second());
|
Chris@16
|
106 }
|
Chris@16
|
107 //! Returns total number of milliseconds truncating any fractional seconds
|
Chris@16
|
108 tick_type total_milliseconds() const
|
Chris@16
|
109 {
|
Chris@16
|
110 if (ticks_per_second() < 1000) {
|
Chris@16
|
111 return ticks() * (static_cast<tick_type>(1000) / ticks_per_second());
|
Chris@16
|
112 }
|
Chris@16
|
113 return ticks() / (ticks_per_second() / static_cast<tick_type>(1000)) ;
|
Chris@16
|
114 }
|
Chris@16
|
115 //! Returns total number of nanoseconds truncating any sub millisecond values
|
Chris@16
|
116 tick_type total_nanoseconds() const
|
Chris@16
|
117 {
|
Chris@16
|
118 if (ticks_per_second() < 1000000000) {
|
Chris@16
|
119 return ticks() * (static_cast<tick_type>(1000000000) / ticks_per_second());
|
Chris@16
|
120 }
|
Chris@16
|
121 return ticks() / (ticks_per_second() / static_cast<tick_type>(1000000000)) ;
|
Chris@16
|
122 }
|
Chris@16
|
123 //! Returns total number of microseconds truncating any sub microsecond values
|
Chris@16
|
124 tick_type total_microseconds() const
|
Chris@16
|
125 {
|
Chris@16
|
126 if (ticks_per_second() < 1000000) {
|
Chris@16
|
127 return ticks() * (static_cast<tick_type>(1000000) / ticks_per_second());
|
Chris@16
|
128 }
|
Chris@16
|
129 return ticks() / (ticks_per_second() / static_cast<tick_type>(1000000)) ;
|
Chris@16
|
130 }
|
Chris@16
|
131 //! Returns count of fractional seconds at given resolution
|
Chris@16
|
132 fractional_seconds_type fractional_seconds() const
|
Chris@16
|
133 {
|
Chris@16
|
134 return (ticks() % ticks_per_second());
|
Chris@16
|
135 }
|
Chris@16
|
136 //! Returns number of possible digits in fractional seconds
|
Chris@16
|
137 static unsigned short num_fractional_digits()
|
Chris@16
|
138 {
|
Chris@16
|
139 return rep_type::num_fractional_digits();
|
Chris@16
|
140 }
|
Chris@16
|
141 duration_type invert_sign() const
|
Chris@16
|
142 {
|
Chris@16
|
143 return duration_type(ticks_ * (-1));
|
Chris@16
|
144 }
|
Chris@16
|
145 bool is_negative() const
|
Chris@16
|
146 {
|
Chris@16
|
147 return ticks_ < 0;
|
Chris@16
|
148 }
|
Chris@16
|
149 bool operator<(const time_duration& rhs) const
|
Chris@16
|
150 {
|
Chris@16
|
151 return ticks_ < rhs.ticks_;
|
Chris@16
|
152 }
|
Chris@16
|
153 bool operator==(const time_duration& rhs) const
|
Chris@16
|
154 {
|
Chris@16
|
155 return ticks_ == rhs.ticks_;
|
Chris@16
|
156 }
|
Chris@16
|
157 //! unary- Allows for time_duration td = -td1
|
Chris@16
|
158 duration_type operator-()const
|
Chris@16
|
159 {
|
Chris@16
|
160 return duration_type(ticks_ * (-1));
|
Chris@16
|
161 }
|
Chris@16
|
162 duration_type operator-(const duration_type& d) const
|
Chris@16
|
163 {
|
Chris@16
|
164 return duration_type(ticks_ - d.ticks_);
|
Chris@16
|
165 }
|
Chris@16
|
166 duration_type operator+(const duration_type& d) const
|
Chris@16
|
167 {
|
Chris@16
|
168 return duration_type(ticks_ + d.ticks_);
|
Chris@16
|
169 }
|
Chris@16
|
170 duration_type operator/(int divisor) const
|
Chris@16
|
171 {
|
Chris@16
|
172 return duration_type(ticks_ / divisor);
|
Chris@16
|
173 }
|
Chris@16
|
174 duration_type operator-=(const duration_type& d)
|
Chris@16
|
175 {
|
Chris@16
|
176 ticks_ = ticks_ - d.ticks_;
|
Chris@16
|
177 return duration_type(ticks_);
|
Chris@16
|
178 }
|
Chris@16
|
179 duration_type operator+=(const duration_type& d)
|
Chris@16
|
180 {
|
Chris@16
|
181 ticks_ = ticks_ + d.ticks_;
|
Chris@16
|
182 return duration_type(ticks_);
|
Chris@16
|
183 }
|
Chris@16
|
184 //! Division operations on a duration with an integer.
|
Chris@16
|
185 duration_type operator/=(int divisor)
|
Chris@16
|
186 {
|
Chris@16
|
187 ticks_ = ticks_ / divisor;
|
Chris@16
|
188 return duration_type(ticks_);
|
Chris@16
|
189 }
|
Chris@16
|
190 //! Multiplication operations an a duration with an integer
|
Chris@16
|
191 duration_type operator*(int rhs) const
|
Chris@16
|
192 {
|
Chris@16
|
193 return duration_type(ticks_ * rhs);
|
Chris@16
|
194 }
|
Chris@16
|
195 duration_type operator*=(int divisor)
|
Chris@16
|
196 {
|
Chris@16
|
197 ticks_ = ticks_ * divisor;
|
Chris@16
|
198 return duration_type(ticks_);
|
Chris@16
|
199 }
|
Chris@16
|
200 tick_type ticks() const
|
Chris@16
|
201 {
|
Chris@16
|
202 return traits_type::as_number(ticks_);
|
Chris@16
|
203 }
|
Chris@16
|
204
|
Chris@16
|
205 //! Is ticks_ a special value?
|
Chris@16
|
206 bool is_special()const
|
Chris@16
|
207 {
|
Chris@16
|
208 if(traits_type::is_adapted())
|
Chris@16
|
209 {
|
Chris@16
|
210 return ticks_.is_special();
|
Chris@16
|
211 }
|
Chris@16
|
212 else{
|
Chris@16
|
213 return false;
|
Chris@16
|
214 }
|
Chris@16
|
215 }
|
Chris@16
|
216 //! Is duration pos-infinity
|
Chris@16
|
217 bool is_pos_infinity()const
|
Chris@16
|
218 {
|
Chris@16
|
219 if(traits_type::is_adapted())
|
Chris@16
|
220 {
|
Chris@16
|
221 return ticks_.is_pos_infinity();
|
Chris@16
|
222 }
|
Chris@16
|
223 else{
|
Chris@16
|
224 return false;
|
Chris@16
|
225 }
|
Chris@16
|
226 }
|
Chris@16
|
227 //! Is duration neg-infinity
|
Chris@16
|
228 bool is_neg_infinity()const
|
Chris@16
|
229 {
|
Chris@16
|
230 if(traits_type::is_adapted())
|
Chris@16
|
231 {
|
Chris@16
|
232 return ticks_.is_neg_infinity();
|
Chris@16
|
233 }
|
Chris@16
|
234 else{
|
Chris@16
|
235 return false;
|
Chris@16
|
236 }
|
Chris@16
|
237 }
|
Chris@16
|
238 //! Is duration not-a-date-time
|
Chris@16
|
239 bool is_not_a_date_time()const
|
Chris@16
|
240 {
|
Chris@16
|
241 if(traits_type::is_adapted())
|
Chris@16
|
242 {
|
Chris@16
|
243 return ticks_.is_nan();
|
Chris@16
|
244 }
|
Chris@16
|
245 else{
|
Chris@16
|
246 return false;
|
Chris@16
|
247 }
|
Chris@16
|
248 }
|
Chris@16
|
249
|
Chris@16
|
250 //! Used for special_values output
|
Chris@16
|
251 impl_type get_rep()const
|
Chris@16
|
252 {
|
Chris@16
|
253 return ticks_;
|
Chris@16
|
254 }
|
Chris@16
|
255
|
Chris@16
|
256 protected:
|
Chris@16
|
257 explicit time_duration(impl_type in) : ticks_(in) {}
|
Chris@16
|
258 impl_type ticks_;
|
Chris@16
|
259 };
|
Chris@16
|
260
|
Chris@16
|
261
|
Chris@16
|
262
|
Chris@16
|
263 //! Template for instantiating derived adjusting durations
|
Chris@16
|
264 /* These templates are designed to work with multiples of
|
Chris@16
|
265 * 10 for frac_of_second and resoultion adjustment
|
Chris@16
|
266 */
|
Chris@16
|
267 template<class base_duration, boost::int64_t frac_of_second>
|
Chris@16
|
268 class subsecond_duration : public base_duration
|
Chris@16
|
269 {
|
Chris@16
|
270 public:
|
Chris@16
|
271 typedef typename base_duration::impl_type impl_type;
|
Chris@16
|
272 typedef typename base_duration::traits_type traits_type;
|
Chris@16
|
273
|
Chris@16
|
274 private:
|
Chris@16
|
275 // To avoid integer overflow we precompute the duration resolution conversion coefficient (ticket #3471)
|
Chris@16
|
276 BOOST_STATIC_ASSERT_MSG((traits_type::ticks_per_second >= frac_of_second ? traits_type::ticks_per_second % frac_of_second : frac_of_second % traits_type::ticks_per_second) == 0,\
|
Chris@16
|
277 "The base duration resolution must be a multiple of the subsecond duration resolution");
|
Chris@16
|
278 BOOST_STATIC_CONSTANT(boost::int64_t, adjustment_ratio = (traits_type::ticks_per_second >= frac_of_second ? traits_type::ticks_per_second / frac_of_second : frac_of_second / traits_type::ticks_per_second));
|
Chris@16
|
279
|
Chris@16
|
280 public:
|
Chris@16
|
281 explicit subsecond_duration(boost::int64_t ss) :
|
Chris@16
|
282 base_duration(impl_type(traits_type::ticks_per_second >= frac_of_second ? ss * adjustment_ratio : ss / adjustment_ratio))
|
Chris@16
|
283 {
|
Chris@16
|
284 }
|
Chris@16
|
285 };
|
Chris@16
|
286
|
Chris@16
|
287
|
Chris@16
|
288
|
Chris@16
|
289 } } //namespace date_time
|
Chris@16
|
290
|
Chris@16
|
291
|
Chris@16
|
292
|
Chris@16
|
293
|
Chris@16
|
294 #endif
|
Chris@16
|
295
|