Wednesday, February 19, 2025

duration

Overview
duration means a fixed number of  time units. A Time unit could be a second or a millisecond or any user defined such as a day or a month. Examples, 10 milliseconds. 2 days etc.

Details
A duration represents a period of time that could be milliseconds, seconds, days etc.
common_type class
This is a helper class. When two duration objects of different types are involved, the one with the longest period is converted to common type before the operation. 
common_type is a specialization of the standard traits class common_type. It defines the most precise duration type between its two template arguments.
Syntax
template< class Rep1, class Period1, class Rep2, class Period2 >
struct common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>

Rep1,Rep2
Represents ticks or count. It should be an arithmetic type, integer or floating point.
Period1,Period2
Represents time units. It should be of type a ratio. By default, it's seconds.

Member Types
NameDescription
typeThe most precise duration common type

The default definition returns a duration type with common_type<Rep1,Rep2> as its first template argument and the greatest common divisor of Period1 and Period2 as its second template argument.
A custom count representation type can provide its own specialization of this template.

duration_values class
This is a traits class to provide the limits and zero value of the type used to represent the count in a duration object.
Syntax
template <class Rep> struct duration_values 
{
//returns a zero-length representation
  static constexpr Rep zero() { return Rep(0); }

//returns the smallest possible representation
  static constexpr Rep min() { return numeric_limits<Rep>::lowest(); }

//returns the largest possible representation
  static constexpr Rep max() { return numeric_limits<Rep>::max(); }
}

Rep
Represents ticks or count. It should be an arithmetic type, integer or floating point.

duration class
The template class duration is represented as below.
template<typename Rep, typename Period = ratio<1>>
struct duration 
{
    //represents ticks or count. It should be an arithmetic type, integer or floating point.
    using rep = Rep;
    //represents time units. It should be of type a ratio. By default, it's seconds.
    using period = Period; };

Examples
//print a duration
template<typename rep, typename rat>
ostream& operator << (ostream&os, duration<rep,rat> d)
{
    os << "[" << d.count() << ", <" << rat::num << "," << rat::den  << ">]"<< endl;
    return os;
}

    //20 seconds
    //[20, <1,1>]
    duration<int> twentySeconds(20);

    //1 millisecond
    //[1, <1,1000>]
    duration<long,ratio<1,1000>> oneMillisecond(1);

    //half a minute
    //[0.5, <60,1>]
    duration<double,ratio<60>> halfAMinute(0.5);

    //2 days
    //[2, <86400,1>]
    duration<int,ratio<60*60*24>> days{2};

    // create a duration that tracks ticks as 1/10ths of a second
    //[5, <1,10>]
    duration<int, ratio<1, 10>> tenths{ 5 };

    // hours is a convenience duration typedef 
    //[12, <3600,1>]
    hours h{12}; 


constructors
The default constructor and copy constructors are automatically defined by the define keyword. The 
following additional constructors are also available.
NameDescription
duration()Default constructor. Default defined.
Example
//0 seconds
seconds zerosecs{};
duration
(const duration& d)
Copy constructor. Default defined.
Example
    seconds zerosecs{};
    seconds again(zerosecs);
template< class Rep2, class Period2 >
constexpr duration
(const duration<Rep2, Period2>& d)
Constructs a duration by converting d to an appropriate period and tick count, as if by duration_cast<duration>(d).count().

Example
// 30Hz clock using fractional ticks
duration<float,ratio<1>> hz30(duration<double, ratio<1, 30>>(3.5));
template< class Rep2 >
constexpr explicit duration
(const Rep2& r)
Constructs an object that represents a time interval of r clock ticks using a default period of std::ratio<1>.
To avoid round-off of tick counts, it's an error to construct a duration object from a representation type Rep2 that can be treated as a floating-point type when duration::rep cannot be treated as a floating-point type.
Example
    //one and half seconds
    duration<double> d(duration<float>(1.5));

methods
The following methods are also supported.
Namedescription
count()Returns ticks of the duration
Example
//10 seconds
auto d{10s};
//prints 10    
cout << d.count();
duration& operator=( const duration &other )Alters the duration to be the same as other without changing the period. Note that assignment from lower period to higher is not allowed.
Example
//20 seconds
auto ds{20s};
//2 minutes
auto dm{2min};
//4 hours
auto dh{4h};
//120 seconds
ds=dm;
cout << ds.count() << " " << dh.count() << endl;

