两个日期之间的天数 C++

Posted

技术标签:

【中文标题】两个日期之间的天数 C++【英文标题】:Number of days between two dates C++ 【发布时间】:2012-12-22 12:52:47 【问题描述】:

我看到了 C#、Java 的示例,但对于 C++,我找不到计算两个日期之间的天数的解决方案。

例如在 2012-01-24 和 2013-01-08 之间

谢谢!

【问题讨论】:

到目前为止你有什么尝试?您使用什么数据类型来存储此日期?在我看来,它可以像 (date1 - date2).to_days(); 一样简单,甚至可以使用 C++11 和适当的代码 ("2012-01-24"_date - "2013-01-08"_date).to_days(); 如果你打算使用这个算法来处理历史数据,要小心,因为过去是惊人的不连续。例如,1582/10/5 和 1582/10/14 之间有多少天?答:1 if you're in Spain, Portugal, or Italy. 【参考方案1】:

这是一种方式。

#include <iostream>
#include <ctime>

int main()

    struct std::tm a = 0,0,0,24,5,104; /* June 24, 2004 */
    struct std::tm b = 0,0,0,5,6,104; /* July 5, 2004 */
    std::time_t x = std::mktime(&a);
    std::time_t y = std::mktime(&b);
    if ( x != (std::time_t)(-1) && y != (std::time_t)(-1) )
    
        double difference = std::difftime(y, x) / (60 * 60 * 24);
        std::cout << std::ctime(&x);
        std::cout << std::ctime(&y);
        std::cout << "difference = " << difference << " days" << std::endl;
    
    return 0;

我的输出

Thu Jun 24 01:00:00 2004
Mon Jul 05 01:00:00 2004
difference = 11 days

Here is a ref to Original author post

【讨论】:

有一个 Ref 要发帖,我把它加粗 我看到了这个(否则我不会知道),但很难看到。 感谢您的提示,我会在下一个回复中考虑这一点 您还应该强调它不起作用。如果日期跨越您在夏季和冬季时间之间更改的日期,您可能会得到不一致的结果。 (暂时使用12:0:0not 0:0:0。)当然,struct tm 中元素的顺序没有指定;你需要像std::tm a; a.tm_year = 104; a.tm_mon = 5; a.tm_mday = 24; a.tm_hour = 12;这样的东西。 这种方法不考虑夏令时转换、闰秒或公历中的空缺。只要您始终考虑每天的午夜并四舍五入到最接近的天数,前两个陷阱就不会伤害您。只要您不使用跨越漏洞的日期范围(1582 之后的任何时间都是安全的),第三个陷阱也不会让您陷入困境。【参考方案2】:

将您的日期转换为表示自一个纪元以来的天数的整数,然后减去。在这个例子中我选择了Rata Die,算法的解释可以在http://mysite.verizon.net/aesir_research/date/rata.htm>找到。

int
rdn(int y, int m, int d)  /* Rata Die day one is 0001-01-01 */
    if (m < 3)
        y--, m += 12;
    return 365*y + y/4 - y/100 + y/400 + (153*m - 457)/5 + d - 306;


int days = rdn(2013, 1, 8) - rdn(2012, 1, 24);

【讨论】:

(153*m - 457)/5 + d - 306 是什么意思? @immiao,算法将二月移动到年底。 (153 * m - 457)/5 计算偏移月份的前几天数。从零年的 3 月 1 日到 12 月 31 日之间有 306 天。【参考方案3】:

旧问题的新答案:

使用这个C++11/C++14 header-only date library,你现在可以写:

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

int
main()

    using namespace date;
    using namespace std;
    auto x = 2012_y/1/24;
    auto y = 2013_y/1/8;
    cout << x << '\n';
    cout << y << '\n';
    cout << "difference = " << (sys_daysy - sys_daysx).count() << " days\n";

哪些输出:

2012-01-24
2013-01-08
difference = 350 days

如果您不想依赖此库,您可以编写自己的库,使用与上述日期库相同的日期算法。它们在本文中找到:chrono-Compatible Low-Level Date Algorithms。本例中使用的本文算法是这样的:

// Returns number of days since civil 1970-01-01.  Negative values indicate
//    days prior to 1970-01-01.
// Preconditions:  y-m-d represents a date in the civil (Gregorian) calendar
//                 m is in [1, 12]
//                 d is in [1, last_day_of_month(y, m)]
//                 y is "approximately" in
//                   [numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366]
//                 Exact range of validity is:
//                 [civil_from_days(numeric_limits<Int>::min()),
//                  civil_from_days(numeric_limits<Int>::max()-719468)]
template <class Int>
constexpr
Int
days_from_civil(Int y, unsigned m, unsigned d) noexcept

    static_assert(std::numeric_limits<unsigned>::digits >= 18,
             "This algorithm has not been ported to a 16 bit unsigned integer");
    static_assert(std::numeric_limits<Int>::digits >= 20,
             "This algorithm has not been ported to a 16 bit signed integer");
    y -= m <= 2;
    const Int era = (y >= 0 ? y : y-399) / 400;
    const unsigned yoe = static_cast<unsigned>(y - era * 400);      // [0, 399]
    const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1;  // [0, 365]
    const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy;         // [0, 146096]
    return era * 146097 + static_cast<Int>(doe) - 719468;

请参阅chrono-Compatible Low-Level Date Algorithms,了解有关此算法如何工作、对其进行单元测试及其有效性范围的详细信息。

此算法模拟proleptic Gregorian calendar,它无限期地扩展公历,向前和向后。要建模其他日历(例如儒略历),您将需要其他算法,such as the ones shown here。一旦你设置了其他日历,并同步到同一个系列纪元(这些算法使用 1970-01-01 Gregorian,这也是 Unix time 纪元),你就可以轻松地计算出任何两个日期之间的天数,但也可以在您建模的任意两个日历之间。

这使您不必在从儒略到公历转换的日期中硬编码。您只需要知道您的输入数据是针对哪个日历引用的。

有时历史文档中可能不明确的日期会用Old Style / New Style 进行注释,以分别表示儒略历或公历。

如果您还关心日期的时间,这个same date library 与&lt;chrono&gt; 库无缝集成以使用hoursminutessecondsmilliseconds、@987654342 @ 和nanoseconds,并用system_clock::now() 获取当前日期和时间。

如果您关心时区,则在date library 之上写一个额外的(单独的)timezone library 以使用IANA timezone database 处理时区。如果需要,timezone library 还具有计算功能,包括 leap seconds。

【讨论】:

如果日期最初存储为std::string 怎么办?你如何将string 转换为sys_days() 可以使用的类型? 搜索“[c++] user:576911 parse”。【参考方案4】:

你可以试试boost date_time库

【讨论】:

【参考方案5】:

为避免创建自己的函数,您可以使用 Boost 中的 date_time

【讨论】:

以上是关于两个日期之间的天数 C++的主要内容,如果未能解决你的问题,请参考以下文章

C++ 计算任意两个日期之间的天数

c++求两个日期之间的间隔天数

用c语言编写计算两个日期之间的天数

C++实现日期相关OJ题

c#如何计算两个日期之间相隔天数

如何写计算两个日期之间的天数函数