如何计算两日期相差的天数?

今天讲的日期是公历日期,农历日期由于涉及到朔望月等较为高深的内容,暂时已经超出了本人的能力范围,故先不探讨。

现行的公历随月份及年份天数不同,如何计算两个日期之间相隔多少天?

这里,介绍一种天文上常用的儒略日,并介绍儒略日与公历的相互转换方法,附上相应的R语言程序。

儒略日是天文上常用的一种计时方法,从公元前4713年1月1日格林尼治平太阳间正午12点开始,每增加一天,儒略日增加1,一直向下累加。(以下内容改写自维基百科)

儒略日是法国学者Joseph Justus Scliger(1540-1609)为纪念他的父亲Julius Caesar Scaliger(1484-1558)在1583年提出来的。   
儒略日的起点确定考虑了太阳、月亮的运行周期,以及古罗马税收的间隔。

Joseph Scliger定义儒略周期为7980年,是因28、19、15的最小公倍数,28×19×15=7980。
其中:

  • 28年为一太阳周期(solar cycle),经过一太阳周期,则星期的日序与月的日序会重复。   

  • 19年为一太阴周期,或称默冬章(Metonic cycle),因235朔望月=19回归年,经过一太阴周期则阴历月年的日序重复。

  • 15年为一小纪(indiction cycle),此为罗马皇帝君士坦丁(Constantine)所颁,每15年评定财产价值以供课税,是古罗马用的一个纪元单位,故以7980年为一儒略周期,而所选的起点公元前4713年,则是这三个循环周期同时开始的最近年份。

在中国科学院紫金山天文台编纂的《中国天文年历》上,有相应年份逐日的儒略日表,可供参考。

还是回到原来的问题,如何计算公历中两个日期相差的天数?办法之一,就是将二者都转换成儒略日,计算其差值。实际上,天文学家也是依靠儒略日来计算天体动态的。

下面是已知日期计算儒略日和已知儒略日计算日期的方法。用R语言写成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
### 已知日期计算儒略日
### y 年 m 月 d日

date2jd <- function(y,m,d){
n=0
G=0
if(y*372+m*31+floor(d)>=588829){
G=1
}
if(m<=2) {
m = m +12
y = y -1
}

if(G) {
n=floor(y/100)
n=2-n+floor(n/4)
}

res <- floor(365.25*(y+4716)) + floor(30.6001*(m+1)) + d + n - 1524.5
return(res)
}

### 已知儒略日,计算日期的公式
###

jd2date <- function(jd){
### 转换日期格式
### 已知儒略日,用jd2date求得到日期,变为年,月,日
jdate2vect <- function(xxx){
year = xxx[[1]]
month = xxx[[2]]
day <- xxx[[3]]
frac <- xxx[[6]]/(60*60*24)+xxx[[5]]/(60*24)+xxx[[4]]/24
day.dec <- day + frac
res <- c(year, month, day.dec)
names(res) <- c("Year","Month","Day")
return(res)
}

D = floor(jd+0.5)
F= jd+0.5-D
if(D>=2299161) {
c = floor((D-1867216.25)/36524.25)
D = D + 1+c-floor(c/4);
}

D = D + 1524;
r.Y = floor((D-122.1)/365.25);
D = D - floor(365.25*r.Y);
r.M = floor(D/30.601);
D = D- floor(30.601*r.M);
r.D = D;

if(r.M>13){
r.M=r.M - 13
r.Y=r.Y - 4715;
}else{
r.M =r.M - 1
r.Y = r.Y- 4716
}
F= F*24;
r.h=floor(F);
F= F -r.h;
F = F * 60;
r.m=floor(F);
F= F - r.m;
F = F * 60;
r.s=F;
res <- list(r.Y, r.M, r.D, r.h, r.m, round(r.s,2))
names(res) <- c("Year","Month","Day","Hour","Minute","Second")
return(jdate2vect(res));

}

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# ## date2jd 举例
#
# ## 求2010年9月21日与1980年1月1日相差的天数
date2jd(2010,9,21) - date2jd(1980,1,1)
# 结果:11221天
#
# ## 求2035年9月2日北京日全食距离现在的天数
date2jd(2035,9,2) - date2jd(2010,9,21)
# 结果:9112天
#
# ## 求美国独立距离现在的天数
date2jd(2010,9,21) - date2jd(1776,7,4)
# 结果:85545天

# ## 求公元前841年1月1日(西周共和元年)距离现在的天数
date2jd(2010,9,21) - date2jd(-841,1,1)
# 结果:1041578 天

# ## 儒略日转年月日举例
# #已知儒略日为2455230.5,求其对应的公历日期。
jd2date(2455230.5)
#
# 结果:
# Year Month Day
# 2010 2 3
# 是2010年2月3日。