提问人:Nare Avetisyan 提问时间:11/8/2023 最后编辑:Nare Avetisyan 更新时间:11/10/2023 访问量:100
计算自特定日期未按预期工作以来的天数
Calculating number of days since a particular date not working as expected
问:
我用 C 语言编写了一个函数来计算自 2000 年 1 月 1 日以来已经过去了多少天。但是,它在某些年份无法正常工作(例如,它适用于 2020 年 5 月 5 日,但不适用于 2029 年 5 月 5 日)。对于某些年份,它正确地确定了天数,对于其他年份,它减少了一天,对于某些年份,它减少了两到三天。代码的哪一部分可能导致此问题?
bool isLeapYear(int y) {
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
return true;
else
return false;
}
int days_since(int y, int m, int d)
{ int m_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int leap_count = 0;
int years_index = y-2000;
for (int i=2001; i<=y; i++){
if(isLeapYear(i))
leap_count ++;
}
int add_years = 366 * (leap_count) + 365 * (years_index-leap_count);
int add_months = 0;
if (isLeapYear(y))
m_days[1] = 29;
for (int i=0; i<m-1; i++)
add_months += m_days[i];
int add_days = d-1;
int total_days = add_years + add_months + add_days;
return total_days;
}
答:
2赞
chux - Reinstate Monica
11/9/2023
#1
在年中处理 2 月 29 日是一件痛苦的事情,OP 的代码在这方面也有问题。
我没有看到 OP 代码的简单修复。
相反,将闰日移到年底,将 3 月定为第一个月,将 1 月/2 月定为上一年的最后一个月。这就是罗马人所做的,然后第 8 个月是 10 月 ober,第 10 个月是 12 月余烬。通过在年底放置闰日关注点,这简化了许多代码。
请注意,闰年和非闰年是相同的,闰年的计算很简单。days_since_March1[]
#include <assert.h>
#define JANUARY 1
#define MARCH 3
#define DECEMBER 12
#define MONTHS_PER_YEAR 12
#define GREGORIAN_FIRST_FULL_YEAR 1583
#define EPOCH_2000Jan1 730426
int days_since2000Jan1(int y, int m, int d) {
assert(y >= GREGORIAN_FIRST_FULL_YEAR);
assert(m >= JANUARY && m <= DECEMBER);
if (m < MARCH) {
m += MONTHS_PER_YEAR;
y--;
}
int months_since_March = m - MARCH;
static const short days_since_March1[12] = {0, 31, 61, 92, 122, 153, 184, 214,
245, 275, 306, 337};
return y * 365 + y / 4 - y / 100 + y / 400
+ days_since_March1[months_since_March] + d - EPOCH_2000Jan1;
}
评论
0赞
chux - Reinstate Monica
11/9/2023
对于那些喜欢限制较少的月份和公式与表格的人:int days_since2000Jan1(int y, int m, int d) { assert(y >= GEGORIAN_FIRST_FULL_YEAR); y += m / MONTHS_PER_YEAR; m %= MONTHS_PER_YEAR; while (m < MARCH) { m += MONTHS_PER_YEAR; y--; } int days_since_March1 = (979 * m - 2919) >> 5; // About 30.6 days/month return y * DAYS_PER_COMMON_YEAR + y / 4 - y / 100 + y / 400 + days_since_March1 + d - EPOCH_2000Jan1; }
1赞
Fe2O3
11/9/2023
有没有办法用这些填充数组,然后将好日子和坏日子分开?:-)
1赞
chux - Reinstate Monica
11/9/2023
@Fe2O3,好日子
0赞
Fe2O3
11/9/2023
我遇到过一些蛋白石矿工,他们不同意那篇文章的前提,或者至少是标题......:-)
评论
isLeapYear()
for (int i=2001; i<=y; i++)
for (int i=2000; i<y; i++)