深入浅出学习boost的date

    xiaoxiao2021-03-25  110

    一、概述

    有过编程经验的人都知道,在我们的工作中基本上都会涉及到字符串的处理,各们编程语言,对字符串的处理的函数也尤其多。除此以外,我们项目的开发中很多地方也会涉及到对时间的处理,比如打日志的时候以日期做为后缀名。

    日期和时间在程序中就像字符串处理一样经常出现。而我们今天要讲的就boost的一个与时间处理相关的库date_time库。date_time库需要编译才能使用,在jamfile中指定lib语句是lib boost_date_time。date_time库中包含两个组件,处理日期的组件gregorian(boost/date_time/gregorian/gregorian.hpp)和处理时间的组件posix_time(boost/date_time/posix_time/posix_time.hpp)。

    二、date_timer库详解

    1、处理日期

    date_time库的日期是基于格里高利历,支持从1400-01-01到9999-12-31之间的日期,如果要使用,需包含头文件gregorian.hpp。

    #include <boost/date_time/gregorian/gregorian.hpp> using namespace boost::gregorian

    下面是gregorian.hpp中的代码

    #ifndef GREGORIAN_HPP__ #define GREGORIAN_HPP__ #include "boost/date_time/compiler_config.hpp" #include "boost/date_time/gregorian/gregorian_types.hpp" #include "boost/date_time/gregorian/conversion.hpp" #if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) #include "boost/date_time/gregorian/formatters_limited.hpp" #else #include "boost/date_time/gregorian/formatters.hpp" #endif #if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) #include "boost/date_time/gregorian/greg_facet.hpp" #else #include "boost/date_time/gregorian/gregorian_io.hpp" #endif // USE_DATE_TIME_PRE_1_33_FACET_IO #include "boost/date_time/gregorian/parsers.hpp" #endif

    这段代码里面并没有什么,全是文件的引用,这部分没有什么需要深入理解的,而要理解的是里面这些代码文件都是干什么的。关于这些文件是干什么的我们稍后再讨论。

    下面我们先说一下date_time库中处理日期的核心类,日期模板基于年-月-日系统日期类的接口shell来表示 , 如gregorian 或iso系统。 它提供了启用计算和比较的基本操作。这个日期表示方式和C tm结构方式基本上不一样。这种类型的目标是在一个具体的类中提供有效的日期操作(加,减)和存储(最小化代表的空间)。 因此,日期使用内部计数表示特定日期。日历参数定义转换年-月-日和内部的规则计数形式。需要执行重的应用程序重复同一日期的格式化效果会更好,这种效果通过使用年-月-日来表示。 在内部,日期使用日期编号来表示日期。 这是一个比较单调的时间表示方式。这种表示允许快速比较以及简化创建写数字操作。基本上, 内部日数调整得像julian日期。 调整由表示为通过第1天的Epoch日期确定日历。 第0天为负无穷大而1且保留任何实际日期自动大于负无穷大。当日期从日期构建或格式化为输出时, 应用适当创建年,月, 天转换来表示。

    #ifndef DATE_TIME_DATE_HPP___ #define DATE_TIME_DATE_HPP___ #include <boost/operators.hpp> #include <boost/date_time/year_month_day.hpp> #include <boost/date_time/special_defs.hpp> namespace boost { namespace date_time { template<class T, class calendar, class duration_type_> class date : private boost::less_than_comparable<T , boost::equality_comparable<T > > { public: typedef T date_type; typedef calendar calendar_type; typedef typename calendar::date_traits_type traits_type; typedef duration_type_ duration_type; typedef typename calendar::year_type year_type; typedef typename calendar::month_type month_type; typedef typename calendar::day_type day_type; typedef typename calendar::ymd_type ymd_type; typedef typename calendar::date_rep_type date_rep_type; typedef typename calendar::date_int_type date_int_type; typedef typename calendar::day_of_week_type day_of_week_type; date(year_type y, month_type m, day_type d) //构造函数 : days_(calendar::day_number(ymd_type(y, m, d))) {} date(const ymd_type& ymd) //拷贝构造函数 : days_(calendar::day_number(ymd)) {} //让编译器来写复制,分配和析构 year_type year() const { ymd_type ymd = calendar::from_day_number(days_); return ymd.year; } month_type month() const { ymd_type ymd = calendar::from_day_number(days_); return ymd.month; } day_type day() const { ymd_type ymd = calendar::from_day_number(days_); return ymd.day; } day_of_week_type day_of_week() const { ymd_type ymd = calendar::from_day_number(days_); return calendar::day_of_week(ymd); } ymd_type year_month_day() const { return calendar::from_day_number(days_); } bool operator<(const date_type& rhs) const { return days_ < rhs.days_; } bool operator==(const date_type& rhs) const { return days_ == rhs.days_; } // 验证是不是特殊的日期 bool is_special()const { return(is_not_a_date() || is_infinity()); } // 验证是不是非日期 bool is_not_a_date() const { return traits_type::is_not_a_number(days_); } 验证是不是一个无穷大的日期值 bool is_infinity() const { return traits_type::is_inf(days_); } // 验证日期是不是大于所有可能的日期 bool is_pos_infinity() const { return traits_type::is_pos_inf(days_); } // 验证日期是不是小于所有可能的日期 bool is_neg_infinity() const { return traits_type::is_neg_inf(days_); } special_values as_special() const { return traits_type::to_special(days_); } duration_type operator-(const date_type& d) const { if (!this->is_special() && !d.is_special()) { // 持续时间潜在类型可能会比日期潜在类型更宽阔 // 因此我们从许多通常固定的基本时间中计算两种持续时间的差异 typedef typename duration_type::duration_rep_type duration_rep_type; return duration_type(static_cast< duration_rep_type >(days_) - static_cast< duration_rep_type >(d.days_)); } else { // 在这种情况下差异将会有一个特别的值 date_rep_type val = date_rep_type(days_) - date_rep_type(d.days_); return duration_type(val.as_special()); } } date_type operator-(const duration_type& dd) const { if(dd.is_special()) { return date_type(date_rep_type(days_) - dd.get_rep()); } return date_type(date_rep_type(days_) - static_cast<date_int_type>(dd.days())); } date_type operator-=(const duration_type& dd) { *this = *this - dd; return date_type(days_); } date_rep_type day_count() const { return days_; } //允许从操作符重载中进入内部 date_type operator+(const duration_type& dd) const { if(dd.is_special()) { return date_type(date_rep_type(days_) + dd.get_rep()); } return date_type(date_rep_type(days_) + static_cast<date_int_type>(dd.days())); } date_type operator+=(const duration_type& dd) { *this = *this + dd; return date_type(days_); } //see reference protected: // 这是允许创建一个新的日期类型的私有构造器,不把它暴露给用户是需要类的使用用户理解date类的内部工作机制 explicit date(date_int_type days) : days_(days) {} explicit date(date_rep_type days) : days_(days.as_number()) {} date_int_type days_; }; } } #endif

    date也可以从一个字符串产生,这需要使用工厂函数from_string()或者from_undelimited_string(),前者使用分隔符(斜杠或者连字符串)分隔年月日格式的字符串,后者则是无分隔符的纯字符串格式。

    date d1 = from_string("2017-3-10"); date d1(from_string("2017/3/10")) date d1 = from_undelimited_string(2017310);

    day_clock也是一个工厂类,调用它的成员函数local_day()或者universal_day()会返回一个当天的日期对象,分别是本地日期和UTC日期。day_clock内部使用了标准C的库函数localtime()和gmtime()函数,因此local_day()也是依赖操作系统的时区设置。

    cout << day_clock::local_day() << endl; cout << day_clock::universal() << endl;

    2.date对象的转换

    to_simple_string(date d):转换为YYYY-mmm-DD格式的字符串,其中mmm为3字符的英文月份名;

    to_is_string(date d): 转换为YYYYMMDD格式的字符串;

    to_iso_extended_string(date d):转换为YYYY-MM-DD格式的数字字符串,date也支持流输入与输出,默认使用YYYY-MM-DD格式。

    to_tm(date):date对象转换到tm;

    date_from_tm(tm datetm):tm转换到date

    3.日期长度

    日期长度是以天为单位的时长,是度量时间长度的一个标量。它与日期不同,值可以是任意整数,可正可负。基本的日期长度类如下:

    #ifndef DATE_TIME_DATE_DURATION__ #define DATE_TIME_DATE_DURATION__ #include <boost/operators.hpp> #include <boost/date_time/special_defs.hpp> namespace boost { namespace date_time { template<class duration_rep_traits> class date_duration : private boost::less_than_comparable1< date_duration< duration_rep_traits > , boost::equality_comparable1< date_duration< duration_rep_traits > , boost::addable1< date_duration< duration_rep_traits > , boost::subtractable1< date_duration< duration_rep_traits > , boost::dividable2< date_duration< duration_rep_traits >, int > > > > > { public: typedef typename duration_rep_traits::int_type duration_rep_type; typedef typename duration_rep_traits::impl_type duration_rep; explicit date_duration(duration_rep day_count) : days_(day_count) {} date_duration(special_values sv) : days_(duration_rep::from_special(sv)) {} date_duration(const date_duration<duration_rep_traits>& other) : days_(other.days_) {} duration_rep get_rep()const { return days_; } bool is_special()const { return days_.is_special(); } duration_rep_type days() const { return duration_rep_traits::as_number(days_); } static date_duration unit() { return date_duration<duration_rep_traits>(1); } bool operator==(const date_duration& rhs) const { return days_ == rhs.days_; } bool operator<(const date_duration& rhs) const { return days_ < rhs.days_; } date_duration& operator-=(const date_duration& rhs) { days_ = days_ - rhs.days_; return *this; } date_duration& operator+=(const date_duration& rhs) { days_ = days_ + rhs.days_; return *this; } date_duration operator-() const { return date_duration<duration_rep_traits>(get_rep() * (-1)); } date_duration& operator/=(int divisor) { days_ = days_ / divisor; return *this; } bool is_negative() const { return days_ < 0; } private: duration_rep days_; }; struct duration_traits_long { typedef long int_type; typedef long impl_type; static int_type as_number(impl_type i) { return i; } }; struct duration_traits_adapted { typedef long int_type; typedef boost::date_time::int_adapter<long> impl_type; static int_type as_number(impl_type i) { return i.as_number(); } }; } } #endif

    date_duration支持全序比较操作(==、 !=、 <、>等),也支持完全加减法和递增递减操作,用起来很像一个整数。此外date_duration还支持除法运算,可以除以一个整数,但不能除以另一个date_duration,其他的数学运算如乘法、取余、取模则不支持。

    date支持加减运算,两个date对象的加操作时无意义的(date_time库会以编译错误的方式通知我们),date主要是与时长概念配合。

    案例:

    #include <boost/date_time/gregorian/gregorian.hpp> using namespace boost; int main() { date d1(2000,1,1), d2(2014,11,18); cout << d2 - d1 << endl; assert(d1+(d2-d1) == d2); d1 += days(10); assert(d1.day() == 11); d1 += months(2); assert(d1.month() == 3 && d1.day() == 11); d1 -= years(10); assert(d2.year() == d1.year() = 4); }
    转载请注明原文地址: https://ju.6miu.com/read-23660.html

    最新回复(0)