javascript 在javascript中计算Jday(儒略日)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11759992/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calculating Jday(Julian Day) in javascript
提问by Esh
I have requirement to calculate jday
in javascript , for doing client side validation , Can any one help me how to calculate JDAY
in javascript or script to change given JDAY to actual date or vice versa .
我需要jday
在 javascript 中进行计算,以便进行客户端验证,任何人都可以帮助我如何JDAY
在 javascript 或脚本中计算以将给定的 JDAY 更改为实际日期,反之亦然。
To know what is JDay ,I found the following site ,
要知道什么是 JDay,我找到了以下网站,
http://www.pauahtun.org/Software/jday.1.html
http://www.pauahtun.org/Software/jday.1.html
Am also refering the below site for calculation which is mentioned in JAVA
我也参考以下网站进行计算,这是在 JAVA 中提到的
http://www.rgagnon.com/javadetails/java-0506.html
http://www.rgagnon.com/javadetails/java-0506.html
Thank you in advance
先感谢您
回答by adeneo
Julian Day
儒略日
The Julian Dayis the number of elapsed days since the beginning of a cycle of 7980 years.
儒略日是自 7980 年循环开始以来经过的天数。
Invented in 1583 by Joseph Scaliger, the purpose of the system is to make it easy to compute an integer (whole number)differencebetween one calendar date and another calendar date.
该系统由 Joseph Scaliger 于 1583 年发明,其目的是使计算一个日历日期和另一个日历日期之间的整数(整数)差异变得容易。
The 7980 year cycle was derived by combining several traditional time cycles (solar, lunar, and a particular Roman tax cycle)for which 7980 was a common multiple.
7980 年周期是通过结合几个传统时间周期(太阳、月球和特定的罗马税收周期)得出的,其中 7980 是公倍数。
The starting point for the first Julian cycle began on January 1, 4713 B.C. at noon GMT, and will end on January 22, 3268 at noon GMT, exactly 7980 whole days later.
第一个儒略周期的起点开始于公元前 4713 年 1 月 1 日格林威治标准时间中午,并将于格林威治标准时间 3268 年 1 月 22 日中午结束,正好是整整 7980 天之后。
As an example, the Julian day number for January 1, 2016 was 2,457,389, which is the number of days since January 1, 4713 B.C. at that day.
例如,2016 年 1 月 1 日的儒略日数是 2,457,389,这是自公元前 4713 年 1 月 1 日以来的天数。
How to calculate it
如何计算
As we know that Unix time is the number of seconds since 00:00:00 UTC, January 1, 1970, not counting leap seconds, and also called Epoch, we can use some math to calculate the Julian Day when we already have the Unix time.
正如我们所知,Unix 时间是自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数,不计算闰秒,也称为纪元,当我们已经拥有 Unix 时,我们可以使用一些数学方法来计算儒略日时间。
GMT and UTC share the same current time in practice, so for this, there should be no difference.
GMT 和 UTC 在实践中共享相同的当前时间,因此对此,应该没有区别。
To start with, we need to know the number of days from when the Julian cycle began, until Unix timestamps began.
In other words, the number of days from January 1, 4713 B.C. at 12:00:00 GMT, until January 1, 1970 at 00:00:00 UTC.
首先,我们需要知道从儒略周期开始到 Unix 时间戳开始的天数。
换句话说,从公元前 4713 年 1 月 1 日 12:00:00 GMT 到 1970 年 1 月 1 日 00:00:00 UTC 的天数。
Having this set number of days, that never change, we can just add the number of days from January 1, 1970 until today, which is what Javascript returns anyway, to get the Julian Day.
有了这个永远不会改变的天数,我们可以添加从 1970 年 1 月 1 日到今天的天数,无论如何,这是 Javascript 返回的天数,以获得儒略日。
Without adding up all those years, but simply by searching the web, it tells us that the difference in days between the year 4713 B.C. and 1970 A.D. is 2440588 days, and because the Julian Cycle began at noon, not at midnight, we have to subtract exactly half a day, making it 2440587.5 days.
没有把所有这些年加起来,只是通过搜索网络,它告诉我们公元前 4713 年和公元 1970 年之间的天数差异是 2440588 天,并且因为朱利安循环开始于中午,而不是午夜,我们必须减去半天,使其成为 2440587.5 天。
So what we have now is 2440587.5 days + UNIX TIME in days === Julian Day
所以我们现在拥有的是 2440587.5 days + UNIX TIME in days === Julian Day
With some simple math we can figure out that a day is 86,400 seconds long, and the Unix timestamp is in milliseconds when using Javascript, so UNIX TIME / 86400000
would get us the number of days since Thursday, 1 January 1970, until today.
通过一些简单的数学运算,我们可以计算出一天的长度为 86,400 秒,而使用 Javascript 时 Unix 时间戳以毫秒为单位,因此UNIX TIME / 86400000
可以得到从 1970 年 1 月 1 日星期四到今天的天数。
Now for just the day, we wanted the whole number of days, and not the fractional, and can just round it down to the closes whole day, doing something like
现在就这一天而言,我们想要的是整数天数,而不是小数,可以将其四舍五入到一整天的收盘价,做类似的事情
Math.floor((UNIX TIME / 86400000) + 2440587.5);
Julian Date
朱利安日期
Sometimes in programming, a "Julian Date" has come to mean the number of days since the year started, for instance June 1, 2016 would be 152 days into that year etc.
有时在编程中,“儒略日期”已开始表示自一年开始以来的天数,例如 2016 年 6 月 1 日将是该年的 152 天等。
The correct use of "Julian Date" is a Julian Day with a timestamp added as a fractional part of the day.
“儒略日期”的正确用法是将时间戳添加为一天的小数部分的儒略日。
Taking the example at the top of this answer, where January 1, 2016 was the Julian Day 2,457,389 , we can add a time to that.
The Julian Day starts at noon, with no fractional time added, and so at midnight it would be 2457389.5
and at 18:00, or six hours after noon, it would be 2457389.25
, adding "half a day", "quarter of a day" etc.
以本答案顶部的示例为例,其中 2016 年 1 月 1 日是儒略日 2,457,389,我们可以为此添加一个时间。
儒略日从中午开始,没有添加小数时间,因此在午夜2457389.5
18:00 或中午后 6 小时,将2457389.25
添加“半天”、“一天的四分之一”等.
Calculating it, again
再计算一下
This means 0.1 Julian Date is the same as 24 hours divided by 10, or 24 / 10 === 2.4 hours
, or in other words, Julian Day timestamps are fractional with decimals (one tenth of a day etc).
这意味着 0.1 Julian Date 等于 24 小时除以 10,或者24 / 10 === 2.4 hours
换句话说,Julian Day 时间戳是带小数的小数(一天的十分之一等)。
Lets look at some Javascript functions, firstly the Date
constructor.
让我们看看一些 Javascript 函数,首先是Date
构造函数。
Javascript only has access to the local time on the computer it runs on, so when we do new Date()
it does not neccessarely create an UTC date, even if UNIX time is in UTC, new Date
gives you the number of seconds from epoch until whatever local time your computer has, and does not take your timezone into consideration.
Javascript 只能访问它运行的计算机上的本地时间,因此当我们这样做时,new Date()
它并不一定要创建 UTC 日期,即使 UNIX 时间是 UTC,也会new Date
为您提供从纪元到计算机本地时间的秒数有,并且不考虑您的时区。
Javascript does however have Date.UTC
, which would return the date in UTC format, lets check the difference, and this will of course differ according to the timezone you've set the local system to.
然而Date.UTC
,Javascript 确实有,它将以 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';
Remember the part at the begin of this chapter, about 0.1 Julian Date being the same as 24 hours divided by 10, or 24 / 10 === 2.4 hours
, well, 2.4 hours is 144 minutes, and now lets look quickly at Javascripts getTimezoneOffset()
method, the docs say
记住本章开头的部分,大约 0.1 Julian Date 等于 24 小时除以 10,或者24 / 10 === 2.4 hours
,好吧,2.4 小时是 144 分钟,现在让我们快速看一下 JavascriptsgetTimezoneOffset()
方法,文档说
The getTimezoneOffset() method returns the time-zone offset from UTC, in minutes, for the current locale.
getTimezoneOffset() 方法返回当前语言环境相对于 UTC 的时区偏移量(以分钟为单位)。
So, it returns the offset for the systems timezone in minutes, that's interesting as most javascript methods that deal with dates returns milliseconds.
因此,它以分钟为单位返回系统时区的偏移量,这很有趣,因为大多数处理日期的 javascript 方法返回毫秒。
We know that a 1/10 of a day is 144 minutes, so 10/10, or a whole day, would be 1440 minutes, so we could use some math to counteract the local systems timezone, given in minutes, and divide it by the number of minutes in a day, to get the correct fractional value
我们知道一天的 1/10 是 144 分钟,因此 10/10 或一整天将是 1440 分钟,因此我们可以使用一些数学方法来抵消以分钟为单位的本地系统时区,然后将其除以一天中的分钟数,以获得正确的小数值
So now we have
所以现在我们有
2440587.5 days + UNIX TIME in days === Julian Day
and we know Javascripts Date constructor doesn't really use UTC for the current date, but the system time, so we have to have
我们知道 Javascripts Date 构造函数并没有真正使用 UTC 作为当前日期,而是系统时间,所以我们必须有
TIMEZONEOFFSET / 1440
joining them together we would get
将他们联合起来,我们会得到
(JAVASCRIPT TIME / 86400000) - (TIMEZONEOFFSET / 1440) + 2440587.5
// ^^ days since epoch ^^ ^^ subtract offset ^^ ^^days from 4713 B.C. to 1970 A.D.
Translating that to javascript would be
将其转换为 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);
Now this is what we should use to get the Julian Dayas well, taking measures to remove the timezone offset, and of course without the fractional time part of the Julian Date.
We would do this by simpy rounding it down to the closest whole integer
现在这也是我们应该用来获取儒略日的方法,采取措施去除时区偏移,当然没有儒略日期的小数时间部分。
我们将通过简单地将其四舍五入到最接近的整数来做到这一点
var julian_date = Math.floor((time / 86400000) - (date.getTimezoneOffset()/1440) + 2440587.5));
And it's time for my original answer to this question, before I made this extremely long edit to explain why this is the correct approach, after complaints in the comment field.
现在是我对这个问题的原始答案的时候了,在我进行了非常长的编辑以解释为什么这是正确的方法之前,在评论字段中投诉之后。
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}
And the same withthe fracional part
而同样与该fracional部分
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 }
And to finish of, an example showing why
最后,一个说明原因的例子
new Date().getTime()/86400000 + 2440587.5
doesn't work, at least not if your system time is set to a timezone with an offset, i.e. anything other than GMT
不起作用,至少如果您的系统时间设置为具有偏移量的时区,即 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 }
回答by Wilbert
new Date().getTime()/86400000 + 2440587.5
will get the unix time stamp, convert it to days and add the JD of 1970-01-01, which is the epoch of the unix time stamp.
new Date().getTime()/86400000 + 2440587.5
将获取unix时间戳,将其转换为天并添加1970-01-01的JD,这是unix时间戳的纪元。
This is what astronomers call julian date. It is well defined. Since neither Unix time stamp nor JD take leap seconds into account that does not reduce the accuracy. Note that JD need not be in timezone UTC (but usually is). This answer gives you the JD in timezone UTC.
这就是天文学家所说的朱利安日期。它定义明确。由于 Unix 时间戳和 JD 都没有考虑闰秒,因此不会降低准确性。请注意,JD 不需要在 UTC 时区(但通常是)。这个答案为您提供了 UTC 时区的 JD。
回答by jbabey
According to wikipedia:
根据维基百科:
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
If you're having a more specific problem with the implementation, provide those details in the question so we can help further.
如果您在实施方面遇到更具体的问题,请在问题中提供这些详细信息,以便我们进一步提供帮助。
NOTE : This is not correct because the "floor brackets" on Wiki were forgotten here.
注意:这是不正确的,因为这里忘记了 Wiki 上的“地板括号”。
The correct formulas are:
正确的公式是:
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
回答by Wtower
Additionally, there is an npm package for this:
此外,还有一个 npm 包:
julian
Convert between Date object and Julian dates used in astronomy and history
朱利安
在日期对象和天文学和历史中使用的儒略日期之间转换
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
回答by Leos Ondra
It seems that the final code given in the accepted answer is wrong. Check the "official" online calculator at US Naval Observarory website:
似乎接受的答案中给出的最终代码是错误的。查看美国海军天文台网站上的“官方”在线计算器:
http://aa.usno.navy.mil/data/docs/JulianDate.php
http://aa.usno.navy.mil/data/docs/JulianDate.php
If someone knows the correct answer to a answer time and calendar, it's USNO.
如果有人知道答案时间和日历的正确答案,那就是 USNO。
回答by Christophe Bouchon
Whatever you do, DON'T USE getTimezoneOffset() on dates before a change of policy in the current Locale, it's completely broken in the past (it doesn't apply iana database rules).
For example, if I enter (UTC date 1st of october 1995 at 00:00:00):var d=new Date(Date.UTC(1995, 9, 1, 0, 0, 0)); console.log(d.toLocaleString()); console.log(d.getTimezoneOffset());
in the javascript console in Chrome, it prints (I'm in France):
01/10/1995 at 01:00:00<= this is winter time, +1:00 from UTC
-120<= BUT this is summer time offset (should be -60 for winter)
Between 1973 and 1995 (included), DST (-120) terminated last Sunday of September, hence for 1st of October 1995, getTimezoneOffset()
should return -60, not -120. Note that the formatted date is right (01:00:00is the expected -60).
Same result in Firefox, but in IE and Edge, it's worse, even the formatted date is wrong (01?/?10?/?1995? ?02?:?00?:?00, matching the bad -120result of getTimezoneOffset()
). Whatever the browser (of these 4), getTimezoneOffset()
uses the current rules rather than those of the considered date.
Variation on the same problem when DST didn't applied in France (1946-1975), Chrome console:d=new Date(Date.UTC(1970, 6, 1, 0, 0, 0)); console.log(d.toLocaleString()); console.log(d.getTimezoneOffset());
displayed:
?01?/?07?/?1970? ?01:?00?:?00<= ok, no DST in june 1970, +1:00
-120<= same problem, should be -60here too
And also, same thing in Firefox, worse in IE/Edge (01?/?07?/?1970? ?02:?00?:?00).
无论您做什么,都不要在当前区域设置中的策略更改之前的日期使用 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 年之间(包括在内),夏令时 (-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()
使用当前规则而不是考虑日期的规则。当 DST 未在法国(1946-1975)应用时,同一问题的变化,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<= 好的,1970 年 6 月没有 DST,+1:00
-120<= 同样的问题,这里也应该是-60
而且,在 Firefox 中也是一样,在 IE/Edge 中更糟(01?/?07?/?1970??02:?00?:?00)。
回答by Per Lundberg
I did this for equinox and solistice. You can use the function for any Julian date. It returns the Julian date in the calender date format: day/month. Include year and you can format it anyway you want. It's all there, year, month, day. Since Equinox and Solistice are time stamps rather than dates, my dates in the code comes back as decimals, hence "day = k.toFixed(0);". For any other Julian date it should be day = k;
我这样做是为了春分和至日。您可以将该函数用于任何儒略日期。它以日历日期格式返回儒略日期:日/月。包括年份,您可以随意格式化它。年、月、日都在那里。由于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);