一、概述
有过编程经验的人都知道,在我们的工作中基本上都会涉及到字符串的处理,各们编程语言,对字符串的处理的函数也尤其多。除此以外,我们项目的开发中很多地方也会涉及到对时间的处理,比如打日志的时候以日期做为后缀名。
日期和时间在程序中就像字符串处理一样经常出现。而我们今天要讲的就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);
}
本文详细介绍了Boost Date_Time库中的日期处理组件gregorian,包括其核心类、构造方法、属性获取、日期运算等功能,并展示了如何从字符串创建日期及日期转换的方法。
2881

被折叠的 条评论
为什么被折叠?



