确定日期之间的差异

Hyd*_*ide 9 c++ visual-studio-2010 visual-studio visual-c++

我正试图找出一个方法让我的程序采取约会(如2003年2月2日),并显示两者之间的差异与另一个日期(如2012年4月2日),不包括闰年.到目前为止,我只能通过减去"日期"来确定日期是否在同一个月.在这个程序中,我使用2组"月","日"和"年"整数.从这里开始,我几乎不知所措.这是我任务中完全可选的一部分,但我想知道如何让它工作.这对我来说似乎很麻烦,但也许有一个简单的数学公式,我没有想到?

抱歉,我没有此部分的任何预先存在的代码,因为其余的任务只涉及让用户输入日期然后添加和减去一天.

Mik*_*our 14

仅使用标准库,您可以将适度疯狂的日期结构转换为自任意零点以来的秒数; 然后减去并转换成天:

#include <ctime>

// Make a tm structure representing this date
std::tm make_tm(int year, int month, int day)
{
    std::tm tm = {0};
    tm.tm_year = year - 1900; // years count from 1900
    tm.tm_mon = month - 1;    // months count from January=0
    tm.tm_mday = day;         // days count from 1
    return tm;
}

// Structures representing the two dates
std::tm tm1 = make_tm(2012,4,2);    // April 2nd, 2012
std::tm tm2 = make_tm(2003,2,2);    // February 2nd, 2003

// Arithmetic time values.
// On a posix system, these are seconds since 1970-01-01 00:00:00 UTC
std::time_t time1 = std::mktime(&tm1);
std::time_t time2 = std::mktime(&tm2);

// Divide by the number of seconds in a day
const int seconds_per_day = 60*60*24;
std::time_t difference = (time1 - time2) / seconds_per_day;    

// To be fully portable, we shouldn't assume that these are Unix time;
// instead, we should use "difftime" to give the difference in seconds:
double portable_difference = std::difftime(time1, time2) / seconds_per_day;
Run Code Online (Sandbox Code Playgroud)

使用Boost.Date_Time有点不太奇怪:

#include "boost/date_time/gregorian/gregorian_types.hpp"

using namespace boost::gregorian;
date date1(2012, Apr, 2);
date date2(2003, Feb, 2);
long difference = (date1 - date2).days();
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎很麻烦,但也许有一个简单的数学公式,我没有想到?

这确实是一个麻烦,但如果你想自己做计算,有一个公式.


小智 7

由于您正在寻找数学公式,它将帮助您找到问题的解决方案.设Y为年,M为月,D为日.对这两个日期进行此计算.

总计= Y*365 + M*30 + D,然后找出相应日期的2个总计之间的差异.

在将30乘以M值时,您必须给出该月的天数.您可以使用#define值或if循环执行此操作.同样地,你也可以通过将366与Y相乘来实现闰年.

希望这会对你有所帮助....


How*_*ant 6

旧问题的新答案:

chrono- 兼容的低级日期算法

有一个公式,用于将{年,月,日}三元组转换为连续数天的天数.您可以使用它来计算两个日期之间的天数,如下所示:

std::cout << days_from_civil(2012, 4, 2) - days_from_civil(2003, 2, 2) << '\n';
Run Code Online (Sandbox Code Playgroud)

哪个输出:

3347
Run Code Online (Sandbox Code Playgroud)

这篇论文是一本操作手册,而不是一本图书馆.它使用C++ 14来演示公式.每个公式都附有详细的描述和推导,如果您关心公式如何工作,您只需要阅读.

这些公式非常有效,并且在极大范围内有效.例如,使用32位算术,+/ - 5百万年(绰绰有余).

序列日计数是自1970年新年以来(或负值之前)的天数,使公式与Unix时间和所有已知的实现兼容std::chrono::system_clock.

days_from_civil算法并不新颖,它应该与其他算法非常相似,可以做同样的事情.但另一方面,从几天回到{年,月,日}三倍是更棘手的.这是记录的公式civil_from_days,我没有看到像这个一样紧凑的其他配方.

本文包括示例用途,显示典型的计算,std::chrono互操作性和广泛的单元测试,证明超过+/- 1百万年的正确性(使用一个公历的阳历).

所有公式和软件都属于公共领域.


Bor*_*rzh 6

这是一个以y/m/d计算日期差异的完整代码.

假设日期类型,而月和天开始1(类似于Qt):

static int increment[12] = { 1, -2, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 };

int daysInc = 0;
if (to.day() - from.day() < 0)
{
    int month = to.month() - 2; // -1 from zero, -1 previous month.
    if (month < 0)
        month = 11; // Previous month is December.
    daysInc = increment[month];
    if ( (month == 1) && (to.year()%4 == 0) )
        daysInc++; // Increment days for leap year.
}

int total1 = from.year()*360 + from.month()*30 + from.day();
int total2 = to.year()*360 + to.month()*30 + to.day();
int diff = total2 - total1;
int years = diff/360;
int months = (diff - years*360)/30;
int days = diff - years*360 - months*30 + daysInc;

// Extra calculation when we can pass one month instead of 30 days.
if (from.day() == 1 && to.day() == 31) {
    months--;
    days = 30;
}
Run Code Online (Sandbox Code Playgroud)

我尝试了这个算法,它工作正常.如果您在使用/理解它时遇到麻烦,请告诉我.