前言
给定两个日期(年月日)要求计算出 这两个日期之间的天数。在生活中我们也总会遇到这样的问题,仔细一想,虽然计算的方法不难,但是真正算起来还是要花费一点时间的,而且在这个过程中很容易因为不细心而得出错误的结果。当我们每次遇到这个问题时,总不能每次都心算或是手算吧?所以呢,写出一个简单的计算两日期之间天数的程序还是有点用的。
分析
虽说这个过程并不复杂,但是我们还是要分析一下:
- 日期是否符合生活规律(即不能出现月为13或是日期出现40的情况)
- 给定日期时不一定是小的在前大的在后
- 计算两日期之间天数的算法
至于日期是否符合生活规律写个判断就可以了,这个很简单,在这里就不赘述,程序中默认给定的日期是正确的,给定日期的先后顺序也我们可以写一个判断并进行位置交换,至于大的在前还是小的在前按你自己的习惯都行,下面的分析以小的在前大的在后为基准并且已经解决日期规范问题。
最最最关键的当然还是计算天数的方法:
写计算天数的算法时我们需要考虑:年份是同年还是不同年,并且我们还要考虑到是否为闰年的情况。同年的情况下还有是否同月的情况,若是同月,将日相减便得到结果,这也是最简单的一种情况。考虑到还有是否闰年,年份是否同年的情况,若是我们这样分那就会有很多种组合,程序也会显得很杂乱。那么我们怎么才能让计算的过程相对更简单呢?
在这里,我就分两种情况:
1):同年的情况下为了不再区分是否同月,我们计算出:(大的日期到年初的天数-小的日期到年初的天数)
2):不同年的情况下,计算出:(小的日期到年末的天数+大的日期到年初的天数+年份差之间的天数)
对于不同年,我们计算小的日期到年末的天数我们还可以计算当前年的总天数-小的日期到年初的天数,所以最后就变成了(大的日期到年初的天数-小的日期到年初的天数+年份差之间的天数)注意此处的年份差之间的天数与2)中的不同,相差1.
为了再简单点,我们再将这两种情况视为一种情况:即不管什么情况,计算出(大的日期到年初的天数-小的日期到年初的天数+年份差之间的天数),因为同年份时的年份差之间的天数为零。
实现
先放上完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <iostream> using namespace std; const int leepMonth[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const int noLeepMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const int year[2] = { 365, 366 }; typedef struct Date { int year; int month; int day; int isLeep; } Date; void isLeep(Date &date) { if ((date.year % 4 == 0 && date.year % 100 != 0) || date.year % 400 == 0) date.isLeep = 1; date.isLeep = 0; } void swap(Date &min, Date &max) { Date temp; if (min.year > max.year || (min.year == max.year && min.month > max.month) || (min.year == max.year && min.month == max.month && min.day > max.day)) { temp = min; min = max; max = temp; } } int diff(Date &min, Date &max) { isLeep(min); isLeep(max); swap(min, max); int minday = 0, maxday = 0, diff = 0; for (int m = 1; m < min.month; m++) { if (min.isLeep) minday += leepMonth[m]; else minday += noLeepMonth[m]; } for (int m = 1; m < max.month; m++) { if (max.isLeep) maxday += leepMonth[m]; else maxday += noLeepMonth[m]; } minday += min.day; maxday += max.day; for (Date y = min; y.year < max.year; y.year++) { isLeep(y); diff += year[y.isLeep]; } diff = diff + maxday - minday; return diff; } int main() { Date startDate, endDate; cout << "please input startday(yyyy MM dd):"; cin >> startDate.year >> startDate.month >> startDate.day; cout << "please input endday(yyyy MM dd):"; cin >> endDate.year >> endDate.month >> endDate.day; cout << "daydiff: " << diff(startDate, endDate) << endl; }
|
为了程序的可读性,这里定义了一个结构体Date
,为了计算年份差之间的天数更方便,结构体中还定义了一个isLeep
成员,结合数组year[2]={355,356}
可以更简单的计算出年份差之间的天数,这部分的完整代码挖出来以便更好理解:
1 2 3 4
| for (Date y = min; y.year < max.year; y.year++) { isLeep(y); diff += year[y.isLeep]; }
|
isLeep()
函数判断当前年是否为闰年,并对结构体成员isLeep
初始化.
为闰年时year[y.isLeep]
即year[1]=366
,不是闰年时year[y.isLeep]
即year[0]=365