Boost程序库完全开发指南:深入C++”准”标准库(第5版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.7 date_time库的高级议题

date_time库包含了丰富的内容,涉及处理日期与时间的很多方面,可以用来解决很多在实际生活中遇到的问题。本节简要讨论一些关于date_time库的高级议题。

2.7.1 编译配置宏

之前的章节中已经讨论了几个用于控制date_time库行为的宏,下面对其进行归纳。

宏DATE_TIME_NO_DEFAULT_CONSTRUCTOR可以禁止编译器创造出date和ptime的默认构造函数,强制在构造它们时必须有一个有效的值,从而避免因某些疏忽而导致的错误。

宏BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES启用了weeks、months、years等日期区间的便捷类型,它们在处理日期时很有用,可以使代码更清晰易懂。但有时候它们也会在进行日期运算时产生非预期结果,如果不想使用它们,就undef这个宏,从而在程序中总使用days,以保证代码的正确性。

宏BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG将启用date_time库更高的时间精确度,由微秒变为纳秒,同时与纳秒相关的一些函数和类也会被启用。在默认情况下此宏是关闭的,因为纳秒精度通常很依赖操作系统,而且在实际生活中很少用到这么高的精确度。

date_time库编译的对象是格里高利历源码,不使用纳秒来处理日期,因此BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG宏对date_time库的编译没有任何影响。

2.7.2 自定义字面值

C++标准新增了自定义字面值的特性(C++11.2.14.8),所以我们可以编写“operator""”操作符来简化与日期时间相关的代码。

下面的代码定义了3个字面值操作符依据C++标准,我们编写的字面值的后缀必须以下画线开始,将无下画线的后缀留给C++标准使用。

适当地使用自定义字面值特性可以很好地简化我们的代码,让代码更具可读性。

2.7.3 格式化时间

date_time库默认的日期时间格式简单、标准,且是英文,但其格式是可以被改变的。date_time库提供了专门的格式化对象date_facet、time_facet等来搭配输入输出流,以定制日期时间的格式。

这些格式化对象就像printf()函数,使用一个格式化字符串来定制日期或时间的格式,也同样有大量的格式标志符。由于格式标志符非常多,本书不在这里一一列出,请参考date_time库的说明文档。

把日期格式化为中文的代码如下:

程序的运行结果如下:

2014年11月03日

2014年11月03日21点50分00.100000秒

2.7.4 本地时间

之前对date_time库的讨论都基于简单的时间,通常对于日常工作和生活是够用的。但如果考虑到世界各地不同时区的因素,时间就变得复杂了,两个不同时区对同一个时间点的日期和时间的表示可能会不同,如果再加上某些地区的夏令时,时间因素就更加复杂了。

date_time库使用time_zone_base、posix_time_zone、custom_time_zone、local_date_time、c_local_adjustor等类和一个文本格式的时区数据库来解决本地时间中时区和夏令时的问题。

本地时间功能位于名字空间boost::local_time,它需要包含的头文件如下:

time_zone_base是时区表示的抽象类,通常我们使用typedef:time_zone_ptr,它是一个指向time_zone_base的智能指针(参见3.3节的shared_ptr)。

local_date_time是一个含有时区信息的时间对象,它可以由date+time_duration+时区构造,在构造时必须指定这个时间是否是夏令时,本地时间会在内部以UTC的形式保存,以方便计算。

为了便于时区编程,date_time库附带了一个小型CSV格式的文本数据库date_time_zonespec.csv,位于libs/date_time/data/,可以自由使用。这个数据库几乎包含了世界上所有国家和地区的时区信息,tz_database类专门管理这个数据库,只要指定时区名,就可以很方便地获得时区信息——一个time_zone_ptr。

假设从北京飞往旧金山,飞行时间为12小时,示范跨时区的时间转换的代码如下:

程序的运行结果如下: