给定一个
year
、month
(1-12) 和 day
(1-31) 形式的日期,C 或 C++ 甚至 Python 中的什么算法计算星期几(如一个数字)?
下面你会发现我正在使用的手动方法。
我正在尝试编码,但看起来有点复杂。也许很容易把东西放在一起,但我希望期待 C 语言或 C++ 甚至 Python 的详细算法,以便我可以以编程方式可视化这个概念。
详细信息基于年、月、年所使用的算法和代码。 月
奇数天数
一月
3
二月(平日/闰月)
(0/1)
三月
3
四月
2
五月
3
六月
2
七月
3
八月
3
九月
2
十月
3
十一月
2
十二月
3
。闰年: 要检查非百年纪念年是否为闰年,我们将其除以 4。如果余数为 0,则该年为闰年。例如,2016 mod 4 = 0。因此,我们可以安全地推断出 2016 年是闰年。 要检查百年纪念年是否为闰年,我们将其除以 400。如果余数为 0,则该年为闰年。例如,1700 mod 400 = 100。因此,这不是闰年。但是 1600 mod 400 = 0。因此,我们可以安全地推断 1600 是闰年。
不。天数和日期
0 = 太阳
1 = 星期一
2 = 星期二
3 = 星期三
4 = 星期四
5 = 星期五
6 = 星期六
1947 年 8 月 16 日是什么日子? 解决方案:
1600 将有 0 个奇数天。 300年会有1个奇数日。现在,在接下来的 46 年里,我们将有 35 个平年和 11 个闰年。 => 奇数天数 = (35 x 1) + (11 x 2) = 35 + 22 = 57 mod 7 = 1 奇数天 迄今为止奇数天总数 = 1 + 1 = 2 一月奇数天数 = 31 mod 7 = 3 2 月奇数天数(1947 年为非闰年)= 28 mod 7 = 0 3 月奇数天数 = 31 mod 7 = 3 4 月奇数天数 = 30 mod 7 = 2 5 月的奇数天数 = 31 mod 7 = 3 6 月的奇数天数 = 30 mod 7 = 2 7 月的奇数天数 = 31 mod 7 = 3 截至 1947 年 8 月 16 日的奇数天数 = 16 mod 7 = 2 所以,奇数天总数 = 2 + 3 + 0 + 3 + 2 + 3 + 2 + 3 + 2 = 20 mod 7 = 6 因此,1947 年 8 月 16 日是星期六(奇数天 = 6 => 星期六)
您询问的是一种计算给定日期是星期几的算法。
因此,1947 年 8 月 16 日是星期六(奇数天 = 6 => 星期六)
Zeller 的同余式正是您所需要的:
来自免费百科全书维基百科
Zeller 的同余 是 Christian Zeller 在 19 世纪设计的一种算法,用于计算任何儒略历或公历日期的星期几。可以认为是基于儒略日和日历日期之间的转换。
这是我对泽勒同余的 C++ 实现。
int ISO_8601_day_of_week(int const year, int const month, int const day)
{
// ISO week date Day-of-Week d (1 = Monday to 7 = Sunday)
// https://datatracker.ietf.org/doc/html/rfc3339#appendix-B
//
// Zeller's congruence
// The formula used here is adapted from the Common Simplification
// described on Wikipedia:
// https://en.wikipedia.org/wiki/Zeller's_congruence#Common_simplification
//
// That formula produces h between 0 and 6, with 0 = Saturday,
// 1 = Sunday, etc.
//
// A further adjustment converts h into d, an an ISO 8601 week date
// Day-of-Week (1 = Monday to 7 = Sunday).
// https://en.wikipedia.org/wiki/Zeller's_congruence#Formula
//
// The initial adjustment effectively turns the last day
// of February into the last day of the year.
check_date(year, month, day);
int const
y{ month < 3 ? year - 1 : year }, // subtract 12 months
m{ month < 3 ? month + 12 : month }, // add 12 months
q{ day }, // q = day of month
h{ (q + 13 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 }, // 0 to 6 = Saturday to Friday
d{ (h + 5) % 7 + 1 }; // 1 to 7 = Monday to Sunday
return d;
}
函数
void check_date(int const y, int const m, int const d)
验证 y
、m
和 d
,如果它们不形成有效日期,则抛出 std::invalid_argument
对象。为了简洁起见,省略了它的定义。
这是一个简短的驱动程序,我用来演示功能
ISO_8601_day_of_week
。
std::string day_name(int const y, int const m, int const d)
{
switch (ISO_8601_day_of_week(y, m, d))
{
case 1: return "Monday";
case 2: return "Tuesday";
case 3: return "Wednesday";
case 4: return "Thursday";
case 5: return "Friday";
case 6: return "Saturday";
case 7: return "Sunday";
default: return "[unknown]";
}
}
int main()
{
std::cout << "Question: What day of the week was 1947-Aug-16?"
"\nAnswer: " << day_name(1947, 8, 16) << "\n\n";
return 0;
}
输出:
Question: What day of the week was 1947-Aug-16?
Answer: Saturday