公元日期计算问题

日期差值问题

给定两个日期,要求出两个日期相隔的天数,这类问题通常非常麻烦。我们的思路是分别算出两个日期距离公元元年元旦的日期,然后相减。有一个非常简短的代码如下:

将 2 月视为每年的最后一个月,因为只有它的天数不定,这样比较好处理。3~7, 48,...,1014 中任意连续 5 个月内都有 3 个大月,每 5 个月的平均每月天数是 30.6 天。用月份数试乘 30.6 后四舍五入,恰好可以对应从上一个 3 月到每个月 1 日的日期。

我们需要将 \(3,4,5,6,7,\dots,11,12,1,2\) 分别对应为 \(0,1,2,3,4,\dots,8,9,10,11\),只要将月份 \(+9\) 以后模 \(12\) 取余数即可。

时间复杂度为: \(O(1)\)

#include <bits/stdc++.h>
using namespace std;
int calc(int y, int m, int d){
    m = (m + 9) % 12;//3月变为0月
    if (m >= 10) --y;//原1、2月此时变为10、11月,归上一年
    return y*365+y/4-y/100+y/400-y/3200+(m*306+5)/10+d;
}
int main(){
    int y1, m1, d1, y2, m2, d2;
    cin >> y1 >> m1 >> d1 >> y2 >> m2 >> d2;
    cout << calc(y2, m2, d2) - calc(y1, m1, d1);
    return 0;
}

例题:三天打鱼两天晒网

#include <iostream>
int calc(int y, int m, int d) {
	m = (m + 9) % 12;
	if (m >= 10) --y;
	return y*365 + y/4 - y/100 + y/400 - y/3200 + (m*306+5)/10 + d;//包含当天
}
int main() {
	int n, x, y1, y2, m1, m2, d1, d2;
	scanf("%d%d%d%d%d%d", &y1, &m1, &d1, &y2, &m2, &d2);
	n =  calc(y2, m2, d2) - calc(y1, m1, d1);
	x = n/5*3;
	if (n%5 >= 3) x += 3;
	else x += n%5;
	printf("%d %d", x, n-x);
	return 0;
}

基姆拉尔森公式(Kim Larsen)

我们把下一年的 1、2月算成当年的 13 和 14 月,而 3 月当成年头,这样闰年只影响下一年的年头,而不影响当年的日期。

同上面计算日期的公式,只是此处只处理 1、2 月,其余月份保持不变。

由此得到,求 \(y\)\(m\)\(d\) 日是周几的一行代码:

int calc(int y, int m, int d) {
    if (m <= 2) --y, m += 12;
    //y不需要再乘365了,365%7刚好为1
    return (y+y/4-y/100+y/400+(m*13+3)/5+d) % 7 + 1;
}

或者

int calc(int y, int m, int d) {
    (m += 9) %= 12;
	if (m >= 10) --y;
    return (y+y/4-y/100+y/400+(m*306+5)/10+d+1) % 7 + 1;
}
posted @ 2026-01-26 13:48  飞花阁  阅读(1)  评论(0)    收藏  举报
//雪花飘落效果