17

我需要jday在 javascript 中计算,以进行客户端验证,任何人都可以帮助我如何JDAY在 javascript 或脚本中计算以将给定的 JDAY 更改为实际日期,反之亦然。

要知道什么是 JDay,我找到了以下站点,

http://www.pauahtun.org/Software/jday.1.html

我还参考下面的站点进行计算,这是在 JAVA 中提到的

http://www.rgagnon.com/javadetails/java-0506.html

先感谢您

4

8 回答 8

31

朱利安日

儒略是自 7980 年周期开始以来经过的天数。

该系统由 Joseph Scaliger 于 1583 年发明,其目的是使计算一个日历日期与另一个日历日期之间的整数(整数)差异变得容易。

7980 年周期是通过结合几个传统时间周期(太阳、月球和特定的罗马税收周期)得出的,其中 7980 是一个公倍数。

第一个儒略周期的起点开始于公元前 4713 年 1 月 1 日格林威治标准时间中午,并将于格林威治标准时间 3268 年 1 月 22 日中午结束,整整 7980 天之后。

例如,2016 年 1 月 1 日的儒略日数是 2,457,389,这是自公元前 4713 年 1 月 1 日那天以来的天数。

如何计算它

我们知道 Unix 时间是自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数,不包括闰秒,也称为 Epoch,当我们已经拥有 Unix 时,我们可以使用一些数学来计算儒略日时间。

GMT 和 UTC 在实践中共享相同的当前时间,因此对此应该没有区别。

首先,我们需要知道从儒略周期开始到 Unix 时间戳开始的天数。
换句话说,从 4713 年 1 月 1 日 12:00:00 GMT 到 1970 年 1 月 1 日 00:00:00 UTC 的天数。

有了这个永远不会改变的固定天数,我们可以添加从 1970 年 1 月 1 日到今天的天数,这是 Javascript 无论如何返回的,以获得儒略日。

没有把这些年加起来,只是通过搜索网络,它告诉我们公元前 4713 年和公元 1970 年之间的天数相差 2440588 天,因为儒略循环是在中午开始的,而不是在午夜,我们必须正好减去半天,就是 2440587.5 天。

所以我们现在拥有的是2440587.5 days + UNIX TIME in days === Julian Day

通过一些简单的数学运算,我们可以算出一天有 86,400 秒长,而使用 Javascript 时 Unix 时间戳以毫秒为单位,因此UNIX TIME / 86400000我们可以得到从 1970 年 1 月 1 日星期四到今天的天数。

现在只是一天,我们想要整数天数,而不是小数,并且可以将它向下舍入到全天结束,做类似的事情

Math.floor((UNIX TIME / 86400000) + 2440587.5);

朱利安日期

有时在编程中,“朱利安日期”表示自一年开始以来的天数,例如 2016 年 6 月 1 日将是该年的 152 天等。

“儒略日”的正确用法是儒略日,其中添加了时间戳作为一天的小数部分。

以这个答案顶部的例子为例,2016 年 1 月 1 日是儒略日 2,457,389 ,我们可以添加一个时间。
儒略日从中午开始,没有添加小数时间,因此在午夜将是2457389.518:00,或中午后六个小时,它将是2457389.25,添加“半天”、“四分之一天”等.

重新计算一下

这意味着 0.1 Julian Date 等于 24 小时除以 10,或者24 / 10 === 2.4 hours,或者换句话说,Julian Day 时间戳是带有小数的分数(一天的十分之一等)

让我们看一些 Javascript 函数,首先是Date构造函数。

Javascript 只能访问它运行的计算机上的本地时间,因此当我们这样做时,new Date()它不一定会创建 UTC 日期,即使 UNIX 时间是 UTC,也会new Date为您提供从纪元到您的计算机本地时间的秒数有,并且不考虑您的时区。

然而,Javascript 确实有Date.UTC,它将以 UTC 格式返回日期,让我们检查差异,这当然会根据您设置本地系统的时区而有所不同。

