Provide a value-semantic type representing both date and time.
More...
Namespaces |
namespace | bdlt |
Detailed Description
- Outline
-
-
- Purpose:
- Provide a value-semantic type representing both date and time.
-
- Classes:
-
- See also:
- Component bdlt_date, Component bdlt_time, Component bdlt_datetimetz
-
- Description:
- This component implements a value-semantic type,
bdlt::Datetime
, that represents the composition of a date and a time value. The combined "date+time" value of a bdlt::Datetime
object is expressed textually as "yyyy/mm/dd_hh:mm:ss.ssssss", where "yyyy/mm/dd" represents the "date" part of the value and "hh:mm:ss.ssssss" represents the "time" part.
- In addition to the usual value-semantic complement of methods for getting and setting value, the
bdlt::Datetime
class provides methods and operators for making relative adjustments to value (addDays
, addTime
, addHours
, etc.). In particular, note that adding units of time to a bdlt::Datetime
object can affect the values of both the time and date parts of the object. For example, invoking addHours(2)
on a bdlt::Datetime
object whose value is "1987/10/03_22:30:00.000000" updates the value to "1987/10/04_00:30:00.000000".
-
- Valid bdlt::Datetime Values and Their Representations:
- The "date" part of a
bdlt::Datetime
value has a range of validity identical to a bdlt::Date
object -- i.e., valid dates (according to the Unix [POSIX] calendar) having years in the range [1 .. 9999]
. The valid time values are [00:00:00.000000 .. 23:59:59.999999]
. Furthermore, the unset time value (i.e., 24:00:00.000000, corresponding to the default constructed value for bdlt::Time
) is available for every valid date. Note that the supported range of time does not allow for the injection of leap seconds. The value "0001/01/01_24:00:00.000000" is the default constructed value of bdlt::Datetime
.
- Furthermore, consistent with the
bdlt::Time
type, a bdlt::Datetime
object whose "time" part has the default constructed value, behaves the same, with respect to manipulators and (most) free operators, as if the "time" part had the value 00:00:00.000000. As for bdlt::Time
, the behavior of all bdlt::Datetime
relational comparison operators is undefined if the "time" part of either operand is 24:00:00.000000. Consequently, bdlt::Datetime
objects whose "time" part has the default constructed value must not be used as keys for the standard associative containers, since operator<
is not defined for such objects.
-
- Attributes:
- Conceptually, the two primary attributes of
bdlt::Datetime
are the constituent date and time values. These attributes are given the special designation "part" in this component (i.e., the "time" part and the "date" part, respectively) to distinguish them from the many other attributes (see below) that derive from these two main parts. Name Related Type Default Range
---- ------------ --------------- ------------------------------------
date bdlt::Date 0001/01/01 [0001/01/01 .. 9999/12/31]
time bdlt::Time 24:00:00.000000 [00:00:00.000000 .. 23:59:59.999999]
A bdlt::Datetime
object can be used in terms of its "date" and "time" parts or, if appropriate to an application, the object can be viewed as a single, integrated type having the combined individual attributes of date and time. Accessors and manipulators are provided for each of these eight (derived) attributes: Name Type Default Range Constraint
----------- ---- ------- ----------- -----------------------------
year int 1 [1 .. 9999] none
month int 1 [1 .. 12] none
day int 1 [1 .. 31] must exist for year and month
hour int 24 [0 .. 24] none
minute int 0 [0 .. 59] must be 0 if '24 == hour'
second int 0 [0 .. 59] must be 0 if '24 == hour'
millisecond int 0 [0 .. 999] must be 0 if '24 == hour'
microsecond int 0 [0 .. 999] must be 0 if '24 == hour'
There are two additional "date" part attributes to bdlt::Datetime
: Name Type Default Range Constraint
--------- --------------------- ------- ------------ ----------------------
dayOfYear int 1 [ 1 .. 366] 366 only on leap years
dayOfWeek bdlt::DayOfWeek::Enum SAT [SUN .. SAT] tied to calendar day
where dayOfYear
tracks the value of year/month/day
(and vice versa), and dayOfWeek
can be accessed but not explicitly set.
-
- ISO Standard Text Representation:
- A common standard text representation of a date and time value is described by ISO 8601. BDE provides the
bdlt_iso8601util
component for conversion to and from the standard ISO8601 format.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Basic Syntax:
- Values represented by objects of type
bdlt::Datetime
are used widely in practice. The values of the individual attributes resulting from a default-constructed bdlt::Datetime
object, dt
, are "0001/01/01_24:00:00.000000": We can then set dt
to have a specific value, say, 8:43pm on January 6, 2013: Now suppose we add 6 hours and 9 seconds to this value. There is more than one way to do it: bdlt::Datetime dt2(dt);
dt2.addHours(6);
dt2.addSeconds(9);
assert(2013 == dt2.date().year());
assert( 1 == dt2.date().month());
assert( 7 == dt2.date().day());
assert( 2 == dt2.hour());
assert( 43 == dt2.minute());
assert( 9 == dt2.second());
assert( 0 == dt2.millisecond());
assert( 0 == dt2.microsecond());
bdlt::Datetime dt3(dt);
dt3.addTime(6, 0, 9);
assert(dt2 == dt3);
Notice that (in both cases) the date changed as a result of adding time; however, changing just the date never affects the time: dt3.addDays(10);
assert(2013 == dt3.date().year());
assert( 1 == dt3.date().month());
assert( 17 == dt3.date().day());
assert( 2 == dt3.hour());
assert( 43 == dt3.minute());
assert( 9 == dt3.second());
assert( 0 == dt3.millisecond());
assert( 0 == dt3.microsecond());
We can also add more than a day's worth of time: dt2.addHours(240);
assert(dt3 == dt2);
The individual arguments can also be negative: dt2.addTime(-246, 0, -10, 1000);
assert(dt == dt2);
Finally, we stream the value of dt2
to stdout
: bsl::cout << dt2 << bsl::endl;
The streaming operator produces the following output on stdout
: 06JAN2013_20:43:00.000000
-
- Example 2: Creating a Schedule of Equal Time Intervals:
- Calculations involving date and time values are difficult to get correct manually; consequently, people tend to schedule events on natural time boundaries (e.g., on the hour) even if that is sub-optimal. Having a class such as
bdlt::Datetime
makes doing date and time calculations trivial.
- Suppose one wants to divide into an arbitrary interval such as the time between sunset and sunrise into an arbitrary number (say 7) of equal intervals (perhaps to use as a duty roster for teams making astronomical observations).
- First, we create objects containing values for the start and end of the time interval:
bdlt::Datetime sunset(2014, 6, 26, 20, 31, 23);
bdlt::Datetime sunrise(2014, 6, 27, 5, 26, 51);
Then, we calculate the length of each shift in milliseconds (for good precision -- we may be synchronizing astronomical instruments). Note that the difference of sunrise
and sunset
creates a temporary bdlt::DatetimeInterval
object: const int numShifts = 7;
const bsls::Types::Int64 shiftLengthInMsec
= (sunrise - sunset).totalMilliseconds()
/ numShifts;
Now, we calculate (and print to stdout
) the beginning and end times for each shift: for (int i = 0; i <= numShifts; ++i) {
bdlt::Datetime startOfShift(sunset);
startOfShift.addMilliseconds(shiftLengthInMsec * i);
bsl::cout << startOfShift << bsl::endl;
}
Finally, we observe: 26JUN2014_20:31:23.000000
26JUN2014_21:47:52.714000
26JUN2014_23:04:22.428000
27JUN2014_00:20:52.142000
27JUN2014_01:37:21.856000
27JUN2014_02:53:51.570000
27JUN2014_04:10:21.284000
27JUN2014_05:26:50.998000
Notice how our objects (since they manage both "date" and "time of day" parts of each point in time) seamlessly handle the transition between the two days.