有关日期年月日相关计算的问题汇总
下面总结了一些有关日期计算的一些问法以及应对方式
1.平闰年的判断:众所周知即为,(year%4 ==0&&year%100!=0)||(year%400==0)
由于程序中经常用到此函数,不妨写一个函数用来判断:
int isLeapYear(int y){ if((y%4==0&&y%100!=0)||(y%400==0)) return 1; return 0; }
这里用int返回类型,可以作为返回值直接使用
2.利用事先写好的平闰年的日期数组:
int data[][12]={ {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31}};
通过isLeapYear的返回值即可访问对应的那一行
问题一:如问当前输入的日期是今年的第几天,属于正向问题求解,思路主要是通过遍历data数组,将天数累加最后加上所输入日期的天数即可:
int month=1; int t = isLeapYear(y); //用于访问data对应的行 int i =0; while(n>=data[t][i]){ n = n - data[t][i]; i++; } month = i+1; //月份要比数组的下标多1
这里对于日期的格式化输入做一个小的笔记:
例如当题目是按照 2008-08-26 格式输入时,我们此时如何把“ - ”过滤掉,只保存年月日呢?
这里使用c语言的scanf的格式化输入: #include<stdio.h>头文件
scanf("%d-%d-%d",&y,&m,&d); //格式化输入 如 2008-08-26
问题二:问题一的反问题,即求输入一个年份和一个天数,问对应的日期,反向求解即可。通过number天数遍历data数组,每次用 number -=data[t][month],并且使month+1,最后剩余的number即为该日期的天数(day)这一项
注意这里有一个格式化输出的问题,是与上题问题相对应的。也是使用c语言标准库中的输出函数 printf
printf("%04d-%02d-%02d ",y,m,d); //例如2008-08-26
注意这里有一个“不足就要补位”的概念,当输出的场宽不足时,即通过补上0 :%04d就是场宽为4 不足补0
问题三:日期累加:设计一个成语,实现计算一个日期加上若干天后是什么日期。此问题是在上两个问题的基础上,增加了对年份的计算,因为加上的若干天可能会出现超过该年的情况,因此要将所输入的日期的天数保存下来+若干天,用整年的天数与其相比较,将年份做相应的变动。再对剩余天数进行上述问题二的类似求解,得到对应的月份和天数。
设置一个返回某年份天数的函数:
int NumberofYear(int y){ if(isLeapYear(y)) return 366; return 365; }
#include<bits/stdc++.h> using namespace std; int isLeapYear(int y){ //判断平闰年 if((y%4==0&&y%100!=0)||(y%400==0)) return 1; return 0; } int NumberofYear(int y){ //获得年份对应的天数 if(isLeapYear(y)) return 366; return 365; } int main(){ int data[][12]={ {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31}}; int n,y,m,d,x; cin>>n; while(n--){ cin>>y>>m>>d>>x; //先计算当前日期为该年的哪一天 int number = d; int t = isLeapYear(y); for(int i=0;i<m-1;i++){ number += data[t][i]; } number += x; //得到累加天数后的新年份 while(number>NumberofYear(y)){ number -= NumberofYear(y); y++; } //得到累加天数后的新月份 m =0; t = isLeapYear(y); while(number>data[t][m]){ number -= data[t][m]; m++; } //得到累加天数后的新天数 d = number; printf("%04d-%02d-%02d ",y,m+1,d); } }