Преобразовать юлианскую дату в обычную дату в Javascript
Я пытаюсь преобразовать юлианское целое число обратно в дату.
Пример:
целое число 2456931 = 2014/09/30 // формат ГГГГ / ММ / ДД
Пожалуйста, помогите - спасибо заранее,
5 ответов
Вот что я разработал для своих нужд:
function dateToJulianNumber(d) {
// convert a Gregorian Date to a Julian number.
// S.Boisseau / BubblingApp.com / 2014
var x = Math.floor((14 - d.getMonth())/12);
var y = d.getFullYear() + 4800 - x;
var z = d.getMonth() - 3 + 12 * x;
var n = d.getDate() + Math.floor(((153 * z) + 2)/5) + (365 * y) + Math.floor(y/4) + Math.floor(y/400) - Math.floor(y/100) - 32045;
return n;
}
// assert September 30 2014 -> 2456931
console.log(dateToJulianNumber(new Date(2014,9,30)).toString());
function julianIntToDate(n) {
// convert a Julian number to a Gregorian Date.
// S.Boisseau / BubblingApp.com / 2014
var a = n + 32044;
var b = Math.floor(((4*a) + 3)/146097);
var c = a - Math.floor((146097*b)/4);
var d = Math.floor(((4*c) + 3)/1461);
var e = c - Math.floor((1461 * d)/4);
var f = Math.floor(((5*e) + 2)/153);
var D = e + 1 - Math.floor(((153*f) + 2)/5);
var M = f + 3 - 12 - Math.round(f/10);
var Y = (100*b) + d - 4800 + Math.floor(f/10);
return new Date(Y,M,D);
}
// assert 2456931 -> September 30 2014
console.log(julianIntToDate(2456931).toString());
Вот пример HTML-файла, который иллюстрирует использование встроенного объекта Date Java.
<!DOCTYPE html>
<html>
<body>
<h1>Julian date conversion example</h1>
<script>
var jd = 2456931;
var millis = (jd - 2440587.5) * 86400000;
var dateLocal = new Date(millis);
document.writeln(dateLocal);
document.writeln("<br>");
document.write(dateLocal.getUTCFullYear(), "-");
document.write(dateLocal.getUTCMonth()+1, "-");
document.write(dateLocal.getUTCDate(), "T12:00:00Z");
</script>
</body>
</html>
Идея состоит в том, чтобы вычесть юлианскую дату полуночи в начале 1 января 1970 года по Гринвичу, которая является началом подсчета миллисекунд, используемого объектами JavaScript Date. Затем число дней с 1 января 1970 года умножается на 86 400 000 - количество миллисекунд в дне.
Значение в миллисекундах используется для создания нового объекта Date.
Результаты, отображаемые на компьютере с часовым поясом, установленным на восток США, с переходом на летнее время:
Вт 30 сен 2014 08:00:00 GMT-0400 (восточное стандартное время)
2014-9-30T12: 00: 00Z
Обратите внимание, что я написал дату и время в формате UTC в формате, аналогичном ISO 8601, но я не удосужился дополнить дату или месяц, когда значение < 10.
Если вы не знали, свидания Джулиана всегда начинаются в полдень по Гринвичу.
Выше не работает для меня. Следующее решение написано строго в соответствии со страницей Википедии ( Wikipedia) -
function dateToJulianNumber0(d){
var year=d.getFullYear();
var month=d.getMonth()+1;
var day=d.getDate();
var a = Math.floor((14-month)/12);
var y = Math.floor(year+4800-a);
var m = month+12*a-3;
var JDN = day + Math.floor((153*m+2)/5)+(365*y)+Math.floor(y/4)-Math.floor(y/100)+Math.floor(y/400)-32045;
return JDN;
}
function julianIntToDate0(JD){
var y = 4716;
var v = 3;
var j = 1401;
var u = 5;
var m = 2;
var s = 153;
var n = 12;
var w = 2;
var r = 4;
var B = 274277;
var p = 1461;
var C = -38;
var f = JD + j + Math.floor((Math.floor((4 * JD + B) / 146097) * 3) / 4) + C;
var e = r * f + v;
var g = Math.floor((e % p) / r);
var h = u * g + w;
var D = Math.floor((h % s) / u) + 1;
var M = ((Math.floor(h / s) + m) % n) + 1;
var Y = Math.floor(e / p) - y + Math.floor((n + m - M) / n) ;
return new Date(Y,M-1,D);
}
//Testing
var jd=dateToJulianNumber0(new Date(2013,11,31)); //Month is 0-based for javascript
var gd=julianIntToDate0(jd);
console.log(jd);
console.log(gd.toString());
Удобный способ создания сценария JD/JDN - это вычисление значения внутреннего времени объекта Date. Предполагая, что, как и другие решения здесь, вы используете эпоху юлианского периода UTC и способ JavaScript точно сообщать время UTC, игнорируя при этом дополнительные секунды getTime()
эти работы:
function jd(dateObj) { // Decimal days
return dateObj / 86400000 + 2440587.5;
}
function jdn(dateObj) { // Integer days (advances at noon)
return Math.floor(dateObj / 86400000 + 2440587.5);
}
function jdUTC(Y, M, D, H, m, s, ms) { // M is Jan = 0, Feb = 1, etc.
// Add local hour offset to `H` or minute offset to `m` for local time
return Date.UTC.apply(Date, arguments) / 86400000 + 2440587.5;
}
function dateFromJD(jd, isValue) { // Any time of day to nearest millisecond
var obj = new Date();
obj.getJD = Date_getJD;
obj.setJD = Date_setJD;
if (arguments.length) obj.setJD(jd);
if (isValue) obj.valueOf = Date_getJD;
return obj;
}
function Date_setJD(jd) {
this.setTime(Math.round((jd - 2440587.5) * 86400000));
return this;
}
function Date_getJD() {
return this.getTime() / 86400000 + 2440587.5;
}
В любом случае, если вы используете объекты Date, это быстрее, чем длинные математические вычисления. Но если вы иначе не используете объекты Date, чистая математика может быть быстрее (jsperf.co):
Если еще не слишком поздно - для Nodejs я использовал модуль moment js, и он сработал, как и ожидалось.
const moment = require("moment");
let date = moment("2456931", "YYYYDDD").format("YYYY/MM/DD");
console.log(date);
Вот комбинация, которую я использую для преобразования даты в целое число по юлианскому календарю, а затем обратно:
// Julian int to Gregorian date
function julianIntToDate(JD) {
JD = Number(JD);
if(!isNaN(JD)){
var y = 4716;
var v = 3;
var j = 1401;
var u = 5;
var m = 2;
var s = 153;
var n = 12;
var w = 2;
var r = 4;
var B = 274277;
var p = 1461;
var C = -38;
var f = JD + j + Math.floor((Math.floor((4 * JD + B) / 146097) * 3) / 4) + C;
var e = r * f + v;
var g = Math.floor((e % p) / r);
var h = u * g + w;
var D = Math.floor((h % s) / u) + 1;
var M = ((Math.floor(h / s) + m) % n) + 1;
var Y = Math.floor(e / p) - y + Math.floor((n + m - M) / n) ;
return new Date(Y,M-1,D);
}
return false;
}
// Date object to Julian Gregorian int
Date.prototype.getJulian = function() {
return Math.ceil((this / 86400000) - (this.getTimezoneOffset()/1440) + 2440587.5);
};
function dateToJulianNumber(d) {
// convert a Gregorian Date to a Julian number.
// S.Boisseau / BubblingApp.com / 2014
var x = Math.floor((14 - d.getMonth())/12);
var y = d.getFullYear() + 4800 - x;
var z = d.getMonth() - 3 + 12 * x;
var n = d.getDate() + Math.floor(((153 * z) + 2)/5) + (365 * y) + Math.floor(y/4) + Math.floor(y/400) - Math.floor(y/100) - 32045;
return n;
}
// assert September 30 2014 -> 2456931
console.log(dateToJulianNumber(new Date(2014,1,1)).toString());
function julianIntToDate(n) {
// convert a Julian number to a Gregorian Date.
// S.Boisseau / BubblingApp.com / 2014
var a = n + 32044;
var b = Math.floor(((4*a) + 3)/146097);
var c = a - Math.floor((146097*b)/4);
var d = Math.floor(((4*c) + 3)/1461);
var e = c - Math.floor((1461 * d)/4);
var f = Math.floor(((5*e) + 2)/153);
var D = e + 1 - Math.floor(((153*f) + 2)/5);
var M = f + 3 - 12 - Math.round(f/10);
var Y = (100*b) + d - 4800 + Math.floor(f/10);
return new Date(Y,M,D);
}
// assert 2456931 -> September 30 2014
console.log(julianIntToDate(2456931).toString());