//error
//dh = dm;
duration::zero()Returns Zero duration of seconds. Internally calls duration_values::zero().
Example:
//0
auto d{seconds::zero().count()};
duration::max()Returns Maximum duration of seconds. Internally calls duration_values::max().
Example:
//9223372036854775808
auto d{seconds::max().count()};
duration::min()Returns Minimum duration of seconds. Internally calls duration_values::min().
Example:
//-9223372036854775808
auto d{seconds::min().count()};
  1. duration operator+()
  2. duration operator-()
  3. duration& operator++()
  4. duration operator++(int)
  5. duration& operator--()
  6. duration  operator--(int)
  7. duration& operator+=(const duration& rhs)
  8. duration& operator-= (const duration& rhs)
  9. duration& operator*= (const rep& r)
  10. duration& operator/= (const rep& r)
  11. duration& operator%= (const rep& r)
  12. duration& operator%= (const duration& rhs)
  1. unary + of ticks
  2. unary - of ticks
  3. increment of ticks
  4. post increment of ticks
  5. decrement of ticks
  6. post decrement of ticks
  7. compound addition using  another duration
  8. compound subtraction using  another duration
  9. compound multiplication using  another duration
  10. compound division using  another duration
  11. modulus using ticks
  12. modulus using  another duration
Example
seconds secs{1}, secs2{-2};

//1
//secs:60s
secs= +1min;

//2
//secs:2
secs = -secs2;
    
//3
//secs:3s
//secs2:3s
secs2=++secs;
    
//4
//secs:4s
//secs2:3s
secs2=secs++;

//5
//secs:3s
//secs2:3s
secs2=--secs;
    
//6
//secs:2s
//secs2:3s
secs2=secs--;

//7
//secs:3602;
secs += 1h;

//8
//secs:2;
secs -= 1h;

//9
//secs:10;
secs *= 5;

//10
//secs:3;
secs /= 3;

//11
//secs:1;
secs %= 2;

//12
//secs:1;
secs %= 10s;

arithmetic operation methods
These are implemented as non member methods.
The following arithmetic operations are supported. When two duration objects of different types are involved, the one with the longest period  is converted to common type before the operation.
The Rep type and Period can be different for rhs and lhs. However storing the result of an arithmetic operation of higher period and lower period into higher period is not allowed. 
For example, secs += millisecs.