var regular_date = new Date(2016, 1, 1, 0, 0, 0);
var UTC_date     = Date.UTC(2016, 1, 1, 0, 0, 0);
var difference   = UTC_date - regular_date;

document.body.innerHTML = 'The difference between your local time and UTC is ' +(difference/1000)+ ' seconds';

记住本章开头的部分,大约 0.1 Julian Date 等于 24 小时除以 10,或者24 / 10 === 2.4 hours,嗯,2.4 小时是 144 分钟,现在让我们快速看一下 JavascriptsgetTimezoneOffset()方法,文档说

getTimezoneOffset() 方法返回当前语言环境与 UTC 的时区偏移量(以分钟为单位)。

因此,它以分钟为单位返回系统时区的偏移量,这很有趣,因为大多数处理日期的 javascript 方法都返回毫秒。

我们知道一天的 1/10 是 144 分钟,所以 10/10 或一整天是 1440 分钟,所以我们可以使用一些数学来抵消本地系统时区,以分钟为单位,然后除以一天中的分钟数,以获得正确的小数值

所以现在我们有

2440587.5 days + UNIX TIME in days === Julian Day

我们知道 Javascripts Date 构造函数并没有真正使用当前日期的UTC,而是系统时间,所以我们必须有

TIMEZONEOFFSET / 1440

将它们结合在一起,我们会得到

(JAVASCRIPT TIME / 86400000) - (TIMEZONEOFFSET / 1440) + 2440587.5
//  ^^ days since epoch ^^      ^^ subtract offset ^^    ^^days from 4713 B.C. to 1970 A.D.

将其翻译为 javascript 将是

var date = new Date();     // a new date
var time = date.getTime(); // the timestamp, not neccessarely using UTC as current time

var julian_day = (time / 86400000) - (date.getTimezoneOffset()/1440) + 2440587.5);

现在这也是我们应该用来获取儒略的方法,采取措施去除时区偏移,当然也没有儒略的小数部分。
我们将通过将其向下舍入到最接近的整数来做到这一点

var julian_date = Math.floor((time / 86400000) - (date.getTimezoneOffset()/1440) + 2440587.5));

现在是我对这个问题的原始回答的时候了,在我在评论字段中提出投诉之后,我进行了这个非常长的编辑来解释为什么这是正确的方法。

Date.prototype.getJulian = function() {
  return Math.floor((this / 86400000) - (this.getTimezoneOffset() / 1440) + 2440587.5);
}

var today = new Date(); //set any date
var julian = today.getJulian(); //get Julian counterpart

console.log(julian)
.as-console-wrapper {top:0}

小数部分也一样

Date.prototype.getJulian = function() {
  return (this / 86400000) - (this.getTimezoneOffset() / 1440) + 2440587.5;
}

var today = new Date(); //set any date
var julian = today.getJulian(); //get Julian counterpart

console.log(julian)
.as-console-wrapper { top: 0 }

最后,举个例子说明原因

new Date().getTime()/86400000 + 2440587.5

不起作用,至少如果您的系统时间设置为具有偏移的时区,即除 GMT 以外的任何时间

// the correct approach
Date.prototype.getJulian = function() {
    return (this / 86400000) - (this.getTimezoneOffset() / 1440) + 2440587.5;
}

// the simple approach, that does not take the timezone into consideration
Date.prototype.notReallyJulian = function() {
  return this.getTime()/86400000 + 2440587.5;
}
// --------------

// remember how 18:00 should return a fractional 0.25 etc
var date = new Date(2016, 0,    1,   18,   0,   0,    0); 
//                   ^    ^     ^     ^    ^    ^     ^
//                 year  month date  hour min  sec  milli
                   
var julian = date.getJulian();       //get Julian date
var maybe  = date.notReallyJulian(); // not so much

console.log(julian); // always returns 2457389.25
console.log(maybe);  // returns different fractions, depending on timezone offset
.as-console-wrapper { top: 0 }

