C++ 日期时间类

9
我有自己定义的C++DateTime类,如下所示:
class DateTime
{
public:
  int year;
  int month;
  int day;
  int hour;
  int min;
  int sec;
  int millisec;
};

我有两个 DateTime 需要比较,以确定哪一个更大(更近)。
是否有任何免费的 C++ DateTime 类可用于:
  1. 将我的 DateTime 类转换为它们的 DateTime 类
  2. 他们的类应提供 < , > , <= , >= 操作符进行比较。
如果能提供一个具体的示例就太好了。请注意,我需要比较到毫秒级别。
我在考虑使用 BoostQt。更倾向于使用 Boost

3
如果你已经有自己的班级,为什么还需要另一个班呢? - Kirill V. Lyadvinsky
7
更重要的是,如果你要使用别人的类,为什么只是拿来做比较呢?直接使用他们的类,这样你就省去了自己编写代码的麻烦。抛弃你自己的类。 - GManNickG
原因是我的应用程序是一个C++库,其他应用程序将使用它。1)我不希望他们必须包含Boost库才能使用我的库。2)这个DateTime类已经在遗留系统的许多地方使用过了。感谢您的评论。 - sivabudh
1
重新发明轮子是不好的 :| 如果他们可以使用你的库,他们也可以使用boost。 - GManNickG
是的...我也希望如此。关于Boost的问题在于它太大了。有很多文件夹,而且.lib文件非常大(我使用的是Windows)。这就是为什么我不想让它们包含Boost的原因。 - sivabudh
你可以提取你需要的文件夹,大部分都是头文件:| 向用户展示“Boost”这个“光明”将会使他们受益匪浅。我现在就停止 :) - GManNickG
8个回答

19

我已经浏览了那份文档,但是它太过冗长。我也找不到一个毫秒级的示例。我正在寻找类似于这个链接中的示例:http://doc.trolltech.com/4.5/qdatetime.html。 - sivabudh
确实,我的类非常像struct tm结构体……然而,关键区别在于我还有一个毫秒字段。 - sivabudh
struct tm 不支持毫秒,因为它是 POSIX 的一部分,普通的 UNIX 时间只精确到秒。 - Tyler McHenry
文档对我来说很清楚……boost::posix_time::ptime 是你要转换的类,它是由 boost::gregorian::date(year, month, day) 和 boost::posix_time::time_duration(hours, minutes, seconds) + boost::posix_time::milliseconds(msec) 构建的。 - Greg Rogers
1
Fred,你提供的示例看起来确实可以使用。我将在我的应用程序中尝试它,如果一切正常,我将接受你的答案。谢谢!=) - sivabudh
使用你指出的例子,我成功编写并测试了代码,它按照我的预期运行。我已将我的成果发布在本帖的回答中。谢谢! - sivabudh

8
你可能需要查看Qt中的QDateTime,它具有所需的运算符和毫秒精度。
通过以下方式可以将你的类转换为它:
class DateTime
{
public:
  int year;
  int month;
  int day;
  int hour;
  int min;
  int sec;
  int millisec;

  QDateTime toQDateTime() {
    return QDateTime(QDate(year, month, day), QTime(hour, min, sec, millisec));
  }
};

另一种方式类似 ;-)

5
我脑海中没有任何想法。但我建议重写您的日期类,以保存描述自公元纪元(1970年)以来毫秒数的单个64位整数。然后,您可以自由地通过除以1000并使用正常CRT函数格式化为字符串,还可以取该值模1000以获取毫秒部分。
比较运算符也变得容易了...

我建议使用这样的方式。将时间内部存储为整数,以便比较容易,并提供访问器以获取分解时间的各个部分(小时、月份等)。如果效率是一个问题,您可以缓存分解的时间,直到内部时间被修改,这样您就不必一直重新计算年份以获取月份等。 - Tyler McHenry
也就是说,如果你不打算使用boost。 - Tyler McHenry

