历法,是一种推算年、月、 日的时间长度和日历编排规则之间的关系,是指定时间序列的法则。
- 判断闰年
- 今天是星期几
我国的官方历法是目前全球各国通用的 公历,也就是公元纪年。
公历实际上是从 1582 年 10 月 15 日开始实行的格里历(Gregorian Calendar)。
格里历:格里高利历法就是我们通常所说的公历,它是一种源自于西方社会的历法,先在儒略历的基础上加以改革,后由罗马教皇格里高利十三世颁布(当时的法国被罗马统治)。
一年分为 12月,其中一、三、五、七、八、十和十二 是大月,大月的一个月有 31 天。四、六、九和十一是小月,小月的一个月有 30 天。2 月天数有规定,为避免以后再发生春分飘离的现象,改闰年方法为: 凡公元年数能被4整除的是闰年,但当公元年数后边是带两个“0”的“世纪年”时,必须能被400整除的年才是闰年。这就是通常所说的:四年一闰,百年不闰,四百年再闰。根据是否是闰年来定,如果是闰年,2月是 29 天,如果是平常年(不是闰年),2月是 28 天。平常 年一年是 365 天,闰年一年是 366 天。
p.s. 地球绕太阳运转的周期是365.2422天,即一个回归年(Tropical Year),而公历的一年是365天,这样一年就比回归年短了0.2422日,四年积累下来就多出0.9688天(约1天),于是设置一个闰年,这一年多一天。
如此,四个公历年又比四个回归年多了0.0312天,平均每年多0.0078天,这样经过四百年就会多出3.12天,也就是说每四百年要减少3个闰年才行,于是就设置了百年不闰,四百年再闰的俗话。
判断闰年
判断闰年的规则: 不满足(1)、(2)条件的就是平常年
- 如果年份是 4 的倍数,且不是 100 的倍数,则是闰年
- 如果年份是 400 的倍数,则是闰年
按照逻辑直接就可以写出如:
事实上,可以利用条件运算符简化,这很优美以至于会让小白看不出这是判断闰年所以一定函数名一定要见名知意~
bool is_leap_year(int year)
{
return year%(year%100?4:400)?false:true;
}
// 使用 stdbool.h 可以让 _Bool 和 bool 互换,C里面也可以使用 bool, false、true 可以宏定义
您只需要记得,条件运算符在 epx1 ? exp2 : exp3,epx1为真时,就不是整除。
今天是星期几
星期 的命名最早起源于古巴比伦。公元前 7~6 世纪,巴比伦人就使用了星期制,一个星期中的每一 天都有一个天神掌管。这一制度后来传到古罗马,并逐渐演变成现在的星期制度。
星期 是固定的 7 天周期(星期本质就是模运算),其排列顺序固定,不受闰年、平常年以及大小月的天数变化影响。因此,只要确切地知道某一天是星期几,就可以推算出其他日期是星期几。
推算方法 : 计算两个日期之间相差多少天,用相差的天数对 7 取余数,这个余数就是两个日期的星期数的差值。
举个例子,今天是 2019年2月26日 星期二 ,那么 2020年2月26日 是星期几 ??
按照推演,计算 2020年2月26日 和 2019年2月26日 的差是 365天,365 除以 7 余 1(星期差值),所以 2020年2月26日 是星期三。如果大于 2 月那需要 + 1天,因为 2020 是闰年,就是星期四因为 366 % 7 = 2 。
如果计算 2018年2月26日是星期几,那么把差值 1 按减法运算即 -1,有如,星期二 - 1 = 星期一。
此算法的核心 : 求俩个日期之间相隔的天数。我为您安利 4 种,高效准确的。
1. 以 公历的 年 、月份 规则 计算
【 显然... 略 】
2. 以 儒略日 计算
【 一种不记年、月、只记日的历法,一秒钟对应的儒略日差值是 0.0000115740 个儒略日 】
3. 蔡勒(Zeller)公式
【 一种简化闰年规律的公式,适合口算 】
4. say , sir
【 -- xxx年xx月x日 到 yyy年yy月y日相差多少天 ,另外替我谢谢 饼干大佬 这么好的方法 】
儒略日(Julian Day,JD) :儒略日是一种不记年、不记月、只记日的历法,是由法国学者 Joseph Justus Scaliger (1540—1609)在 1583 年提出来的一种以天数为计量单位的流水日历。儒略日和儒略历(Julian Calendar)没有任何关系,命名为儒略日仅仅是因为他本人为了纪念他的父亲——意大利学者 JuliusCaesarScalige(r 1484—1558)。
从公元前4713(公元 -4712)年1月1日UTC12:00 开始所经过的天数,通常记为 JD (***),JD0 就被指定为公元前 4713 年 1 月 1 日 12:00(世界时12点开始的)到公元前 4713 年 1 月 2 日 12:00 之间的 24 小时,以此顺推,每一天都被赋予一个唯一的数字。
e.g. 1977年4月26.4日 UTC12:00 = JD 2443 259. 9
1996年1月 1.0日 UTC12:00 = JD 2450 084. 0
计算两个日期之间的天数,利用儒略日计算也很方便,先计算出两个日期的儒略日数, 然后直接相减就可以得到两个日期相隔的天数。
#include <stdio.h>
bool is_leap_year(int year)
{
return year%(year%100?4:400)?false:true;
}
double JD(int year, int month, int day, int hour, int minute, double second)
{
int a = (14 - month) / 12;
int y = year + 4800 - a;
int m = month + 12 * a - 3;
double jdn = day + (153 * m + 2) / 5 + 365 * y + y / 4;
if ( is_leap_year(year) )
{
if( month <= 2 )
jdn = jdn - y / 100 + y / 400 - 32045.5;
}
else
{
jdn -= 32083.5;
}
// 由于是从中午12:00开始, 计算日期是0:00开始所以要加或减0.5个儒略日
return (jdn + hour / 24.0 + minute / 1440.0 + second / 86400.0) + 0.5;
}
int main( int argc, char *argv[] )
{
int year = 1996;
int month = 1;
int day = 1;
int hour = 0;
int minute = 0;
int secode = 0;
printf("%f\n",JD(year, month, day, hour, minute, secode));
return 0;
}
[ 更新ing ... ]