3.4 日期处理
3.4 日期处理
http://codeup.cn/contest.php?cid=100000578
A 日期差值

题目解析
-
为方便计算,设置第二个日期大于第一个日期,即time2>time1。
-
为方便直接取出每个月的天数,定义一个二维数组int month[13][2] 用于存放每个月的天数(第二维为0时表示平年,为1时表示闰年)。
-
⚠️若两个日期连续,则规定二者之间天数为2天。则若两个日期相同,则答案为1。
方法一
令time1不断加1天,直到time1=time2,统计累加的天数。
具体处理时:若加1天后,天数d等于当前月份m拥有天数+1,则m++,d=1;若月份m>12,则y++,m=1。
方法二
为节约时间,可先把time1的年份y1不断加1,直到与time2的年份y2相差1,期间:
-
若当前y1是闰年且d1<=2(证明闰年的2月还没过完,要算入累加天数)累加366天。
Eg:time1=20200101; time2=20220101——输出732
-
若当前(y1+1)是闰年且d1>2(证明第二年的闰年2月要算)累加366天。
Eg:time1=20190303; time2=20210303——输出732
-
上述两种之外的情况累加365天。
Eg:time1=20200303; time2=20220303——输出731(y1是闰年,但d1>2)
然后进行上述不断天数+1操作。
代码1
#include <cstdio>
bool isLeap(int year) {
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
int main() {
int time1, time2;
//第二维第一个表示平年的月份,第二个表示闰年的月份
int month[13][2] = {{0, 0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
int y1, y2, m1, m2, d1, d2;
while (scanf("%d%d", &time1, &time2) != EOF) {
int temp;
int ans = 1;
if (time1 > time2) {
temp = time1;
time1 = time2;
time2 = temp;
}
y1 = time1 / 10000, m1 = (time1 % 10000) / 100, d1 = time1 % 100;
y2 = time2 / 10000, m2 = (time2 % 10000) / 100, d2 = time2 % 100;
while (y1 != y2 || m1 != m2 || d1 != d2) {
d1++;
ans++;
if (d1 > month[m1][isLeap(y1)]) {
m1++;
d1 = 1;
}
if (m1 > 12) {
y1++;
m1 = 1;
}
}
printf("%d\n", ans);
}
return 0;
}
代码2
#include <cstdio>
bool isLeap(int year) {
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
int main() {
int time1, time2;
//第二维第一个表示平年的月份,第二个表示闰年的月份
int month[13][2] = {{0, 0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
int y1, y2, m1, m2, d1, d2;
while (scanf("%d%d", &time1, &time2) != EOF) {
int temp;
int ans = 1;
if (time1 > time2) {
temp = time1;
time1 = time2;
time2 = temp;
}
y1 = time1 / 10000, m1 = (time1 % 10000) / 100, d1 = time1 % 100;
y2 = time2 / 10000, m2 = (time2 % 10000) / 100, d2 = time2 % 100;
while (y2 - y1 > 1) {
if (isLeap(y1) && d1<=2) ans += 366;
else if (isLeap(y1+1) && d1>2) ans+=366;
else ans += 365;
y1++;
}
while (y1 != y2 || m1 != m2 || d1 != d2) {
d1++;
ans++;
if (d1 > month[m1][isLeap(y1)]) {
m1++;
d1 = 1;
}
if (m1 > 12) {
y1++;
m1 = 1;
}
}
printf("%d\n", ans);
}
return 0;
}
B Day of Week

题目解析
要求一日期所表示的星期。
采用基姆拉尔森公式
:w = (d + 1 + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 【w=0~6,w=0表示周日至周六】
公式要求:
- 将1、2月作为前一年的13、14月
(PS:若采用公式w = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 ,则w=0~6表示周一至周日)
公式原理参考:https://blog.csdn.net/qq_33114231/article/details/52352668
代码
#include <cstdio>
#include <cstring>
int getWeek(int y, int m, int d) {
if (m == 1 || m == 2) {
m += 12;
y--;
}
return (d + 1 + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
}
int main() {
char week[7][20] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
char month[13][20] = {"", "January", "February", "March", "April", "May", "June", "July", "August", "September",
"October", "November", "December"};
int y, m, d, w;
char mm[20];
while (scanf("%d %s %d", &d, mm, &y) != EOF) {
for (int i = 1; i <= 12; i++) {
if (strcmp(month[i], mm) == 0) {
m = i;
break;
}
}
printf("%s\n", week[getWeek(y, m, d)]);
}
return 0;
}
扩展
若求某年第几天的星期:
w = (d + y - 1 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400) % 7 【w=0~6,w=0表示周日至周六】
-
初步推导
-
用 y, d, w 分别表示 年 该年第几天 星期 (w=0-6 代表星期日-星期六 )
-
我们从
公元0年1月1日星期日
开始 -
只考虑最开始的 7 天,即 d = 1---7 变换到 w = 0---6
很直观的得到: w = d-1则该年第 d 天:w = (d - 1) % 7 --------- 公式(1)
-
按年扩展:
- 我们不考虑闰年,假设每一年都是 365 天。由于365是7的52倍多1天,所以每一年的第一天和最后一天星期是相同的。
也就是说下一年的第一天与上一年的第一天星期滞后一天。这是个重要的结论,每过一年,公式(1)会有一天的误差,由于我们是从0年开始的,所以只须要简单的加上年就可以修正扩展年引起的误差,得到公式如下:
w = (d-1 + y) % 7 - 将闰年考虑进去
每个闰年会多出一天,会使后面的年份产生一天的误差。如我们要计算2005年1月1日星期几,就要考虑前面的已经过的2004年中有多少个闰年,将这个误差加上就可以正确的计算了。
根据闰年的定义(能被4整但不能被100整除或能被400整),得到计算闰年的个数的算式:y/4 - y/100 + y/400(计算从公元0年开始过去的闰年数,公元0年不算闰年)。
由于我们要计算的是当前要计算的年之前的闰年数,所以要将年减1,得到了如下的公式:
w = [ d - 1+ y + (y - 1) / 4 - (y - 1) / 100+(y - 1) / 400] % 7 -----公式(2)
- 我们不考虑闰年,假设每一年都是 365 天。由于365是7的52倍多1天,所以每一年的第一天和最后一天星期是相同的。
-
C 打印日期

代码
#include <cstdio>
bool isLeap(int y) {
return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}
int main() {
int month[13][2] = {{0, 0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
int y, m, d, n;
while (scanf("%d %d", &y, &n) != EOF) {
m = 1, d = 0;
if (n < 31) d = n;
else {
int temp = isLeap(y);
while (n > month[m][temp]) {
n -= month[m][temp];
m++;
}
d = n;
}
printf("%04d-%02d-%02d\n", y, m, d);
}
return 0;
}
D 日期类

代码
#include <cstdio>
bool isLeap(int y) {
return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}
int main() {
int M, y, m, d;
int month[13][2] = {{0, 0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
while (scanf("%d", &M) != EOF) {
while (M--) {
scanf("%d %d %d", &y, &m, &d);
d++;
if (d > month[m][isLeap(y)]) {
m++;
d = 1;
}
if (m > 12) {
y++;
m = 1;
}
printf("%04d-%02d-%02d\n", y, m, d);
}
}
return 0;
}
E 日期累加

代码
#include <cstdio>
bool isLeap(int y) {
return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}
int main() {
int M, y, m, d, n;
int month[13][2] = {{0, 0},{31, 31},{28, 29},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31},{31, 31},{30, 30},{31, 31},{30, 30},{31, 31}};
while (scanf("%d", &M) != EOF) {
while (M--) {
scanf("%d %d %d %d", &y, &m, &d, &n);
if (n > 366 && isLeap(y) && d <= 2) {
y++;
n -= 366;
} else if (n > 365 && isLeap(y) && d > 2) {
y++;
n -= 365;
} else if (n > 366 && isLeap(y + 1) && d > 2) {
y++;
n -= 366;
} else if (n > 365) {
y++;
n -= 365;
}
while (n--) {
d++;
if (d > month[m][isLeap(y)]) {
m++;
d = 1;
}
if (m > 12) {
y++;
m = 1;
}
}
printf("%04d-%02d-%02d\n", y, m, d);
}
}
return 0;
}
本文作者:Joey-Wang
本文链接:https://www.cnblogs.com/joey-wang/p/14541162.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步