13.6 存储和使用日期和时间

wxWidgets提供了一个功能强大的类wxDateTime来进行时间和日期相关的操作,包括:格式化输出,时区,时间和日期计算等等.还提供了一些静态函数来提供当前的日期和时间以及查询某个给定的年份是不是闰年等.注意即使你只想操作日期或者是时间,你仍然可以使用wxDateTime类型. wxTimeSpan和wxDateSpan类型提供了修改一个wxDateTime值的合适的方法.

wxDateTime

wxDateTime类拥有很多的成员函数,每个函数的含义都很清晰.完整的API可以参考wxWidgets的相关手册,下面只对其中使用最频繁的函数进行一些介绍.

注意尽管时间在其内部总是以格林威治时间(GMT)存储的,但是你通常关心的是本地时区的时间而不是格林威治时间,因此, wxDateTime的构造函数以及更改函数中各个组成时间的要素(比如小时,分钟和秒钟)等都指的是本地时区的时间.所有用于获取时间和日期的函数返回的要素(月,日,小时,分,秒等)也都是本地时间.因此,如果这是你需要的,你不需要作任何额外的操作,如果你希望操作不同时区的时间,请参考相关的文档.

wxDateTime类的构造和更改

wxDateTime可以通过Unix时间戳,仅包含时间的信息,仅包含日期的信息,完整的时间日期信息等途径创建.对于每一个构造函数,都有一个对应的Set函数用来更改已经设置了值的wxDateTime对象.也可以通过类似SetMonth或者SetHour等函数更改时间或者日期中的某个要素.

wxDateTime(time_t)函数根据一个指定的Unix时间戳来构造对象.

wxDateTime(const struct tm&)函数根据一个指定的C语言标准tm结构构造对象.

wxDateTime(wxDateTime_t hour, wxDateTime_t minute = 0, wxDateTime_t second = 0, wxDateTime_t millisec = 0)根据指定的时间要素构造对象.

wxDateTime(wxDateTime_t day, Month month = Inv_Month, int year = Inv_Year, wxDateTime_t hour = 0, wxDateTime_t minute = 0, wxDateTime_t second = 0, wxDateTime_t millisec = 0) 根据指定的时间和日期要素构造对象

wxDateTime访问方法

大多数wxDateTime类的访问函数都是自解释的,比如: GetYear, GetMonth, Getday, GetWeekDay, GetHour, GetMinute, GetSecond, GetMillisecond, GeTDayOfYear, GetWeekOfYear, GetWeekOfMonth和GetYearDay等. wxDateTime还提供了下列一些访问函数:

  • GetTicks返回一个Unix时间戳(也就是自从1970年1月1日午夜以来的秒数).
  • IsValid返回时间日期类是不是已经被初始化(类自使用默认构造函数创建以后始终未被赋值).

获取当前时间

wxDateTime提供了两个静态函数返回当前时间:

  • wxDateTime::Now 返回精度为秒的当前时间.
  • wxDateTime::UNow 返回精度为毫秒的当前时间.

时间和字符串的转换

下面介绍的这些函数用来实现时间和字符串的相互转换.将时间转化成字符串的方法是比较简单的:你可以将时间转换成本地格式的字符串 (FormatDate和FormatTime函数),或者以定义在ISO 8601中的国际标准格式来显示(FormatISODate函数和FormatISOTime函数),也可以以自定义的格式来显示(Format函数).

而从文本到时间的转换则显得更复杂些,因为可能的时间格式太多了.最简单的函数是ParseFormat函数,它用来解析那些指定格式的时间文本.ParseRfc822Date函数用来解析那些定义在RFC822中的时间表示方法,这种方法在email或者互联网上使用比较普遍.

最有趣的文本到时间转换函数是ParseTime,ParseDate和ParseDateTime函数,它们将尽量匹配各种格式的时间文本.除了预定义的那些标准格式以外,ParseDateTime函数甚至可以支持那些类似"tomorrow"(明天), "March first"(三月一日)以及"next Sunday"(下个星期天)这样的时间.

