确定日期之间的差异
Determining the difference between dates
我正在想办法让我的程序确定一个日期(如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参考。
- 如何找到两个日期之间的时间差异(以秒和纳秒为单位)?
- 日期和当前日期之间的差异
- CPP 程序二查找两个给定日期之间的天数,conol CMD
- Qml - c++ 类和 QmlRegisterType 创建的类之间的交换日期
- 十进制格式的日期之间的差异
- 解决方案在两个日期之间的天数内不起作用
- 使用 c++ 获取两个日期与时间字符串之间的差异(以秒为单位)
- 计算当前日期和用户输入日期问题之间的天数
- C 的两个日期之间的差异
- 如何使用C Win32 API计算两个日期之间的天数
- C++计算日期之间的差异
- 两个日期之间的 C++ 日期差异
- v8::值到日期之间的转换
- 两个对象之间的日期比较
- 确定日期之间的差异
- C++ 给定日期和今天日期之间的天数
- 找出日期之间的差异,并将其归类
- c++获取用户选择的日期与实际日期之间的年份(计算日、月、年)
- 两个日期之间的总天数
- 设计一个结构来存储时间和日期.写一个函数来计算两个时间之间的差(以分钟为单位)