3.4 日期处理
日期处理在模拟题中算是挺麻烦的,我们需要注意平年和闰年的二月天数不一样,还要注意大小月的区别。
闰年:年份是4的倍数且不是100的倍数,或者年份是400的倍数。
大小月:大月(1、3、5、7、8、10、12)有31天,小月(4、6、9、11)有30天。
闰年的二月有29天,一年有366天;平年的二月只有28天,一年365天。
这些看起来挺复杂的,为了方便处理,我们一般都会用一个二维数组分别存放平年和闰年各个月份的天数,再用一个函数来判断一个年份是不是闰年。
题目描述:
有两个日期,求两个日期之间的天数,如果两个日期是连续的,则规定它们之间的天数为两天。
输入格式:
有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD。
输出格式:
每组数据输出一行,即日期差值。
样例输入:
20130101
20130105
样例输出:
5
思路:
套路一下,我们先将平年和闰年的各个月份天数用一个二维数组存储,顺便用一个函数来判断一个年份是否为闰年。
求两个日期的差值,最直观的方法就是使更早的日期天数不断加1,直到等于另一个日期为止。这里我们有两个地方需要判断一下,一个是天数加1的时候:若是加1之后没有超过这个月份的天数,那就没什么变化,若是超过了,我们需要将月份加1,天数重置为1;另一个是月份加1的时候:若是加1让它超过12,那么就年份加1,月份重置为1。每次循环判定两个日期不相等的时候,我们都必须进行这两个判断!
注意,题目没有提到两个日期谁早谁晚,所以我们需要判断一下。
参考代码:
#include <cstdio>
// month[0]存储了平年各个月份的天数,month[1]存储了闰年各个月份的天数
// 由于计算机中的数组都是从0开始的,而月份是从1开始,
// 为了方便处理,我们将month[0][0]和month[1][0]都设置为0,然后从1开始正式设置
int month[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
// 判断year是否为闰年,返回false(0)或者true(1),对应month数组中的平年和闰年
bool isLeap(int year){
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main(){
int time1, time2;
// scanf("%d%d", &time1, &time2);
// 多点测试,while循环读到文件末尾
while(scanf("%d%d", &time1, &time2) != EOF){
// 判断两个日期谁早谁晚,早的存储到time1,晚的存储到time2
if(time1 > time2){
int temp = time2;
time2 = time1;
time1 = temp;
}
// 将日期拆分为年、月、日,方便处理
int year1=time1/10000, month1=time1%10000/100, day1=time1%100;
int year2=time2/10000, month2=time2%10000/100, day2=time2%100;
// 统计差值,由于连续日期之间的天数为两天,所以这里初始化为1
int ans = 1;
// 当两个日期不相等的时候,循环处理
while(year1<year2 || month1<month2 || day1<day2){
// 如果天数等于这个月的最后一天,那么加1之后就到了下一个月的1号
if(day1 == month[isLeap(year1)][month1]){
month1++;
day1 = 1;
}else{
// 否则只是天数的增加
day1++;
}
// 再判断月份增加之后是否到了13,如果是则到了下一年的一月份
if(month1 == 13){
year1++;
month1 = 1;
}
// 记录总天数
ans++;
}
printf("%d\n", ans);
}
return 0;
}