于 2012-08-01T13:16:04.167 回答
14

new Date().getTime()/86400000 + 2440587.5 将得到unix时间戳,将其转换为天并添加1970-01-01的JD,即unix时间戳的纪元。

这就是天文学家所说的朱利安日期。它定义明确。由于 Unix 时间戳和 JD 都没有考虑闰秒,因此不会降低准确性。请注意,JD 不必在时区 UTC(但通常是)。这个答案为您提供时区 UTC 的 JD。

于 2012-08-01T13:13:54.840 回答
6

根据维基百科

a = (14 - month) / 12
y = year + 4800 - a
m = month + 12a - 3
JDN = day + (153m + 2) / 5 + 365y + y/4 - y/100 + y/400 - 32045

如果您对实施有更具体的问题,请在问题中提供这些详细信息,以便我们提供进一步帮助。

注意:这是不正确的,因为这里忘记了 Wiki 上的“地板括号”。

正确的公式是:

a = Int((14 - Month) / 12)
y = Year + 4800 - a
m = Month + 12 * a - 3
JDN = Day + Int((153 * m + 2) / 5) + 365 * y + Int(y / 4) - Int(y / 100) + Int(y / 400) - 32045
于 2012-08-01T13:13:52.637 回答
2

京东 =>

const millisecondsSince1970Now = new Date+0
const julianDayNow = 2440587.5+new Date/864e5
const dateNow = new Date((julianDayNow-2440587.5)*864e5)

关于儒略日是什么以及如何计算似乎存在混淆。

Javascript 时间以 GMT/UTC 毫秒 UInt64 为单位,从Jan 1, 1970 at midnight.

JavaScript 函数的月、日、年方面Date都是使用公历规则实现的。但朱利安“日子”不受此影响;但是将“天数”映射到儒略月、日、年。

因此,计算儒略日转换是从该时间点(1970 年 1 月 1 日 GMT/UTC 公历)开始的相对天数。

Julian-DayJan 1, 19702440587.5(0.5,因为 JulianDays 从中午开始)。

864e5常量是 JavaScript 表示法(86,400,000毫秒/天)。

唯一的复杂性是在采用 1582 年公历之前计算儒略日期(天),教皇格列高利要求的更改是为了纠正影响复活节的闰年漂移不准确。直到 1752 年左右,它才在世界上大多数使用儒略历系统或派生系统的国家得到完全采用(俄罗斯和中国一直到 20 世纪)

而在朱利叶斯凯撒的 46BC “改革”任务中,朱利安日期实施的前 60 年中更严重的错误是牧师犯了错误,人们在折叠 14/15 月日历时被误解了。(因此那个时期的许多宗教日期和时间都有错误)

这些都不适用于 Julian Day 值的 JavaScript 计算。

另请参阅:(来自 AfEE EdgeS/EdgeShell 脚本核心说明)

有一个单独的微妙“闰秒”适用于天文计算和与地球轨道路径和旋转漂移有关的原子钟的使用。

即,86,400.000每天的秒数需要“调整”以保持日历(时区、GPS 卫星)与当前同步86,400.002

于 2020-10-30T20:51:28.477 回答
1

似乎接受的答案中给出的最终代码是错误的。查看美国海军天文台网站上的“官方”在线计算器:

http://aa.usno.navy.mil/data/docs/JulianDate.php

如果有人知道答案时间和日历的正确答案,那就是 USNO。

于 2017-03-27T11:44:05.933 回答
0

此外,还有一个 npm 包:

朱利安

在天文学和历史中使用的日期对象和儒略日期之间转换

  var julian = require('julian');
 
  var now = new Date();           // Let's say it's Thu, 21 Nov 2013 10:47:02 GMT 
  var jd = '';
 
  console.log(jd = julian(now));  // -> '2456617.949335' 
  console.log(julian.toDate(jd)); // -> Timestamp above in local TZ 

https://www.npmjs.com/package/julian

于 2016-11-09T13:01:09.617 回答
0

