// bsls_timeinterval.h -*-C++-*- #ifndef INCLUDED_BSLS_TIMEINTERVAL #define INCLUDED_BSLS_TIMEINTERVAL #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a representation of a time interval. // //@CLASSES: // bsls::TimeInterval: time interval with nanosecond resolution // //@SEE_ALSO: bdlt_time, bdlt_datetimeinterval // //@DESCRIPTION: This component provides a value-semantic type, // 'bsls::TimeInterval', that is capable of representing a signed time // interval with nanosecond resolution. // ///Representation ///-------------- // A time interval has a value that is independent of its representation. // Conceptually, a time interval may be thought of as a signed, // arbitrary-precision floating-point number denominated in seconds (or in // days, or in fortnights, if one prefers). A 'bsls::TimeInterval' represents // this value as two fields: seconds and nanoseconds. In the "canonical // representation" of a time interval, the 'seconds' field may have any 64-bit // signed integer value, with the 'nanoseconds' field limited to the range // '[ -999,999,999..999,999,999 ]', and with the additional constraint that the // two fields are either both non-negative or both non-positive. When setting // the value of a time interval via its two-field representation, any integer // value may be used in either field, with the constraint that the resulting // number of seconds be representable as a 64-bit signed integer. Similarly, // the two field values may be accessed in the canonical representation using // the 'seconds' and 'nanoseconds' methods. // // Binary arithmetic and relational operators taking two 'bsls::TimeInterval' // objects, or a 'bsls::TimeInterval' object and a 'double', are provided. A // 'double' operand, representing a real number of seconds, is first converted // to a 'bsls::TimeInterval' object before performing the operation. Under // such circumstances, the fractional part of the 'double', if any, is rounded // to the nearest whole number of nanoseconds. // ///User-Defined Literals ///--------------------- // The user-defined literal 'operator"" _h', 'operator"" _min', // 'operator"" _s', 'operator"" _ms', 'operator"" _us' and 'operator"" _ns' are // declared for the 'TimeInterval'. These suffixes can be applied to integer // literals and allow to create an object, representing the specified number of // hours, minutes, seconds, milliseconds, microseconds or nanoseconds // respectively: //.. // using namespace bsls::TimeIntervalLiterals; // // bsls::TimeInterval i0 = 10_h; // assert(36000 == i0.seconds() ); // assert(0 == i0.nanoseconds()); // // bsls::TimeInterval i1 = 10001_ms; // assert(10 == i1.seconds() ); // assert(1000000 == i1.nanoseconds()); // // bsls::TimeInterval i2 = 100_ns; // assert(0 == i2.seconds() ); // assert(100 == i2.nanoseconds()); //.. // The operators providing literals are available in the // 'BloombergLP::bsls::literals::TimeIntervalLiterals' namespace (where // 'literals' and 'TimeIntervalLiterals' are both inline namespaces). Because // of inline namespaces, there are several viable options for a using // declaration, but *we* *recommend* // 'using namespace bsls::TimeIntervalLiterals', which minimizes the scope of // the using declaration. // // Note that user defined literals can be used only if the compiler supports // the C++11 standard. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Creating and Modifying a 'bsls::TimeInterval' /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - // The following example demonstrates how to create and manipulate a // 'bsls::TimeInterval' object. // // First, we default construct a 'TimeInterval' object, 'interval': //.. // bsls::TimeInterval interval; // // assert(0 == interval.seconds()); // assert(0 == interval.nanoseconds()); //.. // Next, we set the value of 'interval' to 1 second and 10 nanoseconds (a time // interval of 1000000010 nanoseconds): //.. // interval.setInterval(1, 10); // // assert( 1 == interval.seconds()); // assert(10 == interval.nanoseconds()); //.. // Then, we add 3 seconds to 'interval': //.. // interval.addInterval(3, 0); // // assert( 4 == interval.seconds()); // assert(10 == interval.nanoseconds()); //.. // Next, we create a copy of 'interval', 'intervalPrime': //.. // bsls::TimeInterval intervalPrime(interval); // // assert(intervalPrime == interval); //.. // Finally, we assign 3.14 seconds to 'intervalPrime', and then add 2.73 // seconds more: //.. // intervalPrime = 3.14; // intervalPrime += 2.73; // // assert( 5 == intervalPrime.seconds()); // assert(870000000 == intervalPrime.nanoseconds()); //.. #include <bsls_assert.h> #include <bsls_compilerfeatures.h> #include <bsls_keyword.h> #include <bsls_libraryfeatures.h> #include <bsls_preconditions.h> #include <bsls_types.h> #if BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY #include <chrono> #include <type_traits> #endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY #include <iosfwd> #include <limits.h> // 'LLONG_MIN', 'LLONG_MAX' #ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <bsls_nativestd.h> #endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES // BDE_VERIFY pragma: push // BDE_VERIFY pragma: -FABC01 // 'add*' operations are ordered by time unit #if BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY #define BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS #endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY namespace BloombergLP { namespace bsls { #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS // ======================================= // template struct TimeInterval_IsDuration // ======================================= template <class TYPE> struct TimeInterval_IsDuration : std::false_type { // Template metafunction to determine if the specified 'TYPE' is a // 'std::chrono::duration'. }; template <class REP, class PER> struct TimeInterval_IsDuration<std::chrono::duration<REP, PER> > : std::true_type { // Template metafunction specialization for 'std::chrono::duration' types. }; // ============================= // struct TimeInterval_RepTraits // ============================= template <class REP> struct TimeInterval_RepTraits { // Trait metafunction that determines whether the specified 'REP' type is // considered a floating point type. static const bool k_IS_FLOAT = std::is_floating_point<REP>::value || std::chrono::treat_as_floating_point<REP>::value; // This compile time constant is 'true' if the 'REP' (template type // argument) is indicated to be a floating point type by the underlying // library. Otherwise, if the underlying library does not consider 'REP' // floating point anywhere (see note), 'k_IS_FLOAT' is 'false'. Note that // to cover all scenarios we need to examine *two* traits. The first one // that tells if the representation type is a floating point (arithmetic) // type or not (from '<type_traits>'), and another that tells that // representation type is considered a floating point type from the // 'std::chrono' perspective. Formally the second one just duplicates the // first one, but *in theory* either can be specialized to be true, // independently. Also note that conversions from 'std::chrono::duration' // with a floating point representation to 'bsls::TimeInterval' are *not* // supported for now. }; // ================================== // struct TimeInterval_DurationTraits // ================================== template <class REP, class PERIOD> struct TimeInterval_DurationTraits { // Trait metafunction that determines whether the // 'std::chrono::duration<REP, PERIOD>' object can be converted to // 'bsls::TimeInterval' either implicitly or explicitly. static const bool k_IS_FLOAT = TimeInterval_RepTraits<REP>::k_IS_FLOAT; // This compile time constant is 'true' if the 'REP' (template type // argument) is indicated to be a floating point type by the underlying // library. Otherwise, if the underlying library does not consider // 'REP' floating point anywhere (see 'TimeInterval_RepTraits'), // 'k_IS_FLOAT' is 'false'. static const bool k_IS_IMPLICIT = (std::nano::den % PERIOD::den == 0); // This compile time constant is 'true' if any possible value of an // 'std::chrono::duration<REP, PERIOD> object will be represented by // integer nanoseconds (fractions of nanoseconds are not required). // Otherwise this value is 'false'. static const bool k_IMPLICIT_CONVERSION_ENABLED = !k_IS_FLOAT && k_IS_IMPLICIT; // This compile time constant is 'true' if // 'std::chrono::duration<REP, PERIOD>' objects will be implicitly // converted to 'TimeInterval', and 'false' otherwise. This value is // intended to be used with 'enable_if' to enable implicitly converting // function overloads. Note that this boolean value is mutually // exclusive with 'k_EXPLICIT_CONVERION_ENABLED' as in they will never // be both 'true' for the same 'REP" and 'PERIOD', but they may be both // 'false' for floats. static const bool k_EXPLICIT_CONVERSION_ENABLED = !k_IS_FLOAT && !k_IS_IMPLICIT; // This compile time constant is 'true' if // 'std::chrono::duration<REP, PERIOD>' objects can be explicitly // converted to 'TimeInterval', and 'false' otherwise. This value is // intended to be used with 'enable_if' to enable explicitly converting // function overloads. Note that this boolean value is mutually // exclusive with 'k_IMPLICIT_CONVERION_ENABLED' as in they will never // be both 'true' for the same 'REP" and 'PERIOD', but they may be both // 'false' for floats. }; #endif // ================== // class TimeInterval // ================== class TimeInterval { // Each instance of this value-semantic type represents a time interval // with nanosecond resolution. In the "canonical representation" of a time // interval, the 'seconds' field may have any 64-bit signed integer value, // with the 'nanoseconds' field limited to the range // '[ -999,999,999..999,999,999 ]', and with the additional constraint that // the two fields are either both non-negative or both non-positive. // PRIVATE TYPES enum { k_MILLISECS_PER_SEC = 1000, // one thousand k_MICROSECS_PER_SEC = 1000000, // one million k_NANOSECS_PER_MICROSEC = 1000, // one thousand k_NANOSECS_PER_MILLISEC = 1000000, // one million k_NANOSECS_PER_SEC = 1000000000, // one billion k_SECONDS_PER_MINUTE = 60, k_SECONDS_PER_HOUR = 60 * k_SECONDS_PER_MINUTE, k_SECONDS_PER_DAY = 24 * k_SECONDS_PER_HOUR }; // DATA bsls::Types::Int64 d_seconds; // field for seconds int d_nanoseconds; // field for nanoseconds // PRIVATE CLASS METHODS BSLS_KEYWORD_CONSTEXPR static bool isSumValidInt64(bsls::Types::Int64 lhs, bsls::Types::Int64 rhs); // Return 'true' if the sum of the specified 'lhs' and 'rhs' can be // represented using a 64-bit signed integer, and 'false' otherwise. public: // CLASS METHODS BSLS_KEYWORD_CONSTEXPR static bool isValid(bsls::Types::Int64 seconds, int nanoseconds); // Return 'true' if a 'TimeInterval' object can be constructed from the // specified 'seconds' and 'nanoseconds', and 'false' otherwise. A // time interval can be constructed from 'seconds' and 'nanoseconds' if // their sum results in a time interval whose total number of seconds // can be represented with a 64-bit signed integer. #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class REP, class PERIOD> static bool isValid(const std::chrono::duration<REP, PERIOD>& duration); // Return 'true' if a 'TimeInterval' object can be constructed from the // specified 'duration', and 'false' otherwise. A time interval can be // constructed from 'duration' if duration's value converted to seconds // can be represented with a 64-bit signed integer. #endif // Aspects static int maxSupportedBdexVersion(int versionSelector); // Return the maximum valid BDEX format version, as indicated by the // specified 'versionSelector', to be passed to the 'bdexStreamOut' // method. Note that it is highly recommended that 'versionSelector' // be formatted as "YYYYMMDD", a date representation. Also note that // 'versionSelector' should be a *compile*-time-chosen value that // selects a format version supported by both externalizer and // unexternalizer. See the 'bslx' package-level documentation for more // information on BDEX streaming of value-semantic types and // containers. // CREATORS BSLS_KEYWORD_CONSTEXPR TimeInterval(); // Create a time interval having the value of 0 seconds and 0 // nanoseconds. BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval(bsls::Types::Int64 seconds, int nanoseconds); // Create a time interval having the value given by the sum of the // specified integral number of 'seconds' and 'nanoseconds'. The // behavior is undefined unless the total number of seconds in the // resulting time interval can be represented with a 64-bit signed // integer (see 'isValid'). Note that there is no restriction on the // sign or magnitude of either argument except that they must not // violate the method's preconditions. explicit TimeInterval(double seconds); // Create a time interval having the value represented by the specified // real number of 'seconds'. The fractional part of 'seconds', if any, // is rounded to the nearest whole number of nanoseconds. The // behavior is undefined unless the total number of seconds in the // resulting time interval can be represented with a 64-bit signed // integer. #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class REP_TYPE, class PERIOD_TYPE> BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval( const std::chrono::duration<REP_TYPE, PERIOD_TYPE>& duration, typename std::enable_if<TimeInterval_DurationTraits< REP_TYPE, PERIOD_TYPE>::k_IMPLICIT_CONVERSION_ENABLED, int>::type * = 0); template <class REP_TYPE, class PERIOD_TYPE> explicit BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval( const std::chrono::duration<REP_TYPE, PERIOD_TYPE>& duration, typename std::enable_if<TimeInterval_DurationTraits< REP_TYPE, PERIOD_TYPE>::k_EXPLICIT_CONVERSION_ENABLED, int>::type * = 0); // Create a time interval having the value represented by the specified // 'duration'. Only integer representations of 'duration' are // supported (i.e. 'REP_TYPE' is integer). If the 'duration' can be // represented *exactly* by an integer nanoseconds this constructor // will be implicit. Otherwise, the constructor will be explicit. The // behavior is undefined unless the 'duration' can be converted to a // valid 'TimeInterval' object, whose 'seconds' field may have any // 64-bit signed integer value and 'nanoseconds' field limited to the // range '[ -999,999,999..999,999,999 ]'. Note that the current // implementation of the lossy conversions (e.g., fractions of a // nanosecond) truncates the values towards zero, however this behavior // may change without notice in the future, so *do not* rely on this. #endif //! TimeInterval(const TimeInterval& original) = default; // Create a time interval having the value of the specified 'original' // time interval. Note that this trivial copy constructor is // generated by the compiler. //! ~TimeInterval() = default; // Destroy this time interval object. Note that this trivial // destructor is generated by the compiler. // MANIPULATORS // Operator Overloads //! TimeInterval& operator=(const TimeInterval& rhs) = default; // Assign to this time interval the value of the specified 'rhs' time // interval, and return a reference providing modifiable access to this // object. Note that this trivial assignment operation is generated by // the compiler. TimeInterval& operator=(double rhs); // Assign to this time interval the value of the specified 'rhs' real // number of seconds, and return a reference providing modifiable // access to this object. The fractional part of 'rhs', if any, is // rounded to the nearest whole number of nanoseconds. The behavior // is undefined unless 'rhs' can be converted to a valid // 'TimeInterval' object. TimeInterval& operator+=(const TimeInterval& rhs); // Add to this time interval the value of the specified 'rhs' time // interval, and return a reference providing modifiable access to // this object. The behavior is undefined unless the total number of // seconds in the resulting time interval can be represented with a // 64-bit signed integer. TimeInterval& operator+=(double rhs); // Add to this time interval the value of the specified 'rhs' real // number of seconds, and return a reference providing modifiable // access to this object. The fractional part of 'rhs', if any, is // rounded to the nearest whole number of nanoseconds before being // added to this object. The behavior is undefined unless 'rhs' can // be converted to a valid 'TimeInterval' object, and the total number // of seconds in the resulting time interval can be represented with a // 64-bit signed integer. TimeInterval& operator-=(const TimeInterval& rhs); // Subtract from this time interval the value of the specified 'rhs' // time interval, and return a reference providing modifiable access to // this object. The behavior is undefined unless // 'LLONG_MIN != rhs.seconds()', and the total number of seconds in the // resulting time interval can be represented with a 64-bit signed // integer. TimeInterval& operator-=(double rhs); // Subtract from this time interval the value of the specified 'rhs' // real number of seconds, and return a reference providing modifiable // access to this object. The fractional part of 'rhs', if any, is // rounded to the nearest whole number of nanoseconds before being // subtracted from this object. The behavior is undefined unless // 'rhs' can be converted to a valid 'TimeInterval' object whose // 'seconds' field is greater than 'LLONG_MIN', and the total number of // seconds in the resulting time interval can be represented with a // 64-bit signed integer. // Add Operations BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& addDays(bsls::Types::Int64 days); // Add to this time interval the number of seconds represented by the // specified integral number of 'days', and return a reference // providing modifiable access to this object. The behavior is // undefined unless the number of seconds in 'days', and the total // number of seconds in the resulting time interval, can both be // represented with 64-bit signed integers. Note that 'days' may be // negative. BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& addHours(bsls::Types::Int64 hours); // Add to this time interval the number of seconds represented by the // specified integral number of 'hours', and return a reference // providing modifiable access to this object. The behavior is // undefined unless the number of seconds in 'hours', and the total // number of seconds in the resulting time interval, can both be // represented with 64-bit signed integers. Note that 'hours' may be // negative. BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& addMinutes(bsls::Types::Int64 minutes); // Add to this time interval the number of seconds represented by the // specified integral number of 'minutes', and return a reference // providing modifiable access to this object. The behavior is // undefined unless the number of seconds in 'minutes', and the total // number of seconds in the resulting time interval, can both be // represented with 64-bit signed integers. Note that 'minutes' may be // negative. BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& addSeconds(bsls::Types::Int64 seconds); // Add to this time interval the specified integral number of // 'seconds', and return a reference providing modifiable access to // this object. The behavior is undefined unless the total number of // seconds in the resulting time interval can be represented with a // 64-bit signed integer. Note that 'seconds' may be negative. TimeInterval& addMilliseconds(bsls::Types::Int64 milliseconds); // Add to this time interval the specified integral number of // 'milliseconds', and return a reference providing modifiable access // to this object. The behavior is undefined unless the total number // of seconds in the resulting time interval can be represented with a // 64-bit signed integer. Note that 'milliseconds' may be negative. TimeInterval& addMicroseconds(bsls::Types::Int64 microseconds); // Add to this time interval the specified integral number of // 'microseconds', and return a reference providing modifiable access // to this object. The behavior is undefined unless the total number // of seconds in the resulting time interval can be represented with a // 64-bit signed integer. Note that 'microseconds' may be negative. TimeInterval& addNanoseconds(bsls::Types::Int64 nanoseconds); // Add to this time interval the specified integral number of // 'nanoseconds', and return a reference providing modifiable access to // this object. The behavior is undefined unless the total number of // seconds in the resulting time interval can be represented with a // 64-bit signed integer. Note that 'nanoseconds' may be negative. // Set Operations BSLS_KEYWORD_CONSTEXPR_CPP14 void setTotalDays(bsls::Types::Int64 days); // Set the overall value of this object to indicate the specified // integral number of 'days'. The behavior is undefined unless the // number of seconds in 'days' can be represented with a 64-bit signed // integer. Note that 'days' may be negative. BSLS_KEYWORD_CONSTEXPR_CPP14 void setTotalHours(bsls::Types::Int64 hours); // Set the overall value of this object to indicate the specified // integral number of 'hours'. The behavior is undefined unless the // number of seconds in 'hours' can be represented with a 64-bit signed // integer. Note that 'hours' may be negative. BSLS_KEYWORD_CONSTEXPR_CPP14 void setTotalMinutes(bsls::Types::Int64 minutes); // Set the overall value of this object to indicate the specified // integral number of 'minutes'. The behavior is undefined unless the // number of seconds in 'minutes' can be represented with a 64-bit // signed integer. Note that 'minutes' may be negative. BSLS_KEYWORD_CONSTEXPR_CPP14 void setTotalSeconds(bsls::Types::Int64 seconds); // Set the overall value of this object to indicate the specified // integral number of 'seconds'. Note that 'seconds' may be negative. BSLS_KEYWORD_CONSTEXPR_CPP14 void setTotalMilliseconds(bsls::Types::Int64 milliseconds); // Set the overall value of this object to indicate the specified // integral number of 'milliseconds'. Note that 'milliseconds' may be // negative. BSLS_KEYWORD_CONSTEXPR_CPP14 void setTotalMicroseconds(bsls::Types::Int64 microseconds); // Set the overall value of this object to indicate the specified // integral number of 'microseconds'. Note that 'microseconds' may be // negative. BSLS_KEYWORD_CONSTEXPR_CPP14 void setTotalNanoseconds(bsls::Types::Int64 nanoseconds); // Set the overall value of this object to indicate the specified // integral number of 'nanoseconds'. Note that 'nanoseconds' may be // negative. // Time-Interval-Based Manipulators TimeInterval& addInterval(bsls::Types::Int64 seconds, int nanoseconds = 0); // Add to this time interval the specified integral number of // 'seconds', and the optionally specified integral number of // 'nanoseconds'. If unspecified, 'nanoseconds' is 0. Return a // reference providing modifiable access to this object. The behavior // is undefined unless 'seconds() + seconds', and the total number of // seconds in the resulting time interval, can both be represented with // 64-bit signed integers. #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class REP_TYPE, class PERIOD_TYPE> BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& addDuration(const std::chrono::duration<REP_TYPE, PERIOD_TYPE>& duration, typename std::enable_if< TimeInterval_DurationTraits<REP_TYPE, PERIOD_TYPE>:: k_IMPLICIT_CONVERSION_ENABLED, int>::type * = 0); // Add to this time interval the specified 'duration'. Return a // reference providing modifiable access to this object. The behavior // is undefined unless the 'duration' can be converted to a valid // 'TimeInterval' object, whose 'seconds' field may have any // 64-bit signed integer value and 'nanoseconds' field limited to the // range '[ -999,999,999..999,999,999 ]'. Also the behavior is // undefined unless the total number of seconds in the resulting time // interval can be represented with 64-bit signed integer. Note that // this operation is allowed only if representation type of the // 'duration' is not a floating point type and the 'duration' itself // can be *exactly* represented by an integer nanoseconds. #endif BSLS_KEYWORD_CONSTEXPR_CPP14 void setInterval(bsls::Types::Int64 seconds, int nanoseconds = 0); // Set this time interval to have the value given by the sum of the // specified integral number of 'seconds', and the optionally specified // integral number of 'nanoseconds'. If unspecified, 'nanoseconds' is // 0. The behavior is undefined unless the total number of seconds in // the resulting time interval can be represented with a 64-bit signed // integer (see 'isValid'). Note that there is no restriction on the // sign or magnitude of either argument except that they must not // violate the method's preconditions. BSLS_KEYWORD_CONSTEXPR_CPP14 void setIntervalRaw(bsls::Types::Int64 seconds, int nanoseconds = 0); // Set this time interval to have the value given by the sum of the // specified integral number of 'seconds', and the optionally specified // integral number of 'nanoseconds', where 'seconds' and 'nanoseconds' // form a canonical representation of a time interval (see // {Representation}). If unspecified, 'nanoseconds' is 0. The // behavior is undefined unless // '-999,999,999 <= nanoseconds <= +999,999,999' and 'seconds' and // 'nanoseconds' are either both non-negative or both non-positive. // Note that this function provides a subset of the defined behavior of // 'setInterval' chosen to minimize runtime performance cost. // Aspects template <class STREAM> STREAM& bdexStreamIn(STREAM& stream, int version); // Assign to this object the value read from the specified input // 'stream' using the specified 'version' format, and return a // reference to 'stream'. If 'stream' is initially invalid, this // operation has no effect. If 'version' is not supported, this object // is unaltered and 'stream' is invalidated, but otherwise unmodified. // If 'version' is supported but 'stream' becomes invalid during this // operation, this object has an undefined, but valid, state. Note // that no version is read from 'stream'. See the 'bslx' package-level // documentation for more information on BDEX streaming of // value-semantic types and containers. // ACCESSORS #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class DURATION_TYPE> bool isInDurationRange( typename std::enable_if<TimeInterval_IsDuration<DURATION_TYPE>::value, int>::type * = 0) const; // Return 'true' if the value of this time interval is within the valid // range of the parameterized 'DURATION_TYPE', and 'false' otherwise. // Note that this function does not participate in overload resolution // unless 'DURATION_TYPE' is an instantiation of // 'std::chrono::duration'. #endif BSLS_KEYWORD_CONSTEXPR int nanoseconds() const; // Return the nanoseconds field in the canonical representation of the // value of this time interval. BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 seconds() const; // Return the seconds field in the canonical representation of the // value of this time interval. BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 totalDays() const; // Return the value of this time interval as an integral number of // days, rounded towards zero. Note that the return value may be // negative. BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 totalHours() const; // Return the value of this time interval as an integral number of // hours, rounded towards zero. Note that the return value may be // negative. BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 totalMinutes() const; // Return the value of this time interval as an integral number of // minutes, rounded towards zero. Note that the return value may be // negative. BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 totalSeconds() const; // Return the value of this time interval as an integral number of // seconds, rounded towards zero. Note that the return value may be // negative. Also note that this method returns the same value as // 'seconds'. BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::Types::Int64 totalMilliseconds() const; // Return the value of this time interval as an integral number of // milliseconds, rounded towards zero. The behavior is undefined // unless the number of milliseconds can be represented with a 64-bit // signed integer. Note that the return value may be negative. BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::Types::Int64 totalMicroseconds() const; // Return the value of this time interval as an integral number of // microseconds, rounded towards zero. The behavior is undefined // unless the number of microseconds can be represented with a 64-bit // signed integer. Note that the return value may be negative. BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::Types::Int64 totalNanoseconds() const; // Return the value of this time interval as an integral number of // nanoseconds. The behavior is undefined unless the number of // nanoseconds can be represented using a 64-bit signed integer. Note // that the return value may be negative. #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class DURATION_TYPE> BSLS_KEYWORD_CONSTEXPR_CPP14 typename std::enable_if< TimeInterval_IsDuration<DURATION_TYPE>::value && !TimeInterval_RepTraits<typename DURATION_TYPE::rep>::k_IS_FLOAT, DURATION_TYPE>::type asDuration() const; // Return the value of this time interval as a 'std::chrono::duration' // object. This function participates in overloading if // 'DURATION_TYPE' is actually an 'std::chrono::duration' instance, and // if it has *not* a floating point representation. The behavior is // undefined unless the total number of nanoseconds can be represented // using a 'DURATION_TYPE'. Note that the return value may be // negative. #endif double totalSecondsAsDouble() const; // Return the value of this time interval as a real number of seconds. // Note that the return value may be negative and may have a fractional // part (representing the nanosecond field of this object). Also note // that the conversion from the internal representation to a 'double' // may *lose* precision. // Aspects template <class STREAM> STREAM& bdexStreamOut(STREAM& stream, int version) const; // Write the value of this object, using the specified 'version' // format, to the specified output 'stream', and return a reference to // 'stream'. If 'stream' is initially invalid, this operation has no // effect. If 'version' is not supported, 'stream' is invalidated, but // otherwise unmodified. Note that 'version' is not written to // 'stream'. See the 'bslx' package-level documentation for more // information on BDEX streaming of value-semantic types and // containers. std::ostream& print(std::ostream& stream, int level = 0, int spacesPerLevel = 4) const; // Write the value of this object to the specified output 'stream' in a // human-readable format, and return a reference providing modifiable // access to 'stream'. Optionally specify an initial indentation // 'level', whose absolute value is incremented recursively for nested // objects. If 'level' is specified, optionally specify // 'spacesPerLevel', whose absolute value indicates the number of // spaces per indentation level for this and all of its nested objects. // If 'level' is negative, suppress indentation of the first line. If // 'spacesPerLevel' is negative, format the entire output on one line, // suppressing all but the initial indentation (as governed by // 'level'). If 'stream' is not valid on entry, this operation has no // effect. Note that the format is not fully specified, and can change // without notice. #ifndef BDE_OPENSOURCE_PUBLICATION // pending deprecation // DEPRECATED static int maxSupportedBdexVersion(); // !DEPRECATED!: Use 'maxSupportedBdexVersion(int)' instead. // // Return the most current BDEX streaming version number supported by // this class. #endif // BDE_OPENSOURCE_PUBLICATION -- pending deprecation #ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22 static int maxSupportedVersion(); // !DEPRECATED!: Use 'maxSupportedBdexVersion(int)' instead. // // Return the most current BDEX streaming version number supported by // this class. template <class STREAM> STREAM& streamOut(STREAM& stream) const; // !DEPRECATED!: Use 'print' instead. // // Format this time to the specified output 'stream', and return a // reference to the modifiable 'stream'. #endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22 }; // FREE OPERATORS TimeInterval operator+(const TimeInterval& lhs, const TimeInterval& rhs); TimeInterval operator+(const TimeInterval& lhs, double rhs); TimeInterval operator+(double lhs, const TimeInterval& rhs); // Return a 'TimeInterval' value that is the sum of the specified 'lhs' and // 'rhs' time intervals. The behavior is undefined unless (1) operands of // type 'double' can be converted to valid 'TimeInterval' objects, and (2) // the resulting time interval can be represented with a 64-bit signed // integer. TimeInterval operator-(const TimeInterval& lhs, const TimeInterval& rhs); TimeInterval operator-(const TimeInterval& lhs, double rhs); TimeInterval operator-(double lhs, const TimeInterval& rhs); // Return a 'TimeInterval' value that is the difference between the // specified 'lhs' and 'rhs' time intervals. The behavior is undefined // unless (1) operands of type 'double' can be converted to valid // 'TimeInterval' objects, (2) the value on the right-hand side // (potentially after conversion to a 'TimeInterval') has a number of // seconds that is not 'LLONG_MIN', and (3) the resulting time interval can // be represented with a 64-bit signed integer. TimeInterval operator-(const TimeInterval& rhs); // Return a 'TimeInterval' value that is the negative of the specified // 'rhs' time interval. The behavior is undefined unless // 'LLONG_MIN != rhs.seconds()'. bool operator==(const TimeInterval& lhs, const TimeInterval& rhs); bool operator==(const TimeInterval& lhs, double rhs); bool operator==(double lhs, const TimeInterval& rhs); // Return 'true' if the specified 'lhs' and 'rhs' time intervals have the // same value, and 'false' otherwise. Two time intervals have the same // value if their respective second and nanosecond fields have the same // value. The behavior is undefined unless operands of type 'double' can // be converted to valid 'TimeInterval' objects. bool operator!=(const TimeInterval& lhs, const TimeInterval& rhs); bool operator!=(const TimeInterval& lhs, double rhs); bool operator!=(double lhs, const TimeInterval& rhs); // Return 'true' if the specified 'lhs' and 'rhs' time intervals do not // have the same value, and 'false' otherwise. Two time intervals do not // have the same value if their respective second or nanosecond fields // differ in value. The behavior is undefined unless operands of type // 'double' can be converted to valid 'TimeInterval' objects. bool operator< (const TimeInterval& lhs, const TimeInterval& rhs); bool operator< (const TimeInterval& lhs, double rhs); bool operator< (double lhs, const TimeInterval& rhs); bool operator<=(const TimeInterval& lhs, const TimeInterval& rhs); bool operator<=(const TimeInterval& lhs, double rhs); bool operator<=(double lhs, const TimeInterval& rhs); bool operator> (const TimeInterval& lhs, const TimeInterval& rhs); bool operator> (const TimeInterval& lhs, double rhs); bool operator> (double lhs, const TimeInterval& rhs); bool operator>=(const TimeInterval& lhs, const TimeInterval& rhs); bool operator>=(const TimeInterval& lhs, double rhs); bool operator>=(double lhs, const TimeInterval& rhs); // Return 'true' if the nominal relation between the specified 'lhs' and // 'rhs' time interval values holds, and 'false' otherwise. The behavior // is undefined unless operands of type 'double' can be converted to valid // 'TimeInterval' objects. std::ostream& operator<<(std::ostream& stream, const TimeInterval& timeInterval); // Write the value of the specified 'timeInterval' to the specified output // 'stream' in a single-line format, and return a reference providing // modifiable access to 'stream'. If 'stream' is not valid on entry, this // operation has no effect. Note that this human-readable format is not // fully specified and can change without notice. Also note that this // method has the same behavior as 'object.print(stream, 0, -1)'. #if defined(BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE) && \ defined(BSLS_COMPILERFEATURES_SUPPORT_USER_DEFINED_LITERALS) inline namespace literals { inline namespace TimeIntervalLiterals { BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval operator ""_h( unsigned long long int hours); // This user defined literal operator converts the specified 'hours' value // to the respective 'TimeInterval' value. The behavior is undefined // unless the specified number of hours can be converted to valid // 'TimeInterval' object. (See the // "User-Defined Literals" section in the component-level documentation.) BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval operator ""_min(unsigned long long int minutes); // This user defined literal operator converts the specified 'minutes' // value to the respective 'TimeInterval' value. The behavior is undefined // unless the specified number of minutes can be converted to valid // 'TimeInterval' object. (See the // "User-Defined Literals" section in the component-level documentation.) BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval operator ""_s( unsigned long long int seconds); // This user defined literal operator converts the specified 'seconds' // value to the respective 'TimeInterval' value. The behavior is undefined // unless the specified number of seconds can be converted to valid // 'TimeInterval' object. (See the // "User-Defined Literals" section in the component-level documentation.) BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval operator ""_ms( unsigned long long int milliseconds); // This user defined literal operator converts the specified 'milliseconds' // value to the respective 'TimeInterval' value. (See the // "User-Defined Literals" section in the component-level documentation.) BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval operator ""_us( unsigned long long int microseconds); // This user defined literal operator converts the specified 'microseconds' // value to the respective 'TimeInterval' value. (See the // "User-Defined Literals" section in the component-level documentation.) BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval operator ""_ns( unsigned long long int nanoseconds); // This user defined literal operator converts the specified 'nanoseconds' // value to the respective 'TimeInterval' value. (See the // "User-Defined Literals" section in the component-level documentation.) } // close TimeIntervalLiterals namespace } // close literals namespace #endif // BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE && // BSLS_COMPILERFEATURES_SUPPORT_USER_DEFINED_LITERALS // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ------------------ // class TimeInterval // ------------------ // PRIVATE CLASS METHODS inline BSLS_KEYWORD_CONSTEXPR bool TimeInterval::isSumValidInt64(bsls::Types::Int64 lhs, bsls::Types::Int64 rhs) { // {DRQS 164912552} Sun CC miscomplies this ternary operator when the // function is invoked from the 'TimeInterval' constructor. // return lhs > 0 ? LLONG_MAX - lhs >= rhs : LLONG_MIN - lhs <= rhs; return (lhs > 0 && LLONG_MAX - lhs >= rhs) || (lhs <= 0 && LLONG_MIN - lhs <= rhs); } // CLASS METHODS inline int TimeInterval::maxSupportedBdexVersion(int /* versionSelector */) { return 1; } inline BSLS_KEYWORD_CONSTEXPR bool TimeInterval::isValid(bsls::Types::Int64 seconds, int nanoseconds) { return isSumValidInt64(seconds, nanoseconds / k_NANOSECS_PER_SEC); } #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class REP, class PERIOD> bool TimeInterval::isValid(const std::chrono::duration<REP, PERIOD>& duration) { std::chrono::duration<long double> minValue = std::chrono::duration<long double>(LLONG_MIN); --minValue; std::chrono::duration<long double> maxValue = std::chrono::duration<long double>(LLONG_MAX); ++maxValue; const std::chrono::duration<long double> safeDuration = std::chrono::duration_cast<std::chrono::duration<long double> >( duration); return (safeDuration >= minValue && safeDuration <= maxValue); } #endif // BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS // CREATORS inline BSLS_KEYWORD_CONSTEXPR TimeInterval::TimeInterval() : d_seconds(0) , d_nanoseconds(0) { } inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval::TimeInterval(bsls::Types::Int64 seconds, int nanoseconds) : d_seconds(0) , d_nanoseconds(0) { // A seemingly redundant initializer list is needed since members must be // initialized by mem-initializer in 'constexpr' constructor. setInterval(seconds, nanoseconds); } #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class REP_TYPE, class PERIOD_TYPE> inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval::TimeInterval( const std::chrono::duration<REP_TYPE, PERIOD_TYPE>& duration, typename std::enable_if<TimeInterval_DurationTraits< REP_TYPE, PERIOD_TYPE>::k_IMPLICIT_CONVERSION_ENABLED, int>::type *) { BSLS_ASSERT((isValid<REP_TYPE, PERIOD_TYPE>(duration))); using SecondsRatio = std::ratio<1>; using TimeIntervalSeconds = std::chrono::duration<bsls::Types::Int64, SecondsRatio>; using TimeIntervalNanoseconds = std::chrono::duration<int, std::nano>; const bsls::Types::Int64 k_SECONDS = std::chrono::duration_cast<TimeIntervalSeconds>(duration).count(); const int k_NANOSECONDS = std::chrono::duration_cast<TimeIntervalNanoseconds>( duration - TimeIntervalSeconds(k_SECONDS)).count(); setInterval(k_SECONDS, k_NANOSECONDS); } template <class REP_TYPE, class PERIOD_TYPE> inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval::TimeInterval( const std::chrono::duration<REP_TYPE, PERIOD_TYPE>& duration, typename std::enable_if<TimeInterval_DurationTraits< REP_TYPE, PERIOD_TYPE>::k_EXPLICIT_CONVERSION_ENABLED, int>::type *) { BSLS_ASSERT((isValid<REP_TYPE, PERIOD_TYPE>(duration))); const bsls::Types::Int64 k_SECONDS = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); const int k_NANOSECONDS = static_cast<int>( std::chrono::duration_cast<std::chrono::nanoseconds>( duration - std::chrono::seconds(k_SECONDS)).count()); setInterval(k_SECONDS, k_NANOSECONDS); } #endif // MANIPULATORS inline TimeInterval& TimeInterval::operator=(double rhs) { *this = TimeInterval(rhs); return *this; } inline TimeInterval& TimeInterval::operator+=(const TimeInterval& rhs) { return addInterval(rhs.d_seconds, rhs.d_nanoseconds); } inline TimeInterval& TimeInterval::operator+=(double rhs) { *this += TimeInterval(rhs); return *this; } inline TimeInterval& TimeInterval::operator-=(const TimeInterval& rhs) { BSLS_ASSERT_SAFE(LLONG_MIN < rhs.seconds()); return addInterval(-rhs.d_seconds, -rhs.d_nanoseconds); } inline TimeInterval& TimeInterval::operator-=(double rhs) { *this -= TimeInterval(rhs); return *this; } // Add Operations inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& TimeInterval::addDays(bsls::Types::Int64 days) { BSLS_ASSERT_SAFE(LLONG_MAX / k_SECONDS_PER_DAY >= days && LLONG_MIN / k_SECONDS_PER_DAY <= days); return addSeconds(days * k_SECONDS_PER_DAY); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& TimeInterval::addHours(bsls::Types::Int64 hours) { BSLS_ASSERT_SAFE(LLONG_MAX / k_SECONDS_PER_HOUR >= hours && LLONG_MIN / k_SECONDS_PER_HOUR <= hours); return addSeconds(hours * k_SECONDS_PER_HOUR); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& TimeInterval::addMinutes(bsls::Types::Int64 minutes) { BSLS_ASSERT_SAFE(LLONG_MAX / k_SECONDS_PER_MINUTE >= minutes && LLONG_MIN / k_SECONDS_PER_MINUTE <= minutes); return addSeconds(minutes * k_SECONDS_PER_MINUTE); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& TimeInterval::addSeconds(bsls::Types::Int64 seconds) { BSLS_ASSERT_SAFE(isSumValidInt64(seconds, d_seconds)); d_seconds += seconds; if (d_seconds > 0 && d_nanoseconds < 0) { --d_seconds; d_nanoseconds += k_NANOSECS_PER_SEC; } else if (d_seconds < 0 && d_nanoseconds > 0) { ++d_seconds; d_nanoseconds -= k_NANOSECS_PER_SEC; } return *this; } inline TimeInterval& TimeInterval::addMilliseconds(bsls::Types::Int64 milliseconds) { return addInterval( milliseconds / k_MILLISECS_PER_SEC, static_cast<int>((milliseconds % k_MILLISECS_PER_SEC) * k_NANOSECS_PER_MILLISEC)); } inline TimeInterval& TimeInterval::addMicroseconds(bsls::Types::Int64 microseconds) { return addInterval( microseconds / k_MICROSECS_PER_SEC, static_cast<int>((microseconds % k_MICROSECS_PER_SEC) * k_NANOSECS_PER_MICROSEC)); } inline TimeInterval& TimeInterval::addNanoseconds(bsls::Types::Int64 nanoseconds) { return addInterval( nanoseconds / k_NANOSECS_PER_SEC, static_cast<int>(nanoseconds % k_NANOSECS_PER_SEC)); } // Set Operations inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setTotalDays(bsls::Types::Int64 days) { BSLS_ASSERT_SAFE(LLONG_MAX / k_SECONDS_PER_DAY >= days && LLONG_MIN / k_SECONDS_PER_DAY <= days); return setTotalSeconds(days * k_SECONDS_PER_DAY); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setTotalHours(bsls::Types::Int64 hours) { BSLS_ASSERT_SAFE(LLONG_MAX / k_SECONDS_PER_HOUR >= hours && LLONG_MIN / k_SECONDS_PER_HOUR <= hours); return setTotalSeconds(hours * k_SECONDS_PER_HOUR); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setTotalMinutes(bsls::Types::Int64 minutes) { BSLS_ASSERT_SAFE(LLONG_MAX / k_SECONDS_PER_MINUTE >= minutes && LLONG_MIN / k_SECONDS_PER_MINUTE <= minutes); return setTotalSeconds(minutes * k_SECONDS_PER_MINUTE); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setTotalSeconds(bsls::Types::Int64 seconds) { d_seconds = seconds; d_nanoseconds = 0; } inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setTotalMilliseconds(bsls::Types::Int64 milliseconds) { setInterval( milliseconds / k_MILLISECS_PER_SEC, static_cast<int>((milliseconds % k_MILLISECS_PER_SEC) * k_NANOSECS_PER_MILLISEC)); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setTotalMicroseconds(bsls::Types::Int64 microseconds) { setInterval( microseconds / k_MICROSECS_PER_SEC, static_cast<int>((microseconds % k_MICROSECS_PER_SEC) * k_NANOSECS_PER_MICROSEC)); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setTotalNanoseconds(bsls::Types::Int64 nanoseconds) { setInterval( nanoseconds / k_NANOSECS_PER_SEC, static_cast<int>(nanoseconds % k_NANOSECS_PER_SEC)); } #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class REP_TYPE, class PERIOD_TYPE> inline BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval& TimeInterval::addDuration( const std::chrono::duration<REP_TYPE, PERIOD_TYPE>& duration, typename std::enable_if<TimeInterval_DurationTraits< REP_TYPE, PERIOD_TYPE>::k_IMPLICIT_CONVERSION_ENABLED, int>::type *) { BSLS_ASSERT((isValid<REP_TYPE, PERIOD_TYPE>(duration))); const bsls::Types::Int64 k_SECONDS = std::chrono::duration_cast<std::chrono::seconds>(duration).count(); const int k_NANOSECONDS = static_cast<int>( std::chrono::duration_cast<std::chrono::nanoseconds>( duration - std::chrono::seconds(k_SECONDS)).count()); return addInterval(k_SECONDS, k_NANOSECONDS); } #endif inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setInterval(bsls::Types::Int64 seconds, int nanoseconds) { BSLS_PRECONDITIONS_BEGIN(); BSLS_ASSERT(isValid(seconds, nanoseconds)); BSLS_PRECONDITIONS_END(); d_seconds = seconds; if (nanoseconds >= k_NANOSECS_PER_SEC || nanoseconds <= -k_NANOSECS_PER_SEC) { d_seconds += nanoseconds / k_NANOSECS_PER_SEC; d_nanoseconds = static_cast<int>(nanoseconds % k_NANOSECS_PER_SEC); } else { d_nanoseconds = static_cast<int>(nanoseconds); } if (d_seconds > 0 && d_nanoseconds < 0) { --d_seconds; d_nanoseconds += k_NANOSECS_PER_SEC; } else if (d_seconds < 0 && d_nanoseconds > 0) { ++d_seconds; d_nanoseconds -= k_NANOSECS_PER_SEC; } } inline BSLS_KEYWORD_CONSTEXPR_CPP14 void TimeInterval::setIntervalRaw(bsls::Types::Int64 seconds, int nanoseconds) { BSLS_ASSERT_SAFE(-k_NANOSECS_PER_SEC < nanoseconds && k_NANOSECS_PER_SEC > nanoseconds); BSLS_ASSERT_SAFE((seconds >= 0 && nanoseconds >= 0) || (seconds <= 0 && nanoseconds <= 0)); d_seconds = seconds; d_nanoseconds = nanoseconds; } // Aspects template <class STREAM> STREAM& TimeInterval::bdexStreamIn(STREAM& stream, int version) { if (stream) { switch (version) { // switch on the schema version case 1: { bsls::Types::Int64 seconds; int nanoseconds; stream.getInt64(seconds); stream.getInt32(nanoseconds); if (stream && ( (seconds >= 0 && nanoseconds >= 0) || (seconds <= 0 && nanoseconds <= 0)) && nanoseconds > -k_NANOSECS_PER_SEC && nanoseconds < k_NANOSECS_PER_SEC) { d_seconds = seconds; d_nanoseconds = nanoseconds; } else { stream.invalidate(); } } break; default: { stream.invalidate(); // unrecognized version number } } } return stream; } // ACCESSORS #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class DURATION_TYPE> bool TimeInterval::isInDurationRange( typename std::enable_if<TimeInterval_IsDuration<DURATION_TYPE>::value, int>::type *) const { using SecondsRatio = std::ratio<1>; using TimeIntervalSeconds = std::chrono::duration<bsls::Types::Int64, SecondsRatio>; using TimeIntervalNanoseconds = std::chrono::duration<int, std::nano>; using Period = typename DURATION_TYPE::period; using LongDoubleTo = std::chrono::duration<long double, Period>; const LongDoubleTo MIN_VALUE = std::chrono::duration_cast<LongDoubleTo>(DURATION_TYPE::min()); const LongDoubleTo MAX_VALUE = std::chrono::duration_cast<LongDoubleTo>(DURATION_TYPE::max()); const LongDoubleTo value = std::chrono::duration_cast<LongDoubleTo>( TimeIntervalSeconds(seconds())) + std::chrono::duration_cast<LongDoubleTo>( TimeIntervalNanoseconds(nanoseconds())); return (MIN_VALUE <= value && value <= MAX_VALUE); } #endif // BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS inline BSLS_KEYWORD_CONSTEXPR int TimeInterval::nanoseconds() const { return d_nanoseconds; } inline BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 TimeInterval::seconds() const { return d_seconds; } inline BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 TimeInterval::totalDays() const { return d_seconds / k_SECONDS_PER_DAY; } inline BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 TimeInterval::totalHours() const { return d_seconds / k_SECONDS_PER_HOUR; } inline BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 TimeInterval::totalMinutes() const { return d_seconds / k_SECONDS_PER_MINUTE; } inline BSLS_KEYWORD_CONSTEXPR bsls::Types::Int64 TimeInterval::totalSeconds() const { return d_seconds; } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::Types::Int64 TimeInterval::totalMilliseconds() const { BSLS_ASSERT_SAFE(LLONG_MAX / k_MILLISECS_PER_SEC >= d_seconds && LLONG_MIN / k_MILLISECS_PER_SEC <= d_seconds); BSLS_ASSERT_SAFE(isSumValidInt64(d_seconds * k_MILLISECS_PER_SEC, d_nanoseconds / k_NANOSECS_PER_MILLISEC)); return d_seconds * k_MILLISECS_PER_SEC + d_nanoseconds / k_NANOSECS_PER_MILLISEC; } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::Types::Int64 TimeInterval::totalMicroseconds() const { BSLS_ASSERT_SAFE(LLONG_MAX / k_MICROSECS_PER_SEC >= d_seconds && LLONG_MIN / k_MICROSECS_PER_SEC <= d_seconds); BSLS_ASSERT_SAFE(isSumValidInt64(d_seconds * k_MICROSECS_PER_SEC, d_nanoseconds / k_NANOSECS_PER_MICROSEC)); return d_seconds * k_MICROSECS_PER_SEC + d_nanoseconds / k_NANOSECS_PER_MICROSEC; } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::Types::Int64 TimeInterval::totalNanoseconds() const { BSLS_ASSERT_SAFE(LLONG_MAX / k_NANOSECS_PER_SEC >= d_seconds && LLONG_MIN / k_NANOSECS_PER_SEC <= d_seconds); BSLS_ASSERT_SAFE(isSumValidInt64(d_seconds * k_NANOSECS_PER_SEC, d_nanoseconds)); return d_seconds * k_NANOSECS_PER_SEC + d_nanoseconds; } #ifdef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS template <class DURATION_TYPE> inline BSLS_KEYWORD_CONSTEXPR_CPP14 typename std::enable_if< TimeInterval_IsDuration<DURATION_TYPE>::value && !TimeInterval_RepTraits<typename DURATION_TYPE::rep>::k_IS_FLOAT, DURATION_TYPE>::type TimeInterval::asDuration() const { using SecondsRatio = std::ratio<1>; using TimeIntervalSeconds = std::chrono::duration<bsls::Types::Int64, SecondsRatio>; using TimeIntervalNanoseconds = std::chrono::duration<int, std::nano>; BSLS_ASSERT(isInDurationRange<DURATION_TYPE>()); return (std::chrono::duration_cast<DURATION_TYPE>(TimeIntervalSeconds( d_seconds)) + std::chrono::duration_cast<DURATION_TYPE>(TimeIntervalNanoseconds( d_nanoseconds))); } #endif inline double TimeInterval::totalSecondsAsDouble() const { return static_cast<double>(d_seconds) + d_nanoseconds / static_cast<double>(k_NANOSECS_PER_SEC); } // Aspects template <class STREAM> STREAM& TimeInterval::bdexStreamOut(STREAM& stream, int version) const { if (stream) { switch (version) { // switch on the schema version case 1: { stream.putInt64(d_seconds); stream.putInt32(d_nanoseconds); } break; default: { stream.invalidate(); // unrecognized version number } } } return stream; } #ifndef BDE_OPENSOURCE_PUBLICATION // pending deprecation // DEPRECATED METHODS inline int TimeInterval::maxSupportedBdexVersion() { return maxSupportedBdexVersion(0); } #endif // BDE_OPENSOURCE_PUBLICATION -- pending deprecation #ifndef BDE_OMIT_INTERNAL_DEPRECATED // BDE2.22 inline int TimeInterval::maxSupportedVersion() { return maxSupportedBdexVersion(0); } template <class STREAM> inline STREAM& TimeInterval::streamOut(STREAM& stream) const { return print(stream, 0, -1); } #endif // BDE_OMIT_INTERNAL_DEPRECATED -- BDE2.22 } // close package namespace // FREE OPERATORS inline bsls::TimeInterval bsls::operator+(const TimeInterval& lhs, const TimeInterval& rhs) { TimeInterval result(lhs); return result.addInterval(rhs.seconds(), rhs.nanoseconds()); } inline bsls::TimeInterval bsls::operator+(const TimeInterval& lhs, double rhs) { return lhs + TimeInterval(rhs); } inline bsls::TimeInterval bsls::operator+(double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) + rhs; } inline bsls::TimeInterval bsls::operator-(const TimeInterval& lhs, const TimeInterval& rhs) { BSLS_ASSERT_SAFE(LLONG_MIN != rhs.seconds()); TimeInterval result(lhs); result.addInterval(-rhs.seconds(), -rhs.nanoseconds()); return result; } inline bsls::TimeInterval bsls::operator-(const TimeInterval& lhs, double rhs) { return lhs - TimeInterval(rhs); } inline bsls::TimeInterval bsls::operator-(double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) - rhs; } inline bsls::TimeInterval bsls::operator-(const TimeInterval& rhs) { BSLS_ASSERT_SAFE(LLONG_MIN != rhs.seconds()); return TimeInterval(-rhs.seconds(), -rhs.nanoseconds()); } inline bool bsls::operator==(const TimeInterval& lhs, const TimeInterval& rhs) { return lhs.seconds() == rhs.seconds() && lhs.nanoseconds() == rhs.nanoseconds(); } inline bool bsls::operator==(const TimeInterval& lhs, double rhs) { return lhs == TimeInterval(rhs); } inline bool bsls::operator==(double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) == rhs; } inline bool bsls::operator!=(const TimeInterval& lhs, const TimeInterval& rhs) { return lhs.seconds() != rhs.seconds() || lhs.nanoseconds() != rhs.nanoseconds(); } inline bool bsls::operator!=(const TimeInterval& lhs, double rhs) { return lhs != TimeInterval(rhs); } inline bool bsls::operator!=(double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) != rhs; } inline bool bsls::operator< (const TimeInterval& lhs, const TimeInterval& rhs) { return lhs.seconds() < rhs.seconds() || (lhs.seconds() == rhs.seconds() && lhs.nanoseconds() < rhs.nanoseconds()); } inline bool bsls::operator< (const TimeInterval& lhs, double rhs) { return lhs < TimeInterval(rhs); } inline bool bsls::operator< (double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) < rhs; } inline bool bsls::operator<=(const TimeInterval& lhs, const TimeInterval& rhs) { return lhs.seconds() < rhs.seconds() || (lhs.seconds() == rhs.seconds() && lhs.nanoseconds() <= rhs.nanoseconds()); } inline bool bsls::operator<=(const TimeInterval& lhs, double rhs) { return lhs <= TimeInterval(rhs); } inline bool bsls::operator<=(double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) <= rhs; } inline bool bsls::operator> (const TimeInterval& lhs, const TimeInterval& rhs) { return lhs.seconds() > rhs.seconds() || (lhs.seconds() == rhs.seconds() && lhs.nanoseconds() > rhs.nanoseconds()); } inline bool bsls::operator> (const TimeInterval& lhs, double rhs) { return lhs > TimeInterval(rhs); } inline bool bsls::operator> (double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) > rhs; } inline bool bsls::operator>=(const TimeInterval& lhs, const TimeInterval& rhs) { return lhs.seconds() > rhs.seconds() || (lhs.seconds() == rhs.seconds() && lhs.nanoseconds() >= rhs.nanoseconds()); } inline bool bsls::operator>=(const TimeInterval& lhs, double rhs) { return lhs >= TimeInterval(rhs); } inline bool bsls::operator>=(double lhs, const TimeInterval& rhs) { return TimeInterval(lhs) >= rhs; } #if defined(BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE) && \ defined(BSLS_COMPILERFEATURES_SUPPORT_USER_DEFINED_LITERALS) inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::TimeInterval bsls::TimeIntervalLiterals::operator"" _h( unsigned long long int hours) { BSLS_ASSERT((LLONG_MAX/3600) >= hours); return TimeInterval(static_cast<bsls::Types::Int64>(hours*3600), 0); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::TimeInterval bsls::TimeIntervalLiterals::operator"" _min( unsigned long long int minutes) { BSLS_ASSERT((LLONG_MAX/60) >= minutes); return TimeInterval(static_cast<bsls::Types::Int64>(minutes*60), 0); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::TimeInterval bsls::TimeIntervalLiterals::operator"" _s( unsigned long long int seconds) { BSLS_ASSERT(LLONG_MAX > seconds); return TimeInterval(static_cast<bsls::Types::Int64>(seconds), 0); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::TimeInterval bsls::TimeIntervalLiterals::operator"" _ms( unsigned long long int milliseconds) { const bsls::Types::Int64 k_MILLISECS_PER_SEC = 1000; const bsls::Types::Int64 k_NANOSECS_PER_MILLISEC = 1000000; return TimeInterval(milliseconds / k_MILLISECS_PER_SEC, static_cast<int>((milliseconds % k_MILLISECS_PER_SEC) * k_NANOSECS_PER_MILLISEC)); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::TimeInterval bsls::TimeIntervalLiterals::operator"" _us( unsigned long long int microseconds) { const bsls::Types::Int64 k_MICROSECS_PER_SEC = 1000000; const bsls::Types::Int64 k_NANOSECS_PER_MICROSEC = 1000; return TimeInterval(microseconds / k_MICROSECS_PER_SEC, static_cast<int>((microseconds % k_MICROSECS_PER_SEC) * k_NANOSECS_PER_MICROSEC)); } inline BSLS_KEYWORD_CONSTEXPR_CPP14 bsls::TimeInterval bsls::TimeIntervalLiterals::operator"" _ns( unsigned long long int nanoseconds) { const bsls::Types::Int64 k_NANOSECS_PER_SEC = 1000000000; return TimeInterval(nanoseconds / k_NANOSECS_PER_SEC, static_cast<int>(nanoseconds % k_NANOSECS_PER_SEC)); } #endif // BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE && // BSLS_COMPILERFEATURES_SUPPORT_USER_DEFINED_LITERALS // BDE_VERIFY pragma: pop // IMPLEMENTATION NOTE: A 'is_trivially_copyable' trait declaration has been // moved to 'bslmf_istriviallycopyable.h' to work around issues on the Sun CC // 5.13 compiler. We had previously forward declared // 'bsl::is_trivially_copyable' and specialized it for 'TimeInterval' here (see // the 2.24 release tags). //.. // namespace bsl { // template <> // struct is_trivially_copyable<BloombergLP::bsls::TimeInterval> : // bsl::true_type { // // This template specialization for 'is_trivially_copyable' indicates // // that 'Date' is a trivially copyable type. // }; // } //.. } // close enterprise namespace #undef BSLS_TIMEINTERVAL_PROVIDES_CHRONO_CONVERSIONS #endif // ---------------------------------------------------------------------------- // Copyright 2020 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------