OperationDescription
addition
lhs+rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<duration<Rep1,Period1>,duration<Rep2,Period2>>::type  
operator+ (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Converts the two durations to their common type and creates a duration whose tick count is the sum of the tick counts after conversion and returns it.
Example
    //prints [123, <60,1>]
    cout << 2h + 3min << endl;
subtraction
lhs-rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<duration<Rep1,Period1>,duration<Rep2,Period2>>::type  
operator- (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Converts the two durations to their common type and creates a duration whose tick count is the rhs number of ticks subtracted from the lhs number of ticks after conversion  and returns it.
Example
    auto d2 = 2min - 3s;
    //prints [123, <60,1>]
    cout << d2 << endl;
multiplication
d*s
s*d


1. template <class Rep1, class Period, class Rep2>
constexpr duration<typename common_type<Rep1,Rep2>::type, Period>  
operator* (const duration<Rep1,Period>& d, const Rep2& s)

2. template <class Rep1, class Rep2, class Period>
constexpr duration<typename common_type<Rep1,Rep2>::type, Period>  
operator* (const Rep1& s, const duration<Rep2,Period>& d)

Converts the duration d to one whose rep is the common type between Rep1 and Rep2, and multiples the number of ticks after conversion by s. These overloads participate in overload resolution only if s is convertible to typename std::common_type<Rep1, Rep2>::type.

Example
    //1
    //prints [123, <60,1>]
    cout << 2min * 3 << endl;
//2 //prints [123, <60,1>] cout << 3 * 2min << endl;
division
d/s
template <class Rep1, class Period, class Rep2>
constexpr duration<typename common_type<Rep1,Rep2>::type, Period>  
operator/ (const duration<Rep1,Period>& d, const Rep2& s)

Converts the duration d to one whose rep is the common type between Rep1 and Rep2, and divides the number of ticks after conversion by s. This overload participates in overload resolution only if s is convertible to typename std::common_type<Rep1, Rep2>::type and Rep2 is not a specialization of duration.
Example
//[4, <60,1>]
cout << 12min/3  << endl;
division
lhs/rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<Rep1,Rep2>::type  
operator/ (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Converts the two durations to their common type and divides the tick count of lhs after conversion by the tick count of rhs after conversion. Note that the return value of this operator is not a duration.
Example
//6
cout << 3h/30min  << endl;
modulus
lhs%s
template <class Rep1, class Period, class Rep2>
constexpr duration<typename common_type<Rep1,Rep2>::type, Period>  
operator% (const duration<Rep1,Period>& lhs, const Rep2& s)

Converts the duration d to one whose rep is the common type between Rep1 and Rep2, and creates a duration whose tick count is the remainder of the division of the tick count, after conversion, by s. This overload participates in overload resolution only if s is convertible to typename std::common_type<Rep1, Rep2>::type and Rep2 is not a specialization of duration.
Example
//[4, <3600,1>]
cout << 30h % 13  << endl;
modulus
lhs%rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr typename common_type<duration<Rep1,Period1>,duration<Rep2,Period2>>::type  
operator% (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Converts the two durations to their common type and creates a duration whose tick count is the remainder of the tick counts after conversion.
Example
//[9, <1,1>]
cout << 30h % 13s  << endl;
equality
lhs==rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator== (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Checks if  the number of ticks for the type common to both durations are equal.
Example
//1
cout << (1h == 3600s)  << endl;
inequality
lhs!=rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator!= (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Checks if  the number of ticks for the type common to both durations are unequal.
Example
//0
cout << (1h != 3600s)  << endl;
less
lhs < rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator< (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Checks if  the number of ticks for the type common to both durations of lhs is less than rhs.
Example
//0
cout << (1h < 3600s)  << endl;
greater
lhs > rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator> (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Checks if  the number of ticks for the type common to both durations of lhs is greater than rhs.
Example
//0
cout << (1h < 3600s)  << endl;
lessorequal
lhs <=rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>= (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Checks if  the number of ticks for the type common to both durations of lhs is less  than or equal to rhs.
Example
//1
cout << (1h <= 3600s)  << endl;
greater or equal
lhs>=rhs
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<= (const duration<Rep1,Period1>& lhs, const duration<Rep2,Period2>& rhs)

Checks if  the number of ticks for the type common to both durations of lhs is greater than or equal to rhs.
Example
//1
cout << (1h >= 3600s)  << endl;
The example 2 demonstrates duration arithmetic.

Predefined Durations
The following predefined durations are defined under std::chrono namespace. nano, micro and milli are predefined ratios.
NameDescription
nanoseconds
duration</*int64*/,nano>
Example:
//10 nanoseconds
nanoseconds d{10};
microseconds
duration</*int55*/,micro>
Example:
//10 microseconds
microseconds d{10};
milliseconds
duration</*int45*/,milli>
Example:
//10 milliseconds
milliseconds d{10};
seconds
duration</*int35*/>
Example:
//10 seconds
seconds d{10};
minutes
duration</*int35*/,ratio<60>>
Example:
//10 minutes
minutes d{10};
hours
duration</*int23*/,ratio<3600>>
Example:
//10 hours
hours d{10};

Predefined literals
The following predefined d string literals for duration are also defined.
NameDescription
nanoseconds
operator""ns
Example:
//10 nanoseconds
auto d{10ns};
microseconds
operator""us
Example:
//10 microseconds
auto d{10us};
milliseconds
operator""ms
Example:
//10 milliseconds
auto d{10ms};
seconds
operator""s
Example:
//10 seconds
auto d{10s};
minutes
operator""min
Example:
//10 minutes
auto d{10min};
hours
operator""h
Example:
//10 hours
auto d{10h};

duration_cast()
Converts the value of d into ToDuration type, taking into account differences in their periods.
template< class ToDuration, class Rep, class Period >
constexpr ToDuration duration_cast( const std::chrono::duration<Rep, Period>& d )

Examples
    seconds s (1); 
    milliseconds ms = duration_cast<chrono::milliseconds> (s);

    //[3500, <1,1000>]
    ms += 2500ms;

    //[3, <1,1>]
    s = duration_cast<seconds> (ms); 


No comments:

Post a Comment