Cesium中的儒略日JulianDate

在天文和卫星轨道计算中,有关儒略日的计算是一个绕不开的话题。本章阐述下Cesium中有关儒略日的处理方法。

涉及到的时间系统,如UTC,TAI等,这里不再详细阐述,读者自行阅读专业书籍或者网上查询。

Cesium中,使用JulianDate模块来处理儒略日的计算,具体为Cesium软件包目录中的文件:"\Source\Core\JulianDate.js"。

几种时间系统

首先简要阐述下几个不同时间系统的概念。

  1. UTC(coordinated universal time),也称协调时间时。也就是我们现在日常使用的时间。
  2. TAI(International Atomic Time),也称原子时。
  3. DAT,跳秒,或者闰秒,是UTC和TAI之间的差别。
  4. TT(terrestrial time),或者为TDT,也称地球动力学时。
  5. UT1(Universal Time1),也称格林威治平太阳时,在UT0的基础上加入了极移修正。是以地球自转为基准得到的,也是目前使用的世界时标准。

以上几个时间系统中,UT1与地球自转紧密相连,因此不是均匀的。其余诸如UTC,TAI和TT是均匀流逝的,有点像牛顿的绝对时空观里的时间。

不同场合使用不同的时间系统,就像阴历与阳历一样,都是对时间的计数方式而已,我们要弄清楚的就是他们之间的转换关系。

UTC时间与UT1最为接近,且UTC是均匀流逝的,所以UTC作为我们日常使用的时间。但是由于地球的自转速度越转越慢,因此为了协调UT1时间和UTC时间,过个几年会有润秒的出现,即UTC时间减慢一秒,具体可搜索润秒的详细描述,此处不再详述。

下面给出上述几种时间的相互转换关系
U T 1 = U T C + ( U T 1 − U T C ) D A T = T A I − U T C T A I = U T C + D A T T T = T A I + 32.184 s UT1=UTC+(UT1-UTC) \\ DAT=TAI-UTC\\ TAI=UTC+DAT\\ TT=TAI+32.184s UT1=UTC+(UT1UTC)DAT=TAIUTCTAI=UTC+DATTT=TAI+32.184s
上式中,最近的一次跳秒发生在2017年1月1日零时(UTC),因此目前跳秒数DAT为37s。

第一个式子有关UT1的写法可能会感到奇怪。前面说了,UT1的时间流逝是不均匀的,而UTC的时刻我们是知道的,因此IERS公报中给出UTC与UT1的差值:(UT1-UTC),只要将这个差值加上UTC时间即可得到UT1。

儒略日的计算

儒略日(Julian day,JD)是指由公元前4713年1月1日,协调世界时中午12时开始所经过的天数,当然这个天数是包含小数点的。显然,儒略日使用自然累加的天数作为时间的计时方式,是一种均匀流逝的绝对时间。

儒略日的计算涉及到闰年、闰月的处理,计算公式各种程序语言版本的都有。读者可参考书籍中的算法》

注意,儒略日的计算公式只涉及到年月日时分秒的计算,并不管是UTC还是TAI时间。当是TAI时间时,则计算得到的儒略日是正确的;而当是UTC时间时,因为有跳秒的存在,计算得到的儒略日就是“假的”,因此需要主动加上跳秒。

例如:
UTC时间:2020年9月5日12:00:00s,对应的TAI时间为2020年9月5日12:00:37s。
因为我们知道,自2017年1月1日00:00:00s,跳秒为37s。

所以说,给定UTC时间,在转换为TAI时间时,必须知道跳秒数,即前面提到的 D A T DAT DAT
Cesium中,JulianDate模块中,维护了历次跳秒的时刻及跳秒数的数表(见下),在计算UTC向TAI转换时,需要查这个表,以便判断对应的跳秒数。