5
我早就放弃使用公历存储日期了。我将日期存储为32位整数(类似于儒略日)。因此,日期由(年份* 1000)+ DOY(DOY是一年中的第几天)组成。例如: - 2009001表示2009年1月1日 - 2009365表示2009年12月31日
当然,我的日期类提供了获取年、月、日、添加、减去、递增和递减、比较、获取日期之间天数等方法。
对于日期和时间,我使用64位浮点数,其中实数的整数部分与上述整数(类似于儒略日)日期相同,小数部分表示一天中的时间分数。
例如: - 2009001.04166666666~ 表示2009年1月1日上午1:00 - 2009001.06249999999~ 表示2009年1月1日上午1:30 - 2009001.95833333333~ 表示2009年1月1日晚上11:00
如果只需要分钟精度,则可以使用32位浮点数表示日期和时间,但无法足够准确地存储秒和毫秒。
以这种方式存储日期(和时间)的优点包括: - 只需8字节即可表示数据和时间,而DateTime类在问题中使用32位整数需要28字节。 - 与从时代开始计算的秒数存储的日期相比,当查看数字时(例如在调试器中),您可以从数字中更或多或少地识别出年份、日子和大约的时间(要获取午夜后的小时、分钟、秒,请分别乘以24、1440、86400)。 - 比较日期很简单,只需比较数字(与示例DateTime需要的几个CPU操作相比)。 - 进行日期算术运算需要进行更少的比较操作。
这种方法的缺点(对于时间而言)是略微丧失了精度(实际上这几乎不重要),并且在将其转换为小时、分钟和秒的整数值时需要进行一些简单的舍入。

4

好的,这是回答我自己问题的最终代码片段。我想与其他人分享,以便将来可能会有所帮助。感谢Fred Larson指出的Boost示例。

我选择使用Boost进行DateTime计算,因为我的应用程序已经在其他地方使用了Boost。我认为我也可以使用Qt,但我不能完全确认。

假设DateTime被定义为:

class DateTime
{
public:
  int year;
  int month;
  int day;
  int hour;
  int min;
  int sec;
  int millisec;
};

如何进行简单的日期时间比较

bool DateTime::operator < (const DateTime& dt_)
{
  using namespace boost::posix_time;
  using namespace boost::gregorian;

  ptime thisTime( date(this->year,this->month,this->day),
                  hours(this->hour)  +
                  minutes(this->min) +
                  seconds(this->sec) +
                  boost::posix_time::millisec(int(this->millisec)) );

  ptime thatTime( date(dt_.year,dt_.month,dt_.day),
                  hours(dt_.hour)  +
                  minutes(dt_.min) +
                  seconds(dt_.sec) +
                  boost::posix_time::millisec(int(dt_.millisec)) );

  return thisTime < thatTime;
}

将两个DateTime相加以返回一个新的DateTime

DateTime DateTime::operator + ( const DateTime& dt_ )
{
  using namespace boost::posix_time;
  using namespace boost::gregorian;

  date thisDate( this->year, this->month, this->day );
  date newDate = thisDate + years(dt_.year) + months(dt_.month) + days(dt_.day);

  ptime newDateTime( newDate,
    hours(this->hour)  + hours(dt_.hour)   +
    minutes(this->min) + minutes(dt_.min)  +
    seconds(this->sec) + seconds(dt_.sec)  +
    boost::posix_time::millisec(int(this->millisec)) +
    boost::posix_time::millisec(int(dt_.millisec))
    );

  DateTime dateTime;

  date t1_date = newDateTime.date();

  dateTime.year  = t1_date.year();
  dateTime.month = t1_date.month();
  dateTime.day   = t1_date.day();

  time_duration t1_time = newDateTime.time_of_day();

  dateTime.hour     = t1_time.hours();
  dateTime.min      = t1_time.minutes();
  dateTime.sec      = t1_time.seconds();
  dateTime.millisec = t1_time.fractional_seconds()/1000.0f;

  return dateTime;
}

3
使用<time.h>的内容来实现你的类有什么问题吗?这是C90标准。

没问题...您能否提供一个使用<time.h>的示例呢? - sivabudh
3
这是C++语言。应该加入#include <ctime> - GManNickG

1

GNU R使用一个带有微秒精度的struct tm替代品,而不是(整数)自纪元以来的秒数,现在它使用浮点数。这真的非常有用。对于我的许多应用程序,我只需传递双精度浮点数即可进行时间转换。 请参见当前R源代码中的R-2.9.1/src/main/datetime.c。

如果将其放入独立的C++类中会很方便。


0

对不起,我不能使用MFC,因为我们打算将它做成一个跨平台应用程序。 - sivabudh
请查看链接,可能会有用。 - Learner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接