通用时与儒略日的转换代码解析

在GPS学习时,接触到儒略日,通用时,和GPS时。得知,时间的算法远比我们普通推理天更麻烦

1介绍

儒略日

是一个不涉及年月等概念的长期连续的记日法,在天文学,空间大地测量和卫星导航定位种经常使用。 儒略日的起点定在公元前4713年(天文学上记为-4712年)1月1日世界时12:00 即 JD 0 ,国际时长的24小时 TU24 为1天 即 JD 1(4713BC1月1日12:00到4713BC1月2日12:00)

而此时儒略日的规则时 分平年和闰年 每4年一闰 平年365 闰年366

直到1582年10月4结束 开始用格力高历,就是现在的公历

规则 每4年一闰, 百年不闰,400又闰。

但是格力高历其实抹掉了10天(1582,10月4 下一日直接跳到10月15日)

GPS时

GPS系统内部采用的时间系统是GPS时间,是以1980年1月6日为起点,用周数(一个星期7天)和周数中的秒计算。

各个时间的想换转换都有严格的转换公式,其转换的主要思想是把通用时,GPS时间转换为儒略日,然后以儒略日为媒介,实现任意两个时间系统的相互转换

2代码展示

GPS转换为儒略日

void GPSTimeToJulianDay(PGPSTIME pgt,PJULIANDAY pjd)//GPS时到儒略日的转换//GPS系统内部采用得时间系统时GPS时间,是以1980年1月6日子夜为起点,用周数和周内描述来表示{ pjd->day=int(pgt->wn*7+double(pgt->tow.sn)/86400.0+2444244.5); pjd->tod.sn=(pgt->tow.sn+43200)%86400; pjd->tod.tos=pgt->tow.tos;}

这个代码应该比较容易理解

pgt->wn 周数 *7为从19801月6日的周天数

pgt->tow.sn / 86400 类比 一周内已经走的秒数 除以 每天24 * 60 *60 的秒数

取整的到这个星期周数已经走的天数

取整得到当天州走的秒数

pgt->tow.tos 秒数的小数点位

公式中 2444244.5 为 1980 1月 6日的 儒略日天数 类比 JD 2444244.5

儒略日转通用时

void JulianDayToCommonTime(PJULIANDAY pjd,PCOMMONTIME pct)//儒略日到通用时的转换{ double x=pjd->day+(pjd->tod.sn+pjd->tod.tos)/(60.0*60.0*24); int a=int(x+0.5); int b=a+1537; int c=int((b-122.1)/365.25); int d=int(365.25*c); int e=int((b-d)/30.6001); pct->day=b-d-int(30.6001*e); pct->month=e-1-12*int(e/14); pct->year=c-4715-int((7+pct->month)/10); pct->hour=(pjd->tod.sn/3600+12)%24; pct->minute=(pjd->tod.sn%3600)/60; pct->second=pjd->tod.sn%60+pjd->tod.tos; //int N=a%7; //std::cout<<pct->year<<” “<<pct->month<<” “<<pct->day<<” “<<pct->hour<<“:”<<pct->minute<<“:”<<pct->second<<std::endl;}

在计算儒略日转通用时前,先了解通用时是怎么转儒略日,然后再反推

计算儒略日就是计算日的集和,计算前提为 -4712年1月1日以后的到1582年10月4日以前,儒略日的计算公式为:

JD = int(365.35*(y+4712)) + int(30.61*(m+1))+d -63.5

y为年 m为月 d为号

首先年得计算都时天文纪年法 也就是说公元前4713就是-4712

闰年: 年积日 = int(365.25*(y+4712))

平年: 年积日 = int(365.25*(y+4712))+1

月的积日计算,当把所有得2月份都当作只有28天时发现一个规律

当月份m <= 2 时 可以将上一年得13月和14月 当然尽在月份这么计算将年数-1,把一个年得月份添加到13 或这14 再利用这个公式计算出来的天数也是正确的int(30.61*(m+12)) -63; y =y-1当月份m > 2时 天数闰年:int(30.61*(m+1))-63 + 1平年:int(30.61*(m+1)) – 63

最后日得计算 因为儒略日是从-4712年1月1日平午12:00开始计算积累,-4712年1月2日为0.5日 所以

日得积日 = d – 1.5

​ 可以发现无论Y是平年还是闰年就按日的公式(该公式使用图1582年前的计算,因为再后面改用格力高历也就是通用时间)

​ JD=int(365.25*(y+4712)) + int(30.61*(m+1)) + d – 63.5 //该公式始终成立

格里高历每百年不能被400整除则不闰,按照之前的年积日计算就是把1582年之后的不需要闰的年份也给闰了,随意得除掉这部分

//这里公式采用了取巧得办法 1580年后,到目前2000后,百年未有大变化之下。

1600 1700 1800 1900 2000 本不能被闰 其1600 2000 能被400 整除 也就是数多出了3天的闰年时间。

月得积日计算完全一致

日的积日计算:格里高历就是目前得通用公历 是从1582年10月15日开始计算的,按照上面的计算方法相当于格里高历多计算10天所以减去10天 所以积日计算为(2000-2100年)

日的积日 = d- 1.5 -10 -3

代码中年份 -4715,其他的文章都写得是4716年

这里得16年解释 在计算4712年1月2月(1月为上一年的13月)的是时候,年份会变成-4713年的,如果加上4712会出现负数。所以不能是4712,那么4713行不行,这里好多文章都解释平均年是365.25天。年份的加数必须是4的倍数,可以是4716 或者 4720。所加的天数在后面减掉 4 *365.25.

公历一年实际只有365日,需在某月中减去一天,而公历设在二月。这时,3~12月份仍然是有规律的(大小月相隔),1月有31天,2月有29天。如此,可假设以3月份作为岁首,2月为年尾。则在2月减去的一天可理解为上年岁末(即今年岁首前)少一天。并以13、14月表示上一年的1、2月(即一年只有3~14月)。则每年仍然是单数月31天,双数月为30天,且岁首(M=3)仍为大月,则仅需令上式再减1(2月少一天)。计算M月的积日,则有:int(30.5*M)-31(M>2)

而此时为什么是4715不是4716呢,这就是涉及月的计算。为了保证 M>2 那么m+12 >2 的式子永远成立,只需要 y -1 .所以

JD=int(365.25(y+4716 -1)) + int(30.61(m+1+12)) + d – 63 -4365.25- 10 -3
JD=int(365.25(y+4716 -1)) + int(30.61*(m+1+12)) + d – 1537**

而在代码中

*121.1由来,是因为儒略日的计算时间在4716年的3月1日 3月的i计算(m+1)30.61
并且时间从12:00改为 00:00
日的积日 d = 121-0.5

//这里121.1有点强行解释的感觉,搜了很多的解释,基本没有讨论到日的积日变化。大多数文章还是复制。主要的难点是代码中1537的由来 和 121的由来。其他的在别的文章都有解释。其实时间的计算可以有很多其他的方式,我只是刚好觉得这个解释起来最简单。也不需要带入很大的JD数。

此片参考两位的文章,让我更好理解时间的转换。如果哪位有更好的解释,希望私信。、

儒略日与公历转换

https://blog.csdn.net/weixin_42763614/article/details/82880007

对儒略日计算公式的解读

http://blog.sina.com.cn/s/blog_71e5888f0102wzmh.html