确定日期之间的差异

Determining the difference between dates

本文关键字:之间 日期      更新时间:2023-10-16

我正在想办法让我的程序确定一个日期(如2003年2月2日),并用另一个日期显示两者之间的差异(如2012年4月2日,不包括闰年)。到目前为止,我只能通过减去"天"来计算日期是否在同一个月。在这个程序中,我使用了两组"月"、"日"answers"年"整数。我很不知道从这里到哪里去。这是我作业中完全可以选择的部分,但我想知道如何让它发挥作用。这对我来说似乎很麻烦,但也许有一个简单的数学公式我没有想过?

对不起,我没有这部分的任何预先存在的代码,因为任务的其余部分只是让用户输入日期,然后加减一天。

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

#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;

使用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();

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

这确实很麻烦,但如果你想自己计算的话,有一个公式。

这里有一个以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;
}

我试过这个算法,它运行良好。如果您在使用/理解它时遇到问题,请告诉我。

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

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

当用M值乘以30时,您必须给出当月的天数。您可以使用#define值或if循环来执行此操作。同样,你也可以用366乘以Y来计算闰年。

希望这能帮助你…

老问题的新答案:

chrono-兼容的低级别数据算法

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

std::cout << days_from_civil(2012, 4, 2) - days_from_civil(2003, 2, 2) << 'n';

输出:

3347

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

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

串行天数是1970年新年以来(或负值之前)的天数,使公式与Unix Time和std::chrono::system_clock的所有已知实现兼容。

days_from_civil算法并不新颖,它看起来应该与其他算法非常相似。但反过来说,从天数回到{年、月、日}的三倍更为棘手。这是civil_from_days记录的公式,我还没有见过其他公式像这个公式一样紧凑。

该论文包括展示典型计算、std::chrono互操作性的示例使用,以及在+/-100万年内证明正确性的广泛单元测试(使用一个神秘的公历)。

所有的公式和软件都在公共领域。

我不确定你在哪个平台上?Windows、Linux?但让我们假设您想要一个独立于平台的解决方案,并且语言是标准C++。

如果可以使用库,则可以使用Boost::Date_Time库(http://www.boost.org/doc/libs/1_49_0/doc/html/date_time.html)

如果你不能使用库来解决你的作业,你需要找到一个共同的简单基础。也许你可以将所有日期转换为秒,或者减去天,然后再次转换回数据。将天或月作为整数是没有帮助的,因为除非你不考虑其他因素,否则会导致不正确的结果。希望能有所帮助。

就像dbrank0指出的那样。:)

还有另一种方法。。。

  • 给定两个日期,将较早日期的年份作为参考年份
  • 然后计算否。两个给定日期中的每一个之间的天数,并且1/1/<当年>
  • 保留一个单独的函数,告诉到某个特定月份所用的天数
  • 这两个no的绝对差异。天将给出两个给定日期之间的差异
  • 此外,不要忘记考虑闰年

代码:

#‎include‬<stdio.h>
#include<math.h>
typedef struct
{
    int d, m, y;
} Date;
int isLeap (int y)
{
    return (y % 4 == 0) && ( y % 100 != 0) || (y % 400 == 0);
}
int diff (Date d1, Date d2)                         //logic here!
{
    int dd1 = 0, dd2 = 0, y, yref;                  //dd1 and dd2 store the <i>no. of days</i> between d1, d2 and the reference year
    yref = (d1.y < d2.y)? d1.y: d2.y;               //that <b>reference year</b>
    for (y = yref; y < d1.y; y++)
        if (isLeap(y))                              //check if there is any leap year between the reference year and d1's year (exclusive)
            dd1++;
    if (isLeap(d1.y) && d1.m > 2) dd1++;                //add another day if the date is past a leap year's February
    dd1 += daysTill(d1.m) + d1.d + (d1.y - yref) * 365;     //sum up all the tiny bits (days)
    for (y = yref; y < d2.y; y++)                       //repeat for d2
        if(isLeap(y))
            dd2++;
    if (isLeap(y) && d2.m > 2) dd2++;
    dd2 += daysTill(d2.m) + d2.d + (d2.y - yref) * 365;
    return abs(dd2 - dd1);                          //return the absolute difference between the two <i>no. of days elapsed past the reference year</i>
}
int daysTill (int month)                            //some logic here too!!
{
    int days = 0;
    switch (month)
    {
        case 1: days = 0;
        break;
        case 2: days = 31;
        break;
        case 3: days = 59;
        break;
        case 4: days = 90;      //number of days elapsed before April in a non-leap year
        break;
        case 5: days = 120;
        break;
        case 6: days = 151;
        break;
        case 7: days = 181;
        break;
        case 8: days = 212;
        break;
        case 9: days = 243;
        break;
        case 10:days = 273;
        break;
        case 11:days = 304;
        break;
        case 12:days = 334;
        break;
    }
    return days;
}
main()
{
    int t;          //no. of test cases
    Date d1, d2;    //d1 is the first date, d2 is the second one! obvious, duh!?
    scanf ("%d", &t);
    while (t--)
    {
        scanf ("%d %d %d", &d1.d, &d1.m, &d1.y);
        scanf ("%d %d %d", &d2.d, &d2.m, &d2.y);
        printf ("%dn", diff(d1, d2));
    }
}

标准输入:

1
23 9 1960
11 3 2015

标准输出:

19892

行动守则:https://ideone.com/RrADFR

