Julian Day Number
跳到导航
跳到搜索
任何操作系统都需要“时间”格式。 对于操作系统何时开始测量“时间的开始”,似乎没有真正的标准。 但事实上,有一个接近标准。
基本定义
天文学中有一种测量时间的方法,叫做儒略日数(Julian Day Number-JDN)。 出于历史日历系统的原因,它从UTC正午(公元前4713年1月1日)开始测量时间,并使用浮点值以天为单位测量时间。 因为它是一种标准,所以有代码可用于将JDN转换为日历日期。
在任何情况下,一旦从任何自定义时间格式中划分出秒和秒的分数,就剩下“天”。 这意味着你的数字和儒略日数字之间的差异只是一个一天内的偏差。 当然,也就可以可以截断JDN,并将其用作整数。
日期计算
公元2000年的JDN为2451545。 如果你假装有一个“公元前0年”(或者说公元前1年),那么那一年的1月1日就是JDN 1721060。
计算(标准)公历日期:400年正好有146097天。
计算闰年:如果一年是4的倍数,那么它就是闰年,除非它恰好是一个新世纪,不能除以400。
代码示例
uint32_t days2years[401];
#define LEAP_FLAG 0x80000000
//days2years表涵盖400年,包括:
//1)年初的天数
//2)“世纪”(year/100)向上移动了24位
//3)闰年标志
void BuildDaysTbl()
{
int i;
int j = 0;
uint32_t days = 366;
days2years[0] = LEAP_FLAG;
while (days < 0x40000000)
{
i = 24;
while (--i >= 0)
{
days2years[++j] = days;
days += 365;
days2years[++j] = days;
days += 365;
days2years[++j] = days;
days += 365;
days2years[++j] = days | LEAP_FLAG;
days += 366;
}
days2years[++j] = days;
days += 365;
days2years[++j] = days;
days += 365;
days2years[++j] = days;
days += 365 + 0x10000000;
days2years[++j] = days;
days += 365;
}
}
//将儒略日转换为公历年,并带有“余数”和闰年标志
// outputs: *doy = day of year (jan 1 = 0) with leapyear flag, *cent = century AD
uint32_t JDN_to_GregYear(uint32_t jdn, uint16_t *doy, uint32_t *cent)
{
uint32_t greg_yr = 0;
uint32_t qcen, temp, temp2;
temp -= 1721060; // make temp align with jan1, "year 0" quadcentury boundary
qcen = temp / 146097; // 400 years contain 146097 days
temp %= 146097; // get the remainder days within the 400 yr span
temp2 = temp; // save a copy
// do an approximate conversion to years -- sometimes one too low
if (temp > 73048) // calculation for years 200 to 399
{
temp -= 73048; // this shifts the calculation by 1 day
greg_yr= 200;
}
greg_yr += (temp << 10) / 374014; // 374014 is a magic number
if ((days2years[greg_yr + 1] & 0xfffffff) <= temp2) // fix if greg_yr is off by 1
++greg_yr;
temp = days2years[greg_yr];
*doy = (uint16_t) (temp2 - (temp & 0xfffffff));
*cent = ((temp & 0x30000000) >> 24) + qcen * 4;
if ((int32_t) temp < 0)
*doy |= 0x8000; // set the leapyear flag on "day of year"
return greg_yr;
}
// convert Jan 1 of a Gregorian year to a Julian day #
// "sign" bit of the return value is set on a leap year
uint32_t GregYear_to_JDN(uint32_t greg_yr)
{
uint32_t jdn = (greg_yr / 400) * 146097; // convert quadcenturies to days
uint32_t temp = greg_yr % 400;
// add in the days from the remaining years, and adjust jan1, "year 0" to actual JDN
jdn += (days2years[temp] & 0xfffffff) + 1721060;
jdn |= days2years[temp] & 0x80000000; // copy the leap year bit
return jdn;
}