深入浅出学习boost的date_time库(一 )

来源:互联网 发布:淘宝虚标电池 编辑:程序博客网 时间:2024/05/02 00:09

一、概述

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

日期和时间在程序中就像字符串处理一样经常出现。而我们今天要讲的就boost的一个与时间处理相关的库date_time库。date_time库需要编译才能使用,在jamfile中指定lib语句是lib boost_date_timedate_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);}
0 0
原创粉丝点击