我试图找出一个方法让我的程序采取约会(如2003年2月2日),并显示两者之间的差异与另一个日期(如2012年4月2日),不包括闰年。到目前为止,我只能通过减去" day"来确定日期是否在同一个月。在这个程序中,我使用2套"月","日"和"年"整数。从这里开始,我几乎不知所措。这是我任务中完全可选的一部分,但我想知道如何让它发挥作用。这对我来说似乎很麻烦,但也许这是一个我没想过的简单的数学公式?
抱歉,我没有此部分的任何预先存在的代码,因为其余的任务只涉及让用户输入日期然后添加和减去一天。
答案 0 :(得分: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;
使用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();
这对我来说似乎很麻烦,但也许有一个简单的数学公式我不会考虑?
这确实很麻烦,但如果你想自己做计算,那就有一个formula。
答案 1 :(得分:7)
由于您正在寻找数学公式,它将帮助您找到问题的解决方案。设Y为年,M为月,D为日。对这两个日期进行此计算。
总计= Y * 365 + M * 30 + D,然后找出相应日期的2个总数之间的差异。
在将30乘以M值时,您必须给出该月的天数。您可以使用#define值或if循环执行此操作。同样地,你也可以通过将366与Y相乘来实现闰年。
希望这会对你有所帮助....
答案 2 :(得分:6)
旧问题的新答案:
chrono
-Compatible Low-Level Date Algorithms
具有将{年,月,日}三元组转换为天数和后续数的公式。您可以使用它来计算两个日期之间的天数,如下所示:
std::cout << days_from_civil(2012, 4, 2) - days_from_civil(2003, 2, 2) << '\n';
输出:
3347
该论文是一本操作手册,而非图书馆。它使用C ++ 14来演示公式。每个公式都附有详细的描述和推导,如果您关心公式如何运作,您只需要阅读。
公式非常有效,并且在极大范围内有效。例如,使用32位算术,+ / - 5百万年(绰绰有余)。
序列日计数是自1970年新年以来(或负值之前)的天数,使公式与Unix Time以及std::chrono::system_clock
的所有已知实现兼容。
days_from_civil
算法并不新颖,它应该与其他算法非常相似,可以做同样的事情。但另一方面,从几天回到{年,月,日}三倍是更棘手的。这是civil_from_days
记录的公式,我没有看到其他公式与此一样紧凑。
该论文包含显示typical computations,std::chrono
interoperability和广泛unit tests的示例用法,展示了超过+/- 1百万年的正确性(使用proleptic Gregorian calendar)。
所有公式和软件都属于公共领域。
答案 3 :(得分:5)
以下是以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;
}
我尝试了这个算法,它运行正常。如果您在使用/理解它时遇到麻烦,请告诉我。
答案 4 :(得分:2)
我不确定你在哪个平台? Windows,Linux?但是,让我们假装您希望拥有一个独立于平台的解决方案,并且该语言是标准的C ++。
如果您可以使用库,您可以使用Boost :: Date_Time库(http://www.boost.org/doc/libs/1_49_0/doc/html/date_time.html)
如果你不能使用库来解决你的任务,你需要找到一个共同的简单基础。也许您可以将所有日期转换为秒,或将天数减去它们,然后再将其转换回数据。将整数天或月作为整数进行减法将无济于事,因为除非您不考虑其余部分,否则会导致错误的结果。 希望有所帮助。
像dbrank0指出的那样。 :)
答案 5 :(得分:2)
还有另一种方式...
代码:
#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 ("%d\n", diff(d1, d2));
}
}
标准输入:
1
23 9 1960
11 3 2015
标准输出:
19892
行动准则:https://ideone.com/RrADFR
欢迎更好的算法,优化和编辑!
答案 6 :(得分:1)
如果您需要自己完成,那么通过将日期转换为Julian Day,可以轻松实现这一目标。您可以在该链接获得公式,并且从转换开始,您只能使用浮点数,其中每天为1个单位。
答案 7 :(得分:0)
您应该查看DateTime课程。
C ++语法的msdn reference。
答案 8 :(得分:0)
我做了类似的程序,但它只计算一年或几年的天数
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;
}