BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlt_datetime

Detailed Description

Outline

Purpose

Provide a value-semantic type representing both date and time.

Classes

See also
bdlt_date, bdlt_time, 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]
Definition bdlt_date.h:294
Definition bdlt_time.h:196

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
Enum
Enumerated day-of-week values.
Definition bdlt_dayofweek.h:123

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":

bdlt::Datetime dt; assert( 1 == dt.date().year());
assert( 1 == dt.date().month());
assert( 1 == dt.date().day());
assert(24 == dt.hour());
assert( 0 == dt.minute());
assert( 0 == dt.second());
assert( 0 == dt.millisecond());
assert( 0 == dt.microsecond());
int day() const
Return the day of the month in the range [1 .. 31] of this date.
Definition bdlt_date.h:927
int year() const
Return the year in the range [1 .. 9999] of this date.
Definition bdlt_date.h:977
int month() const
Return the month of the year in the range [1 .. 12] of this date.
Definition bdlt_date.h:965
Definition bdlt_datetime.h:331
Date date() const
Return the value of the "date" part of this object.
Definition bdlt_datetime.h:2164
int hour() const
Return the value of the hour attribute of this object.
Definition bdlt_datetime.h:2223
int minute() const
Return the value of the minute attribute of this object.
Definition bdlt_datetime.h:2249
int millisecond() const
Return the value of the millisecond attribute of this object.
Definition bdlt_datetime.h:2239
int microsecond() const
Return the value of the microsecond attribute of this object.
Definition bdlt_datetime.h:2231
int second() const
Return the value of the second attribute of this object.
Definition bdlt_datetime.h:2265

We can then set dt to have a specific value, say, 8:43pm on January 6, 2013:

dt.setDatetime(2013, 1, 6, 20, 43);
assert(2013 == dt.date().year());
assert( 1 == dt.date().month());
assert( 6 == dt.date().day());
assert( 20 == dt.hour());
assert( 43 == dt.minute());
assert( 0 == dt.second());
assert( 0 == dt.millisecond());
assert( 0 == dt.microsecond());
void setDatetime(const Date &date, int hour=0, int minute=0, int second=0, int millisecond=0, int microsecond=0)
Definition bdlt_datetime.h:1360

Now suppose we add 6 hours and 9 seconds to this value. There is more than one way to do it:

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());
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); // -246 h, -10 s, +1000 ms
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); // New York City
bdlt::Datetime sunrise(2014, 6, 27, 5, 26, 51); // New York City

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;
long long Int64
Definition bsls_types.h:132

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.