无论您做什么,都不要在当前区域设置中的策略更改之前的日期使用 getTimezoneOffset(),它在过去完全被破坏(它不应用iana 数据库规则)。例如,如果我输入(UTC 日期 1995 年 10 月 1 日 00:00:00):
var d=new Date(Date.UTC(1995, 9, 1, 0, 0, 0)); console.log(d.toLocaleString()); console.log(d.getTimezoneOffset());
在 Chrome 的 javascript 控制台中,它会打印(我在法国):
01/10/1995 at 01:00:00 < = 这是冬季时间,UTC
-120 +1:00 <= 但这是夏季时间偏移量(冬季应为 -60)
1973 年至 1995 年(包括在内)之间,DST (-120) 于 9 月的最后一个星期日终止,因此对于 1995 年 10 月 1 日,getTimezoneOffset()应该返回-60,而不是-120。请注意,格式化的日期是正确的(01:00:00是预期的-60 )。在 Firefox 中的结果相同,但在 IE 和 Edge 中,更糟糕的是,甚至格式化的日期也是错误的(01‎/‎10‎/‎1995‎ ‎02‎:‎00‎:‎00,匹配坏的-120结果getTimezoneOffset()) . 无论使用哪种浏览器(这 4 个),都getTimezoneOffset()使用当前规则而不是考虑日期的规则。在法国(1946-1975)未应用 DST 时相同问题的变化,Chrome 控制台:
d=new Date(Date.UTC(1970, 6, 1, 0, 0, 0)); console.log(d.toLocaleString()); console.log(d.getTimezoneOffset());
显示:
‎01‎/‎07‎/‎1970‎‎01:‎00‎:‎00 <= ok, no DST 1970 年 6 月,+1:00
-120 <= 同样的问题,这里也应该是-60
而且,在 Firefox 中也是如此,在 IE/Edge 中更糟(01‎/‎07‎/‎1970‎‎02:‎00 ‎:‎00 )。

于 2018-05-16T19:44:46.387 回答
0

我这样做是为了春分和冬日。您可以将该函数用于任何儒略日期。它以日历日期格式返回儒略日期:日/月。包括年份,您可以根据需要对其进行格式化。年,月,日,一切都在那里。由于 Equinox 和 Solistice 是时间戳而不是日期,因此我在代码中的日期以小数形式返回,因此“day = k.toFixed(0);”。对于任何其他儒略日期,它应该是 day = k;

// For the HTML-page
<script src="../js/meuusjs.1.0.3.min.js"></script> 
<script src="../js/Astro.Solistice.js"></script>

// Javascript, Julian Date to Calender Date
function jdat (jdag) {
  var jd, year, month, day, l, n, i, j, k;
  jd = jdag;
  l = jd + 68569;
  n = Math.floor(Math.floor(4 * l) / 146097);
  l = l - Math.floor((146097 * n + 3) / 4);
  i = Math.floor(4000 * (l + 1) / 1461001);
  l = l - Math.floor(1461 * i / 4) + 31;
  j = Math.floor(80 * l / 2447);
  k = l - Math.floor(2447 * j / 80);
  l = Math.floor(j / 11);
  j = j + 2 - 12 * l;
  i = 100 * (n - 49) + i + l;

  year  = i;
  month = j;
  day   = k.toFixed(0); // Integer
  dat = day.toString() + "/" + month.toString(); // Format anyway you want.
  return dat;
}

// Below is only for Equinox and Solistice. Just skip if not relevant.

// Vernal Equinox
var jv = A.Solistice.march(year); // (year) predefined, today.getFullYear()
var vdag = jdat(jv);

// Summer Solistice
var js = A.Solistice.june(year); 
var ssol = jdat(js);    

//Autumnal Equinox
var jh = A.Solistice.september(year);
var hdag = jdat(jh);

// Winter Solistice
var jw = A.Solistice.december(year);
var vsol = jdat(jw);
于 2019-10-02T11:20:47.407 回答