【问题标题】:C++ - compare two datesC++ - 比较两个日期
【发布时间】:2015-07-19 13:16:22
【问题描述】:

我正在编写一个需要比较两个日期的应用程序。这是我目前所拥有的:

struct entry {
    string text;
    string date; // format: dd.mm.yyyy
    bool finished; 
};

string addNulls(int number, int cols) {
    string num = to_string(number);
    if (num.size() < cols) {
        int count = cols - num.size();
        for (int i = 0; i < count; i++) {
            num = "0" + num;
        }
    }
    return num;
}

// [...]

entry e = {"here is some text", "21.03.2019", false};

int day2 = atoi(e.date.substr(0, 2).c_str());
int month2 = atoi(e.date.substr(3, 2).c_str());
int year2 = atoi(e.date.substr(6, 4).c_str());

time_t t = time(0);
struct tm * now = localtime(&t);

string date1 = e.date.substr(6, 4) + "-" + e.date.substr(3, 2) + "-" + e.date.substr(0, 2) + " 00:00:00";
string date2 = addNulls(now->tm_year, 4) + "-" + addNulls(now->tm_mon, 2) + "-" + addNulls(now->tm_mday, 2) + " 00:00:00";

if(date2 > date1) {
    // do something
}

代码得到一个包含日期的“入口”结构。比代码将日期与实际时间进行比较。问题是,它不起作用!我用一些示例内容运行了一些测试,但结果 (date2 > date1) 返回 false。

为什么?

我读到这个:C++ compare to string dates

【问题讨论】:

  • 通过比较两个日期,没有为std::string 定义operator&gt;。你期待什么?
  • @πάνταῥεῖ 但是,如果您以YYYY-MM-DD 的 ISO 格式表示两个日期,那么这些字符串的字典比较也会正确地对日期进行排序。
  • tm_year是存储实际年份减去1900;例如2015 年表示为 105。类似地,tm_month 从零开始:0 表示 1 月,11 表示 12 月。如果您尝试过最少的调试并在比较之前实际查看了date1date2 的内容,您自己就会注意到这一点。
  • @IgorTandetnik 好吧,OP 应该明确比较的实际输入包括哪些内容。
  • @πάνταῥεῖ OP 显示了在比较之前构建两个字符串的代码。对我来说看起来很清楚。

标签: c++ time


【解决方案1】:

我实际上并没有回答你的问题。但是,我正在为您提供解决方案。您是否考虑过日期/时间库? Boost datetime 很受欢迎。

如果您使用 C++11 或更高版本进行编译,我推荐使用 date time library,因为它是仅头文件(无需链接到诸如 boost 之类的库),而且在我看来,它更简洁语法(这是一个非常主观和有偏见的观点)。

后一个库基于 C++11 &lt;chrono&gt; 库构建。这是您使用此库的示例代码:

#include "date.h"
#include <iostream>
#include <string>

struct entry {
    std::string text;
    date::year_month_day date;
    bool finished; 
};

int
main()
{
    entry e = {"here is some text", date::day(21)/3/2019, false};
    auto day2 = e.date.day();
    auto month2 = e.date.month();
    auto year2 = e.date.year();
    auto t = std::chrono::system_clock::now();
    auto date1 = date::sys_days{e.date};
    auto date2 = t;
    if (date2 > date1)
        std::cout << "It is past " << e.date << '\n';
    else
        std::cout << "It is not past " << e.date << '\n';
}

当前输出:

It is not past 2019-03-21

在 C++14 中,chrono 文字使得指定文字时间非常紧凑:

using namespace std::literals;
auto date1 = date::sys_days{e.date} + 0h + 0min + 0s;

同样关于字面量,如果你加入 using namespace date;,你可以使 entry 的构造更紧凑:

entry e = {"here is some text", 21_d/3/2019, false};

重用日期或日期时间类,甚至创建自己的类,比尝试使用字符串保存日期更容易。此外,当您打算将持续时间添加到时间点时,您可以获得不会意外地将字符串添加到日期的类型安全性。

【讨论】:

    【解决方案2】:

    为什么不使用strptime 来解析日期字符串,将它们转换为纪元时间然后进行比较?

     #include <time.h>
    
     char *
     strptime(const char *restrict buf, const char *restrict format,
         struct tm *restrict tm);
    

    【讨论】:

    • 不这样做有几个原因。例如,(1)它不是标准的 C++,(2)它是以 C 为中心的指针。
    • 同意,但@Paul 已经在使用以 C 为中心的 localtimetime(实际上在 time.hstrptime 相同的标头中定义)。
    • 这在技术上是不正确的。 &lt;time.h&gt; 是标准 C++ 头文件。 strptime 是该标头内容的非标准 扩展。更多信息:stackoverflow.com/questions/321849/…
    猜你喜欢
    • 1970-01-01
    • 2011-09-01
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多