JulianDate.leapSeconds = [
  new LeapSecond(new JulianDate(2441317, 43210.0, TimeStandard.TAI), 10), // January 1, 1972 00:00:00 UTC
  new LeapSecond(new JulianDate(2441499, 43211.0, TimeStandard.TAI), 11), // July 1, 1972 00:00:00 UTC
  new LeapSecond(new JulianDate(2441683, 43212.0, TimeStandard.TAI), 12), // January 1, 1973 00:00:00 UTC
  new LeapSecond(new JulianDate(2442048, 43213.0, TimeStandard.TAI), 13), // January 1, 1974 00:00:00 UTC
  new LeapSecond(new JulianDate(2442413, 43214.0, TimeStandard.TAI), 14), // January 1, 1975 00:00:00 UTC
  new LeapSecond(new JulianDate(2442778, 43215.0, TimeStandard.TAI), 15), // January 1, 1976 00:00:00 UTC
  new LeapSecond(new JulianDate(2443144, 43216.0, TimeStandard.TAI), 16), // January 1, 1977 00:00:00 UTC
  new LeapSecond(new JulianDate(2443509, 43217.0, TimeStandard.TAI), 17), // January 1, 1978 00:00:00 UTC
  new LeapSecond(new JulianDate(2443874, 43218.0, TimeStandard.TAI), 18), // January 1, 1979 00:00:00 UTC
  new LeapSecond(new JulianDate(2444239, 43219.0, TimeStandard.TAI), 19), // January 1, 1980 00:00:00 UTC
  new LeapSecond(new JulianDate(2444786, 43220.0, TimeStandard.TAI), 20), // July 1, 1981 00:00:00 UTC
  new LeapSecond(new JulianDate(2445151, 43221.0, TimeStandard.TAI), 21), // July 1, 1982 00:00:00 UTC
  new LeapSecond(new JulianDate(2445516, 43222.0, TimeStandard.TAI), 22), // July 1, 1983 00:00:00 UTC
  new LeapSecond(new JulianDate(2446247, 43223.0, TimeStandard.TAI), 23), // July 1, 1985 00:00:00 UTC
  new LeapSecond(new JulianDate(2447161, 43224.0, TimeStandard.TAI), 24), // January 1, 1988 00:00:00 UTC
  new LeapSecond(new JulianDate(2447892, 43225.0, TimeStandard.TAI), 25), // January 1, 1990 00:00:00 UTC
  new LeapSecond(new JulianDate(2448257, 43226.0, TimeStandard.TAI), 26), // January 1, 1991 00:00:00 UTC
  new LeapSecond(new JulianDate(2448804, 43227.0, TimeStandard.TAI), 27), // July 1, 1992 00:00:00 UTC
  new LeapSecond(new JulianDate(2449169, 43228.0, TimeStandard.TAI), 28), // July 1, 1993 00:00:00 UTC
  new LeapSecond(new JulianDate(2449534, 43229.0, TimeStandard.TAI), 29), // July 1, 1994 00:00:00 UTC
  new LeapSecond(new JulianDate(2450083, 43230.0, TimeStandard.TAI), 30), // January 1, 1996 00:00:00 UTC
  new LeapSecond(new JulianDate(2450630, 43231.0, TimeStandard.TAI), 31), // July 1, 1997 00:00:00 UTC
  new LeapSecond(new JulianDate(2451179, 43232.0, TimeStandard.TAI), 32), // January 1, 1999 00:00:00 UTC
  new LeapSecond(new JulianDate(2453736, 43233.0, TimeStandard.TAI), 33), // January 1, 2006 00:00:00 UTC
  new LeapSecond(new JulianDate(2454832, 43234.0, TimeStandard.TAI), 34), // January 1, 2009 00:00:00 UTC
  new LeapSecond(new JulianDate(2456109, 43235.0, TimeStandard.TAI), 35), // July 1, 2012 00:00:00 UTC
  new LeapSecond(new JulianDate(2457204, 43236.0, TimeStandard.TAI), 36), // July 1, 2015 00:00:00 UTC
  new LeapSecond(new JulianDate(2457754, 43237.0, TimeStandard.TAI), 37), // January 1, 2017 00:00:00 UTC
];

JulianDate的结构和计算

Cesium中,使用JulianDate模块包含了相关的计算函数。
可以使用构造函数可以创建一个JulianDate对象,对象内部仅包含两个属性,且仅对应TAI时间:

  • dayNumber: 保留儒略日的整数部分,单位为天;
  • secondsOfDay:保留儒略日的小数部分,单位为秒;

之所以用两个参数来表示儒略日,是为了最大可能的保证数据的精度。例如J2000时刻,儒略日为2451545天。光整数天就需要7位有效数字,如果表示到1ms的精度,则儒略日为:2451545.00000001天,可以看出超出了一般双精度15位有效数字。因此使用内部使用整数天和不足一天的秒数来保存,从而保证了儒略日数据的精度。

直接的构造函数如下:

function JulianDate(julianDayNumber, secondsOfDay, timeStandard) 

其中,timeStandard表示时间类型,只有两种选择:UTC和TAI。没有则默认为UTC。当为UTC类型时,构造函数内部需要将UTC时间转换为TAI时间(涉及到跳秒数表的查询)。

其它的构造函数有:JulianDate.fromGregorianDate、JulianDate.fromDate等。

下面给出了使用两种构造函数创建JulianDate对象的代码例子:

//  使用ES6 module, 引用Cesium代码包里的源代码文件
import JulianDate from "../Source/Core/JulianDate.js";
import GregorianDate from "../Source/Core/GregorianDate.js";

//  使用GregorianDate时间类型创建,默认为UTC时间
var jd1 = JulianDate.fromGregorianDate(new GregorianDate(2020,9,5,0,0,0,0));
console.log(jd1);

//  直接使用儒略日的整数天和一天内的秒数创建,默认为UTC时间
var jd2 =new JulianDate(2459097, 43200.0);
console.log(jd2);

/*  输出都是(TAI时间):
JulianDate {dayNumber: 2459097, secondsOfDay: 43237}
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值