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
。
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <boost/date_time/gregorian/gregorian.hpp>
- #include <iostream>
- int main()
- {
- boost::posix_time::ptime pt(boost::gregorian::date(2009, 1, 5), boost::posix_time::time_duration(12, 0, 0));
- boost::gregorian::date d = pt.date();
- std::cout << d << std::endl;
- boost::posix_time::time_duration td = pt.time_of_day();
- std::cout << td << std::endl;
- }
要初始化一个 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 也提供了相应的自由函数和对象来创建时间。
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <boost/date_time/gregorian/gregorian.hpp>
- #include <iostream>
- int main()
- {
- boost::posix_time::ptime pt = boost::posix_time::second_clock::universal_time();
- std::cout << pt.date() << std::endl;
- std::cout << pt.time_of_day() << std::endl;
- pt = boost::posix_time::from_iso_string("20090105T120000");
- std::cout << pt.date() << std::endl;
- std::cout << pt.time_of_day() << std::endl;
- }
类 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
也可以单独使用。
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <iostream>
- int main()
- {
- boost::posix_time::time_duration td(16, 30, 0);
- std::cout << td.hours() << std::endl;
- std::cout << td.minutes() << std::endl;
- std::cout << td.seconds() << std::endl;
- std::cout << td.total_seconds() << std::endl;
- }
hours()
, minutes()
和 seconds()
均返回传给构造函数的各个值,而象 total_seconds()
这样的方法则返回总的秒数,以简单的方式为你提供额外的信息。
可以传递任意值给 boost::posix_time::time_duration
,因为没有象24小时这样的上限存在。
和历法日期一样,时间点与时间长度也可以执行运算。
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <iostream>
- int main()
- {
- boost::posix_time::ptime pt1(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
- boost::posix_time::ptime pt2(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(18, 30, 0));
- boost::posix_time::time_duration td = pt2 - pt1;
- std::cout << td.hours() << std::endl;
- std::cout << td.minutes() << std::endl;
- std::cout << td.seconds() << std::endl;
- }
如果两个 boost::posix_time::ptime
类型的时间点相减,结果将是一个 boost::posix_time::time_duration
类型的对象,给出两个时间点之间的时间长度。
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <iostream>
- int main()
- {
- boost::posix_time::ptime pt1(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
- boost::posix_time::time_duration td(6, 30, 0);
- boost::posix_time::ptime pt2 = pt1 + td;
- std::cout << pt2.time_of_day() << std::endl;
- }
正如这个例子所示,时间长度可以被增加至一个时间点上,以得到一个新的时间点。 以上程序将打印 18:30:00
到标准输出流。
你可能已经留意到,Boost.DateTime 对于历法日期和时间使用了相同的概念。 就象有时间类和时间长度类一样,也有一个时间区间的类。 对于历法日期,这个类是 boost::gregorian::date_period
; 对于时间则是 boost::posix_time::time_period
。 这两个类均要求传入两个参数给构造函数: boost::gregorian::date_period
要求两个历法日期,而 boost::posix_time::time_period
则要求两个时间。
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <iostream>
- int main()
- {
- boost::posix_time::ptime pt1(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
- boost::posix_time::ptime pt2(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(18, 30, 0));
- boost::posix_time::time_period tp(pt1, pt2);
- std::cout << tp.contains(pt1) << std::endl;
- std::cout << tp.contains(pt2) << std::endl;
- }
大致上说,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
用于对时间点进行迭代。
- #include <boost/date_time/local_time/local_time.hpp>
- #include <iostream>
- int main()
- {
- boost::posix_time::ptime pt(boost::gregorian::date(2009, 1, 05), boost::posix_time::time_duration(12, 0, 0));
- boost::posix_time::time_iterator it(pt, boost::posix_time::time_duration(6, 30, 0));
- std::cout << *++it << std::endl;
- std::cout << *++it << std::endl;
- }
以上程序使用了迭代器 it 从时间点 pt 开始向前跳6.5个小时 。 由于迭代器被递增两次,所以相应的输出分别为 2009-Jan-05 18:30:00
和 2009-Jan-06 01:00:00
。