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

本文详细介绍了Boost Date_Time库中的日期处理组件gregorian,包括其核心类、构造方法、属性获取、日期运算等功能,并展示了如何从字符串创建日期及日期转换的方法。

一、概述

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

日期和时间在程序中就像字符串处理一样经常出现。而我们今天要讲的就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);
}
Boost.Date_Time 中,`boost::posix_time::ptime` 类型可以用来表示个具体的时间点,包括日期和时间。如果只想输出 `ptime` 对象的日期部分,可以通过提取其 `date()` 成员函数获取日期信息,并使用相应的格式化方法进行输出。 以下是个示例代码,展示如何输出 `ptime` 对象的日期部分: ```cpp #include <iostream> #include <boost/date_time/posix_time/posix_time.hpp> int main() { // 创建个当前时间的 ptime 对象 boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); // 提取日期部分 boost::gregorian::date datePart = now.date(); // 输出日期 std::cout << "Date: " << datePart << std::endl; return 0; } ``` 上述代码中,`now.date()` 返回个 `boost::gregorian::date` 类型的对象,它表示 `ptime` 的日期部分,格式为 `YYYY-MM-DD`。该对象可以直接通过流操作符输出[^1]。 也可以自定义日期的输出格式,例如将日期转换为字符串并按照指定格式显示: ```cpp #include <iostream> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/gregorian/gregorian.hpp> int main() { boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); boost::gregorian::date datePart = now.date(); // 自定义日期格式,例如 YYYY/MM/DD std::cout << "Formatted Date: " << datePart.year() << "/" << datePart.month().as_number() << "/" << datePart.day() << std::endl; return 0; } ``` 通过这种方式,可以根据需求灵活地格式化 `ptime` 对象的日期部分。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The_Web3_社区

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值