10.3. 位置无关的时间

boost::gregorian::date 用于创建日期,boost::posix_time::ptime 则用于定义一个位置无关的时间。 boost::posix_time::ptime 会存取 boost::gregorian::date 且额外保存一个时间。

为了使用 boost::posix_time::ptime,必须包含头文件 boost/date_time/posix_time/posix_time.hpp

  1. #include <boost/date_time/posix_time/posix_time.hpp>
  2. #include <boost/date_time/gregorian/gregorian.hpp>
  3. #include <iostream>
  4.  
  5. int main()
  6. {
  7. boost::posix_time::ptime pt(boost::gregorian::date(2009, 1, 5), boost::posix_time::time_duration(12, 0, 0));
  8. boost::gregorian::date d = pt.date();
  9. std::cout << d << std::endl;
  10. boost::posix_time::time_duration td = pt.time_of_day();
  11. std::cout << td << std::endl;
  12. }

要初始化一个 boost::posix_time::ptime 类型的对象,要把一个类型为 boost::gregorian::date 的日期和一个类型为 boost::posix_time::time_duration 的时间长度作为第一和第二参数传递给构造函数。 传给 boost::posix_time::time_duration 构造函数的三个参数决定了时间点。 以上程序指定的时间点是 January 5, 2009 的 12 PM。

要查询日期和时间,可以使用 date()time_of_day() 方法。

boost::gregorian::date 的缺省构造函数会创建一个无效日期一样,如果使用缺省构造函数,boost::posix_time::ptime 类型的对象也是无效的。 也可以通过传递一个 boost::date_time::not_a_date_time 给构造函数来显式创建一个无效时间。

和使用自由函数或其它对象的方法来创建 boost::gregorian::date 类型的历法日期一样,Boost.DateTime 也提供了相应的自由函数和对象来创建时间。

  1. #include <boost/date_time/posix_time/posix_time.hpp>
  2. #include <boost/date_time/gregorian/gregorian.hpp>
  3. #include <iostream>
  4.  
  5. int main()
  6. {
  7. boost::posix_time::ptime pt = boost::posix_time::second_clock::universal_time();
  8. std::cout << pt.date() << std::endl;
  9. std::cout << pt.time_of_day() << std::endl;
  10.  
  11. pt = boost::posix_time::from_iso_string("20090105T120000");
  12. std::cout << pt.date() << std::endl;
  13. std::cout << pt.time_of_day() << std::endl;
  14. }

boost::posix_time::second_clock 表示一个返回当前时间的时钟。 universal_time() 方法返回 UTC 时间,如上例所示。 如果需要本地时间,则必须使用 local_time()

Boost.DateTime 还提供了一个名为 boost::posix_time::microsec_clock 的类,它返回包含微秒在内的当前时间,供需要更高精度时使用。

要将一个保存在字符串中的时间点转换为类型为 boost::posix_time::ptime 的对象,可以用 boost::posix_time::from_iso_string() 这样的自由函数,它要求传入的时间点以 ISO 8601 格式提供。

除了 boost::posix_time::ptime, Boost.DateTime 也提供了 boost::posix_time::time_duration 类,用于指定一个时间长度。 这个类前面已经提到过,因为 boost::posix_time::ptime 的构造函数实际上需要一个 boost::posix_time::time_duration 类型的对象作为其第二个参数。 当然,boost::posix_time::time_duration 也可以单独使用。

  1. #include <boost/date_time/posix_time/posix_time.hpp>
  2. #include <iostream>
  3.  
  4. int main()
  5. {
  6. boost::posix_time::time_duration td(16, 30, 0);
  7. std::cout << td.hours() << std::endl;
  8. std::cout << td.minutes() << std::endl;
  9. std::cout << td.seconds() << std::endl;
  10. std::cout << td.total_seconds() << std::endl;
  11. }

hours(), minutes()seconds() 均返回传给构造函数的各个值,而象 total_seconds() 这样的方法则返回总的秒数,以简单的方式为你提供额外的信息。

可以传递任意值给 boost::posix_time::time_duration,因为没有象24小时这样的上限存在。

和历法日期一样,时间点与时间长度也可以执行运算。

  1. #include <boost/date_time/posix_time/posix_time.hpp>
  2. #include <iostream>
  3.  
  4. int main()
  5. {
  6. boost::posix_time::ptime pt1(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
  7. boost::posix_time::ptime pt2(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(18, 30, 0));
  8. boost::posix_time::time_duration td = pt2 - pt1;
  9. std::cout << td.hours() << std::endl;
  10. std::cout << td.minutes() << std::endl;
  11. std::cout << td.seconds() << std::endl;
  12. }

如果两个 boost::posix_time::ptime 类型的时间点相减,结果将是一个 boost::posix_time::time_duration 类型的对象,给出两个时间点之间的时间长度。

  1. #include <boost/date_time/posix_time/posix_time.hpp>
  2. #include <iostream>
  3.  
  4. int main()
  5. {
  6. boost::posix_time::ptime pt1(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
  7. boost::posix_time::time_duration td(6, 30, 0);
  8. boost::posix_time::ptime pt2 = pt1 + td;
  9. std::cout << pt2.time_of_day() << std::endl;
  10. }

正如这个例子所示,时间长度可以被增加至一个时间点上,以得到一个新的时间点。 以上程序将打印 18:30:00 到标准输出流。

你可能已经留意到,Boost.DateTime 对于历法日期和时间使用了相同的概念。 就象有时间类和时间长度类一样,也有一个时间区间的类。 对于历法日期,这个类是 boost::gregorian::date_period; 对于时间则是 boost::posix_time::time_period。 这两个类均要求传入两个参数给构造函数: boost::gregorian::date_period 要求两个历法日期,而 boost::posix_time::time_period 则要求两个时间。

  1. #include <boost/date_time/posix_time/posix_time.hpp>
  2. #include <iostream>
  3.  
  4. int main()
  5. {
  6. boost::posix_time::ptime pt1(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
  7. boost::posix_time::ptime pt2(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(18, 30, 0));
  8. boost::posix_time::time_period tp(pt1, pt2);
  9. std::cout << tp.contains(pt1) << std::endl;
  10. std::cout << tp.contains(pt2) << std::endl;
  11. }

大致上说,boost::posix_time::time_period 非常象 boost::gregorian::date_period。 它提供了一个名为 contains() 的方法,对于位于该时间区间内的每一个时间点,它返回 true。 由于传给 boost::posix_time::time_period 的构造函数的结束时间不是时间区间的一部分,所以上例中第二个 contains() 调用将返回 false

boost::posix_time::time_period 还提供了其它方法,如 intersection()merge() 分别用于计算两个重叠时间区间的交集,以及合并两个相交区间。

最后,迭代器 boost::posix_time::time_iterator 用于对时间点进行迭代。

  1. #include <boost/date_time/local_time/local_time.hpp>
  2. #include <iostream>
  3.  
  4. int main()
  5. {
  6. boost::posix_time::ptime pt(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
  7. boost::posix_time::time_iterator it(pt, boost::posix_time::time_duration(6, 30, 0));
  8. std::cout << *++it << std::endl;
  9. std::cout << *++it << std::endl;
  10. }

以上程序使用了迭代器 it 从时间点 pt 开始向前跳6.5个小时 。 由于迭代器被递增两次,所以相应的输出分别为 2009-Jan-05 18:30:002009-Jan-06 01:00:00