日期比较

两个wxDateTime对象可以通过各种函数进行比较,这些函数都返回bool类型的值.这些函数包括:IsEqualTo, IsEarlierThan, IsLaterThan, IsSameDate和IsSameTime等.

而IsStrictlyBetween和IsBetween则用来比较某个日期是不是在两个日期之间.这两个函数的区别在于,如果要比较的时间刚好等于其中的与其比较的边界值的时候,前者返回False而后者返回True.

日期计算

wxWidgets提供了两个非常灵活的类wxTimeSpan和wxDateSpan来辅助进行日期和时间的计算. wxTimeSpan用来计算那些以毫秒为单位的,跨度不大的,快速的和精确的计算,而wxDateSpan则用来进行跨度比较大的比如几周或者几个月的计算.wxDateSpan将尽可能使用更自然的方法来进行计算,因此其含义有时候并不象它看上去的那样精确.比如1月31日加上一个月将返回二月28日 (或29日),也就是说是二月的最后一天,而不是永远不可能存在的二月31日.通常,你比较喜欢这样的结果,不过有时候相应的减法运算可能也会把你搞糊涂,比如二月28日减去一个月的结果的一月28日而不是一月31日.

日期类型可以进行的操作很多,但是这些操作的组合却未必是有效的.比如:对一个日期进行乘法运算是无效的,而对于任何一个表示时间间隔的类(wxTimeSpan或wxDateSpan)进行乘法运算则没有任何问题.

  • 加法: wxTimeSpan或wxDateSpan可以和wxDateTime进行加法运算,返回一个新的wxDateTime对象. 两个相同类型的时间间隔类也可以进行加法运算,返回一个新的同样类型的对象.
  • 减法: 减法适用和加法同样的规则,额外的一个规则是两个wxDateTime对象相减返回一个wxTimeSpan对象.
  • 乘法: wxTimeSpan或wxDateSpan对象可以乘以一个整数,返回一个同样类型的对象.
  • Unary相减:wxTimeSpan或wxDateSpan对象可以定义为负数,导致相反的时间方向上的同样的间隔.

下面的例子演示了wxDateSpan和wxTimeSpan的用法,更多的用法请参考wxWidgets的相关手册.

void TimeTests()
{
    // 获取当前时间和日期
    wxDateTime DT1 = wxDateTime::Now();
    // 创建一个2星期零1天,或者说15天的间隔
    wxDateSpan Span1(0, 0, 2, 1);
    // 今天减去15天
    wxDateTime DT2 = DT1 - Span1;
    // 用静态方法创建一天的间隔
    wxDateSpan Span2 = wxDateSpan::Day();
    // Span3将代表14天的间隔
    wxDateSpan Span3 = Span1 - Span2;
    // 0 天 (这个间隔将用2周来表示)
    int Days = Span3.GetDays();
    // 14 天 (2 周)
    int TotalDays = Span3.GetTotalDays();
    // 之前两周
    wxDateSpan Span4 = -Span3;
    // 3个月的间隔
    wxDateSpan Span5 = wxDateSpan::Month() * 3;
    // 10小时5分6秒的间隔
    wxTimeSpan Span6(10, 5, 6, 0);
    // DT2增加固定的间隔Span6
    wxDateTime DT3 = DT2 + Span6;
    // Span7是相反方向上的3倍Span6的间隔.
    wxTimeSpan Span7 = (-Span6) * 3;
    // SpanNeg将返回True, 这个间隔是负方向的.
    bool SpanNeg = Span7.IsNegative();
    // 适用静态方法创建一个1小时的间隔
    wxTimeSpan Span8 = wxTimeSpan::Hour();
    // 1小时当然小于30小时(这里使用绝对值)
    bool Longer = Span8.IsLongerThan(Span7);
}