Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bdlt_epochutil
[Package bdlt]

Conversion between absolute/relative time with respect to epoch. More...

Namespaces

namespace  bdlt

Detailed Description

Outline
Purpose:
Conversion between absolute/relative time with respect to epoch.
Classes:
bdlt::EpochUtil non-primitive functions on epoch-related conversions
See also:
Component bdlt_datetime, Component bdlt_datetimeinterval, Component bsls_timeinterval
Description:
This component defines a namespace, bdlt::EpochUtil, providing non-primitive conversions between two different concepts of time. Clients can convert between absolute time (bdlt::Datetime) and relative time (such as bsl::time_t, bdlt::EpochUtil::TimeT64, bsls::TimeInterval, and bdlt::DatetimeInterval) with respect to the Unix standard "epoch" (1970/01/01_00:00:00.000 UTC), henceforth, simply referred to as "the epoch". Also provided is a fast, thread-safe method, epoch, for access to a pre-instantiated bdlt::Datetime object whose (constant) value is that of the epoch.
Due to different resolutions, conversions between absolute/relative time are possibly lossy when converting from a type with higher resolution to one with lower resolution. The value of the type with higher resolution will be truncated (not rounded). The following table lists the resolution of the types involved in this component:
  Type                      Reference          Resolution
  ---------------------     --------------     ------------
  bsl::time_t               relative           seconds
  bdlt::EpochUtil::TimeT64  relative           seconds
  bdlt::Datetime            absolute (UTC)     microseconds
  bdlt::DatetimeInterval    relative           microseconds
  bsls::TimeInterval        relative           nanoseconds
Note that the interfaces using bdlt::EpochUtil::TimeT64 can be validly used for values before the epoch (corresponding to negative TimeT64 values), whereas the interfaces using bsl::time_t have undefined behavior for such input. Furthermore, even on platforms where bsl::time_t is a 64-bit value, clients of this component are strongly encouraged to use the TimeT64-based methods to avoid limitations imposed by the bsl::time_t-based methods required to ensure identical behavior on all supported platforms (e.g., see the function-level documentation for convertToTimeT(bsl::time_t)).
Also note that these conversions do not take into account the leap seconds (25 as of this writing) added to UTC by the International Earth Rotation and Reference Systems Service, but simply regard each day as having a fixed number of seconds (24 hours * 60 minutes per hour * 60 seconds per minute).
Thread Safety:
It is safe to invoke any function defined in this component in two or more separate threads simultaneously, provided no other thread is simultaneously modifying the argument passed by reference to a non-modifiable user-defined type (such as bsls::TimeInterval or bdlt::Datetime).
Usage:
This section illustrates intended use of this component.
Example 1: Converting Between Various Representations of Time:
When processing date/time data, we are often required to deal with a variety of ways in which to represent that data, and therefore we need to be able to convert between those representations. We can use the methods contained in bdlt::EpochUtil to do this.
First, we set up date/time input values in a variety of formats. We'll use 900ms past midnight of January 1, 2000 as the base date and time, dropping the 900ms if the resolution of a format doesn't support it:
  const bsl::time_t            inputTime         (946684800);
  const bsls::TimeInterval     inputTimeInterval (946684800, 900000000);
  const bdlt::DatetimeInterval inputDatetimeInterval(
                                                0, 0, 0, 0, 946684800900LL);
  const bdlt::Datetime         inputDatetime     (2000, 1, 1, 0, 0, 0, 900);
Then, we set up a set of output variables to receive converted values:
  bsl::time_t            outputTime;
  bsls::TimeInterval     outputTimeInterval;
  bdlt::DatetimeInterval outputDatetimeInterval;
  bdlt::Datetime         outputDatetime;
Next, because bdlt::EpochUtil uses bdlt::Datetime as the common format for conversion, we will set up a pair of variables in this format to represent the values we expect to see:
  const bdlt::Datetime epochDatetimeWithMs   (2000, 1, 1, 0, 0, 0, 900);
  const bdlt::Datetime epochDatetimeWithoutMs(2000, 1, 1, 0, 0, 0, 0);
Now, we perform a set of conversions to bdlt::Datetime and verify that the results are correct. We will use the conversion methods that return by value:
  outputDatetime = bdlt::EpochUtil::convertFromTimeT(inputTime);
  assert(epochDatetimeWithoutMs == outputDatetime);

  outputDatetime =
                 bdlt::EpochUtil::convertFromTimeInterval(inputTimeInterval);
  assert(epochDatetimeWithMs    == outputDatetime);

  outputDatetime =
         bdlt::EpochUtil::convertFromDatetimeInterval(inputDatetimeInterval);
  assert(epochDatetimeWithMs    == outputDatetime);
Finally, we perform a set of conversions from bdlt::Datetime and verify that the results are correct. This time, for variety, we will illustrate the conversion methods which return through an object pointer:
  assert(0 == bdlt::EpochUtil::convertToTimeT(&outputTime, inputDatetime));
  assert(inputTime             == outputTime);

  assert(0 == bdlt::EpochUtil::convertToTimeInterval(&outputTimeInterval,
                                                     inputDatetime));
  assert(inputTimeInterval     == outputTimeInterval);

  assert(0 == bdlt::EpochUtil::convertToDatetimeInterval(
                                                     &outputDatetimeInterval,
                                                     inputDatetime));
  assert(inputDatetimeInterval == outputDatetimeInterval);