Преобразование юлианской даты в обычную дату в Javascript

Я пытаюсь преобразовать юлианское целое число обратно в дату.

Пример:

целое число 2456931 = 2014/09/30 // формат ГГГГ / ММ / ДД

Пожалуйста, помогите - заранее спасибо,


person AJR    schedule 14.10.2014    source источник
comment
что вы пробовали до сих пор? где ты застрял?   -  person Icepickle    schedule 15.10.2014


Ответы (7)


Вот что я разработал для своих нужд:

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());
person Stephane BOISSEAU    schedule 14.10.2014
comment
Я только что попробовал, и расчет немного сбился. Например: целое число 2456931 = 24.09.2014. Это должно быть 30.09.2014. Не могли бы вы добавить некоторые улучшения в фомулу? Заранее спасибо - person AJR; 20.10.2014
comment
Я взял эту строку кода var D = Math.floor (((h% 153)) / 6); и добавил к нему 6. он работает сейчас ... но проверим его и на другие даты - person AJR; 20.10.2014
comment
У меня это не работает, расчет отключен, есть ли обновление для него? - person Shek; 09.04.2019

Вот пример 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.

Если вы не знали, даты по юлианскому календарю всегда начинаются в полдень по всемирному координированному времени.

person Gerard Ashton    schedule 18.03.2016

Вышеупомянутое не работает для меня. Следующее решение написано строго в соответствии со страницей википедии (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());
person Eugene Y.    schedule 17.03.2016
comment
сейчас это не работает! dateToJulianNumber0(new Date("2017-08-14")) \\ =2457980 ; julianIntToDate(2457980) \\ = Sun Aug 14 2016 00:00:00 GMT+0300 (EAT) - person ShegaMike; 14.08.2017
comment
На сегодняшний день ваш int - единственная работающая функция JS, которую я нашел. Спасибо! - person OwN; 17.04.2020

Удобный способ создания сценария 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):

person Feld B.    schedule 23.10.2016

Если еще не поздно - для Nodejs я использовал модуль moment js, и он работал у меня так, как ожидалось -

const moment = require("moment");
let date = moment("2456931", "YYYYDDD").format("YYYY/MM/DD");
console.log(date);
person Shek    schedule 09.04.2019

Вот комбинация, которую я использую для преобразования даты в целое число по юлианскому календарю, а затем обратно:

// 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);
};
person OwN    schedule 17.04.2020

person    schedule
comment
сейчас это не работает! dateToJulianNumber0(new Date("2017-08-14")) \\ =2457980 ; julianIntToDate(2457980) \\ = Sun Aug 14 2016 00:00:00 GMT+0300 (EAT) - person ShegaMike; 14.08.2017