The Boost C++ Libraries

Location-independent Times

The class boost::posix_time::ptime defines a location-independent time. It uses the type boost::gregorian::date, but also stores a time. To use boost::posix_time::ptime, include the header file boost/date_time/posix_time/posix_time.hpp.

Example 36.10. Using boost::posix_time::ptime
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt{date{2014, 5, 12}, time_duration{12, 0, 0}};
  date d = pt.date();
  std::cout << d << '\n';
  time_duration td = pt.time_of_day();
  std::cout << td << '\n';
}

To initialize an object of type boost::posix_time::ptime, pass a date of type boost::gregorian::date and a duration of type boost::posix_time::time_duration as the first and second parameters to the constructor. The constructor of boost::posix_time::time_duration takes three parameters, which determine the time. Example 36.10 specifies 12 PM on May 12, 2014, as the point in time. To query date and time, use the member functions date() and time_of_day().

Just as the default constructor of boost::gregorian::date creates an invalid date, the default constructor of boost::posix_time::ptime creates an invalid time. An invalid time can also be created explicitly by passing boost::date_time::not_a_date_time to the constructor. Boost.DateTime provides free-standing functions and member functions to create times that are analogous to those used to create calendar dates of type boost::gregorian::date.

Example 36.11. Creating a timepoint with a clock or a string
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>

using namespace boost::posix_time;

int main()
{
  ptime pt = second_clock::universal_time();
  std::cout << pt.date() << '\n';
  std::cout << pt.time_of_day() << '\n';

  pt = from_iso_string("20140512T120000");
  std::cout << pt.date() << '\n';
  std::cout << pt.time_of_day() << '\n';
}

The class boost::posix_time::second_clock returns the current time. The member function universal_time() returns the UTC time (see Example 36.11). local_time() returns the local time. If you need a higher resolution, boost::posix_time::microsec_clock returns the current time including microseconds.

The free-standing function boost::posix_time::from_iso_string() converts a time stored in a string formatted using the ISO 8601 standard into an object of type boost::posix_time::ptime.

Example 36.12. Using boost::posix_time::time_duration
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;

int main()
{
  time_duration td{16, 30, 0};
  std::cout << td.hours() << '\n';
  std::cout << td.minutes() << '\n';
  std::cout << td.seconds() << '\n';
  std::cout << td.total_seconds() << '\n';
}

Boost.DateTime also provides the class boost::posix_time::time_duration, which specifies a duration. This class has been mentioned before because the constructor of boost::posix_time::ptime expects an object of type boost::posix_time::time_duration as its second parameter. You can also use boost::posix_time::time_duration independently.

hours(), minutes(), and seconds() return the respective parts of a time duration, while member functions such as total_seconds(), which returns the total number of seconds, provide additional information (see Example 36.12). There is no upper limit, such as 24 hours, to the values you can legally pass to boost::posix_time::time_duration.

Example 36.13. Processing timepoints
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt1{date{2014, 5, 12}, time_duration{12, 0, 0}};
  ptime pt2{date{2014, 5, 12}, time_duration{18, 30, 0}};
  time_duration td = pt2 - pt1;
  std::cout << td.hours() << '\n';
  std::cout << td.minutes() << '\n';
  std::cout << td.seconds() << '\n';
}

As with calendar dates, calculations can be performed with points in time and durations. If two times of type boost::posix_time::ptime are subtracted from each other, as in Example 36.13, the result is an object of type boost::posix_time::time_duration that specifies the duration between the two times.

Example 36.14. Processing time durations
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt1{date{2014, 5, 12}, time_duration{12, 0, 0}};
  time_duration td{6, 30, 0};
  ptime pt2 = pt1 + td;
  std::cout << pt2.time_of_day() << '\n';
}

As shown in Example 36.14, a duration can be added to a time, resulting in a new point in time. This example writes 18:30:00 to the standard output stream.

Boost.DateTime uses the same concepts for calendar dates and times. Just as there are classes for times and durations, there is also one for periods. For calendar dates, this is boost::gregorian::date_period; for times it is boost::posix_time::time_period. The constructors of both classes expect two parameters: boost::gregorian::date_period expects two calendar dates as parameters and boost::posix_time::time_period expects two points in time.

Example 36.15. Using boost::posix_time::time_period
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt1{date{2014, 5, 12}, time_duration{12, 0, 0}};
  ptime pt2{date{2014, 5, 12}, time_duration{18, 30, 0}};
  time_period tp{pt1, pt2};
  std::cout.setf(std::ios::boolalpha);
  std::cout << tp.contains(pt1) << '\n';
  std::cout << tp.contains(pt2) << '\n';
}

In general, boost::posix_time::time_period works just like boost::gregorian::date_period. It provides a member function, contains(), which returns true for every point in time within the period. Because the end time, which is passed to the constructor of boost::posix_time::time_period, is not part of the period, the second call to contains() in Example 36.15 returns false.

boost::posix_time::time_period provides additional member functions such as intersection() and merge(), which respectively, calculate the intersection of two overlapping periods and merge two intersecting periods.

Finally, the iterator boost::posix_time::time_iterator iterates over points in time.

Example 36.16. Iterating over points in time
#include <boost/date_time/local_time/local_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt{date{2014, 5, 12}, time_duration{12, 0, 0}};
  time_iterator it{pt, time_duration{6, 30, 0}};
  std::cout << *++it << '\n';
  std::cout << *++it << '\n';
}

Example 36.16 uses the iterator it to jump forward 6.5 hours from the time pt. Because the iterator is incremented twice, the output is 2014-May-12 18:30:00 and 2014-May-13 01:00:00.