296 lines
9.4 KiB
C++
296 lines
9.4 KiB
C++
|
#ifndef DATE_TIME_TIME_DURATION_HPP___
|
||
|
#define DATE_TIME_TIME_DURATION_HPP___
|
||
|
|
||
|
/* Copyright (c) 2002,2003 CrystalClear Software, Inc.
|
||
|
* Use, modification and distribution is subject to the
|
||
|
* Boost Software License, Version 1.0. (See accompanying
|
||
|
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||
|
* Author: Jeff Garland, Bart Garst
|
||
|
* $Date$
|
||
|
*/
|
||
|
|
||
|
#include <boost/cstdint.hpp>
|
||
|
#include <boost/operators.hpp>
|
||
|
#include <boost/static_assert.hpp>
|
||
|
#include <boost/date_time/time_defs.hpp>
|
||
|
#include <boost/date_time/special_defs.hpp>
|
||
|
#include <boost/date_time/compiler_config.hpp>
|
||
|
|
||
|
namespace boost {
|
||
|
namespace date_time {
|
||
|
|
||
|
|
||
|
//! Represents some amount of elapsed time measure to a given resolution
|
||
|
/*! This class represents a standard set of capabilities for all
|
||
|
counted time durations. Time duration implementations should derive
|
||
|
from this class passing their type as the first template parameter.
|
||
|
This design allows the subclass duration types to provide custom
|
||
|
construction policies or other custom features not provided here.
|
||
|
|
||
|
@param T The subclass type
|
||
|
@param rep_type The time resolution traits for this duration type.
|
||
|
*/
|
||
|
template<class T, typename rep_type>
|
||
|
class time_duration : private
|
||
|
boost::less_than_comparable<T
|
||
|
, boost::equality_comparable<T
|
||
|
> >
|
||
|
/* dividable, addable, and subtractable operator templates
|
||
|
* won't work with this class (MSVC++ 6.0). return type
|
||
|
* from '+=' is different than expected return type
|
||
|
* from '+'. multipliable probably wont work
|
||
|
* either (haven't tried) */
|
||
|
{
|
||
|
public:
|
||
|
// A tag for type categorization. Can be used to detect Boost.DateTime duration types in generic code.
|
||
|
typedef void _is_boost_date_time_duration;
|
||
|
typedef T duration_type; //the subclass
|
||
|
typedef rep_type traits_type;
|
||
|
typedef typename rep_type::day_type day_type;
|
||
|
typedef typename rep_type::hour_type hour_type;
|
||
|
typedef typename rep_type::min_type min_type;
|
||
|
typedef typename rep_type::sec_type sec_type;
|
||
|
typedef typename rep_type::fractional_seconds_type fractional_seconds_type;
|
||
|
typedef typename rep_type::tick_type tick_type;
|
||
|
typedef typename rep_type::impl_type impl_type;
|
||
|
|
||
|
time_duration() : ticks_(0) {}
|
||
|
time_duration(hour_type hours_in,
|
||
|
min_type minutes_in,
|
||
|
sec_type seconds_in=0,
|
||
|
fractional_seconds_type frac_sec_in = 0) :
|
||
|
ticks_(rep_type::to_tick_count(hours_in,minutes_in,seconds_in,frac_sec_in))
|
||
|
{}
|
||
|
// copy constructor required for dividable<>
|
||
|
//! Construct from another time_duration (Copy constructor)
|
||
|
time_duration(const time_duration<T, rep_type>& other)
|
||
|
: ticks_(other.ticks_)
|
||
|
{}
|
||
|
//! Construct from special_values
|
||
|
time_duration(special_values sv) : ticks_(impl_type::from_special(sv))
|
||
|
{}
|
||
|
//! Returns smallest representable duration
|
||
|
static duration_type unit()
|
||
|
{
|
||
|
return duration_type(0,0,0,1);
|
||
|
}
|
||
|
//! Return the number of ticks in a second
|
||
|
static tick_type ticks_per_second()
|
||
|
{
|
||
|
return rep_type::res_adjust();
|
||
|
}
|
||
|
//! Provide the resolution of this duration type
|
||
|
static time_resolutions resolution()
|
||
|
{
|
||
|
return rep_type::resolution();
|
||
|
}
|
||
|
//! Returns number of hours in the duration
|
||
|
hour_type hours() const
|
||
|
{
|
||
|
return static_cast<hour_type>(ticks() / (3600*ticks_per_second()));
|
||
|
}
|
||
|
//! Returns normalized number of minutes
|
||
|
min_type minutes() const
|
||
|
{
|
||
|
return static_cast<min_type>((ticks() / (60*ticks_per_second())) % 60);
|
||
|
}
|
||
|
//! Returns normalized number of seconds (0..60)
|
||
|
sec_type seconds() const
|
||
|
{
|
||
|
return static_cast<sec_type>((ticks()/ticks_per_second()) % 60);
|
||
|
}
|
||
|
//! Returns total number of seconds truncating any fractional seconds
|
||
|
sec_type total_seconds() const
|
||
|
{
|
||
|
return static_cast<sec_type>(ticks() / ticks_per_second());
|
||
|
}
|
||
|
//! Returns total number of milliseconds truncating any fractional seconds
|
||
|
tick_type total_milliseconds() const
|
||
|
{
|
||
|
if (ticks_per_second() < 1000) {
|
||
|
return ticks() * (static_cast<tick_type>(1000) / ticks_per_second());
|
||
|
}
|
||
|
return ticks() / (ticks_per_second() / static_cast<tick_type>(1000)) ;
|
||
|
}
|
||
|
//! Returns total number of nanoseconds truncating any sub millisecond values
|
||
|
tick_type total_nanoseconds() const
|
||
|
{
|
||
|
if (ticks_per_second() < 1000000000) {
|
||
|
return ticks() * (static_cast<tick_type>(1000000000) / ticks_per_second());
|
||
|
}
|
||
|
return ticks() / (ticks_per_second() / static_cast<tick_type>(1000000000)) ;
|
||
|
}
|
||
|
//! Returns total number of microseconds truncating any sub microsecond values
|
||
|
tick_type total_microseconds() const
|
||
|
{
|
||
|
if (ticks_per_second() < 1000000) {
|
||
|
return ticks() * (static_cast<tick_type>(1000000) / ticks_per_second());
|
||
|
}
|
||
|
return ticks() / (ticks_per_second() / static_cast<tick_type>(1000000)) ;
|
||
|
}
|
||
|
//! Returns count of fractional seconds at given resolution
|
||
|
fractional_seconds_type fractional_seconds() const
|
||
|
{
|
||
|
return (ticks() % ticks_per_second());
|
||
|
}
|
||
|
//! Returns number of possible digits in fractional seconds
|
||
|
static unsigned short num_fractional_digits()
|
||
|
{
|
||
|
return rep_type::num_fractional_digits();
|
||
|
}
|
||
|
duration_type invert_sign() const
|
||
|
{
|
||
|
return duration_type(ticks_ * (-1));
|
||
|
}
|
||
|
bool is_negative() const
|
||
|
{
|
||
|
return ticks_ < 0;
|
||
|
}
|
||
|
bool operator<(const time_duration& rhs) const
|
||
|
{
|
||
|
return ticks_ < rhs.ticks_;
|
||
|
}
|
||
|
bool operator==(const time_duration& rhs) const
|
||
|
{
|
||
|
return ticks_ == rhs.ticks_;
|
||
|
}
|
||
|
//! unary- Allows for time_duration td = -td1
|
||
|
duration_type operator-()const
|
||
|
{
|
||
|
return duration_type(ticks_ * (-1));
|
||
|
}
|
||
|
duration_type operator-(const duration_type& d) const
|
||
|
{
|
||
|
return duration_type(ticks_ - d.ticks_);
|
||
|
}
|
||
|
duration_type operator+(const duration_type& d) const
|
||
|
{
|
||
|
return duration_type(ticks_ + d.ticks_);
|
||
|
}
|
||
|
duration_type operator/(int divisor) const
|
||
|
{
|
||
|
return duration_type(ticks_ / divisor);
|
||
|
}
|
||
|
duration_type operator-=(const duration_type& d)
|
||
|
{
|
||
|
ticks_ = ticks_ - d.ticks_;
|
||
|
return duration_type(ticks_);
|
||
|
}
|
||
|
duration_type operator+=(const duration_type& d)
|
||
|
{
|
||
|
ticks_ = ticks_ + d.ticks_;
|
||
|
return duration_type(ticks_);
|
||
|
}
|
||
|
//! Division operations on a duration with an integer.
|
||
|
duration_type operator/=(int divisor)
|
||
|
{
|
||
|
ticks_ = ticks_ / divisor;
|
||
|
return duration_type(ticks_);
|
||
|
}
|
||
|
//! Multiplication operations an a duration with an integer
|
||
|
duration_type operator*(int rhs) const
|
||
|
{
|
||
|
return duration_type(ticks_ * rhs);
|
||
|
}
|
||
|
duration_type operator*=(int divisor)
|
||
|
{
|
||
|
ticks_ = ticks_ * divisor;
|
||
|
return duration_type(ticks_);
|
||
|
}
|
||
|
tick_type ticks() const
|
||
|
{
|
||
|
return traits_type::as_number(ticks_);
|
||
|
}
|
||
|
|
||
|
//! Is ticks_ a special value?
|
||
|
bool is_special()const
|
||
|
{
|
||
|
if(traits_type::is_adapted())
|
||
|
{
|
||
|
return ticks_.is_special();
|
||
|
}
|
||
|
else{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
//! Is duration pos-infinity
|
||
|
bool is_pos_infinity()const
|
||
|
{
|
||
|
if(traits_type::is_adapted())
|
||
|
{
|
||
|
return ticks_.is_pos_infinity();
|
||
|
}
|
||
|
else{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
//! Is duration neg-infinity
|
||
|
bool is_neg_infinity()const
|
||
|
{
|
||
|
if(traits_type::is_adapted())
|
||
|
{
|
||
|
return ticks_.is_neg_infinity();
|
||
|
}
|
||
|
else{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
//! Is duration not-a-date-time
|
||
|
bool is_not_a_date_time()const
|
||
|
{
|
||
|
if(traits_type::is_adapted())
|
||
|
{
|
||
|
return ticks_.is_nan();
|
||
|
}
|
||
|
else{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//! Used for special_values output
|
||
|
impl_type get_rep()const
|
||
|
{
|
||
|
return ticks_;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
explicit time_duration(impl_type in) : ticks_(in) {}
|
||
|
impl_type ticks_;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
//! Template for instantiating derived adjusting durations
|
||
|
/* These templates are designed to work with multiples of
|
||
|
* 10 for frac_of_second and resoultion adjustment
|
||
|
*/
|
||
|
template<class base_duration, boost::int64_t frac_of_second>
|
||
|
class subsecond_duration : public base_duration
|
||
|
{
|
||
|
public:
|
||
|
typedef typename base_duration::impl_type impl_type;
|
||
|
typedef typename base_duration::traits_type traits_type;
|
||
|
|
||
|
private:
|
||
|
// To avoid integer overflow we precompute the duration resolution conversion coefficient (ticket #3471)
|
||
|
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,\
|
||
|
"The base duration resolution must be a multiple of the subsecond duration resolution");
|
||
|
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));
|
||
|
|
||
|
public:
|
||
|
explicit subsecond_duration(boost::int64_t ss) :
|
||
|
base_duration(impl_type(traits_type::ticks_per_second >= frac_of_second ? ss * adjustment_ratio : ss / adjustment_ratio))
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
} } //namespace date_time
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif
|
||
|
|