更好的算法、优化和编辑总是受欢迎的!

如果你需要自己做,那么一种非常简单的方法是将日期转换为儒略日。你可以在这个链接上获得公式,从转换开始,你只使用浮动,每天是1个单位。

我也做过类似的程序,但它只计算一年或几年的天数

PS我在c++编程只有大约两个月的

    #include<iostream>
    int calculateDaysInYears(int intYear, int endYear);
    int checkYear(int intYear);
    int checkMonth(int i, int intYear);
    int getUserData()
{
    int dayOrMonthOrYear;
    std::cin >> dayOrMonthOrYear;
    return dayOrMonthOrYear;
}
    int calculateMonthInYears(int initialMonth, int endMonth, int initialYear)
{
    //Подсчет дней начальной даты для варианта с несколькими годами
    int x(0);
    initialMonth++;
    for (int i = initialMonth; i <= endMonth; i++)
        x += checkMonth(i, initialYear);
    return x;
}
    int calculateMonth(int startMonth, int endMonth, int initialYear)
{
    //Формула для подсчета кол-вa дней промежуточных месяцев
    //Расчет в пределах года
    
    startMonth++;
    int x(0);
    for (int i = startMonth; i < endMonth; i++)
        x += checkMonth(i, initialYear);
    return x;
}
    int calculateMonthForEndYear(int endMonth, int endYear)
{
    //Подсчет дней в конечном году
    int x(0);
    //Декремент кол-ва конечных месяцев для компенсации дней последнего месяца
    --endMonth;
    for (int i = 1; i <= endMonth; i++)
        x += checkMonth(i, endYear);
    return x;
}
    int checkMonth(int i, int intYear)
{
        if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
            return 31;
        else 
            if (i == 2)
            {
                //Если год високосный, то делится на 4 и 400 без остатка, а на 100 с остатком
                if ((intYear % 4 == 0) && (intYear % 100 != 0 ) || (intYear % 400 == 0))
                    return 29;                                                  
                else
                    return 28;
            }
        else
            return 30;
}
    int calculateAmountOfDays(int initialDay, int initialMonth, int initialYear)
{
    //Подсчет дней до конца стартового месяца
    int month = checkMonth(initialMonth, initialYear);
    int days = month - initialDay;
    return days;
}
    int allDays(int initilDays, int endDays, int midleMonth)
{
    int totalDays;
    
    //Подсчет всех дней от начала до конца
    totalDays = midleMonth + initilDays + endDays;
    return totalDays;
}
    int checkYear(int intYear)
{
    if ((intYear % 4 == 0) && (intYear % 100 != 0) || (intYear % 400 == 0))
        return 366;//Високосный год
    else
        return 365;//Невисокосный год
}
    int calculateDaysInYears(int intYear, int endYear)
{
    //Начальное кол-во дней. Необходимо для запуска счетчика
    int amountDays(0);
    //Инкремент начального года для компенсации кол-ва дней промежуточных годов
    intYear++;
    for (int i = intYear; i < endYear; i++)
        amountDays += checkYear(i);
    return amountDays;
}
    int main()
{
    int initialDay;
    int initialMonth;
    int initialYear;
    int endDay;
    int endMonth;
    int endYear;
    std::cout << "Hello! I'm your calendar calculator."            << std::endl <<
                 "Here some rules: "                               << std::endl << 
                 "you should enter a data like(d.m.y): 23.8.2020." << std::endl <<
                 "Also you can ask me to calculate for couple years or in border of one year. Good luck! " << std::endl;
    std::cout << "" << std::endl;
    //Начальная дата
    std::cout << "Enter an initial day: ";
    initialDay = getUserData();
    std::cout << "Enter an initial month: ";
    initialMonth = getUserData();
    std::cout << "Enter an initial year: ";
    initialYear = getUserData();
    std::cout << "" << std::endl;//Пропуск строки
    //Конечная дата
    std::cout << "Enter an end day: ";
    endDay = getUserData();
    std::cout << "Enter an end month: ";
    endMonth = getUserData();
    std::cout << "Enter an end year: ";
    endYear = getUserData();
    //Проверка кол-ва годов
    if ((endYear - initialYear) >= 1)
    {
        //Подсчет дней до конца начального года
        int daysToTheEndOfStartYear = calculateMonthInYears(initialMonth, 12, initialYear) + calculateAmountOfDays(initialDay, initialMonth, initialYear);
        //Подсчет дней до конца конечного месяца
        int daysToTheEndOfEndYear = calculateMonthForEndYear(endMonth, endYear) + endDay;
        //Подсчет дней между годами
        int whalDays = calculateDaysInYears(initialYear, endYear);
        //Подсчет конечной цыфры
        int allDay = whalDays + daysToTheEndOfEndYear + daysToTheEndOfStartYear;
        //Вывод в консоль
        std::cout << allDay;
    }
    else
    {
        //Дни месяцев между начальным и конечным месяцами
        int daysInMonths = calculateMonth(initialMonth, endMonth, initialYear);
        //Подсчет дней до конца начального месяца
        int daysInFirstMonth = calculateAmountOfDays(initialDay, initialMonth, initialYear);
        //Подсчет конечной цыфры
        int allDay = daysInMonths + daysInFirstMonth + endDay;
        //Вывод в консоль
        std::cout << allDay;
    }
    return 0;
}

您应该查看DateTime类。

也是C++语法的msdn参考。