1

I am trying to calculate the Julian Date from a calendar date string using javascript. I found this site that explains how to calculate it.

I made this javascript code: https://jsfiddle.net/kzgn8vs1/1/

var time = moment("2018-04-07 23:45:16 -0300", "YYYY-MM-DD HH:mm:ss Z").utc(); 
var Y = time.year();
var M = time.month() + 1;
var D = time.date() + moment.duration(time.format('HH:mm:ss')).asDays();

if( M == 1 || M == 2 ) {
    Y = Y - 1;
    M = M + 12;
}

var A = Y / 100;
var B = 2 - A + (A / 4);
var C = ( Y > 0 ) ? (365.25 * Y) : ((365.25 * Y) - 0.75);
var E = 30.6001 * (M + 1);

var JD = B+C+D+E+1720994.5;

console.log(JD);

Which returns 2458216.9802685184 for the date 2018-04-07 23:45:16 -0300. But when I try some online converters like http://www.onlineconversion.com/julian_date.htm and https://www.aavso.org/jd-calculator

Entering the date 2018-04-08 2:45:16 (my date converted to UTC), both return 2458216.61477. A 0.36 difference from my result.

Where is the error? In my code or in the calculation method?

Mark
  • 577
  • 1
  • 7
  • 29
  • 1
    You could find a detailed explanation on this question https://stackoverflow.com/questions/11759992/calculating-jdayjulian-day-in-javascript – Lasitha Petthawadu Apr 07 '18 at 03:13
  • The code sample on that question also gives me a different result than all the online calculators I tried, with a difference of +-30 or 40, my code is much closer to the online calculators result. – Mark Apr 07 '18 at 03:26
  • Check the answer I have posted, I was able to revise your code to get the online calculators answer and have detailed out how I got to it – Lasitha Petthawadu Apr 07 '18 at 03:43

3 Answers3

1

Based on the StackOverflow Question here, I have modified your JsFiddle

I have changed your implementation based on

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

(UNIX TIME / 86400000) + 2440587.5) === Julian Day;

and have updated your code to reflect as var JD = time/86400000 + 2440587.5; To get the same result as the online calculator I had to use the UTC time you used with the online examples.

Community
  • 1
  • 1
  • Thanks, I made my code implementation work after all, I had to use some values as ints instead of doubles, like this var `JD = parseInt(B)+parseInt(C)+(D)+parseInt(E)+1720994.5;` – Mark Apr 07 '18 at 04:39
  • This doesn't answer the question "*Where is the error*". – RobG Apr 07 '18 at 14:15
  • @Mark—that is your actual answer, the page you reference has "A=INT(Y/100)" so you should do something like `var A = Y / 100 | 0` or use *Math.floor* or *parseInt* to truncate the decimal part wherever *INT(…)* is used. The same applies to *B*, *C* and *E*. – RobG Apr 07 '18 at 14:27
0

If you just need Gregorian dates, you can take this function:

function jdFromDate(dateTime) {
    return (
        Date.UTC(
            dateTime.getFullYear(),
            dateTime.getMonth(),
            dateTime.getDate()
        ) /
            86400000 +
        2440588
    );
}

As for the discussion of Gregorian vs. Julian calendars, this is a lot more complex than many people might think. Some countries adopted the Gregorian calendar quite late (e.g. Britain except Scottland in 1752), so comparing historical dates is a difficult task between 1582 and, say 1918 (Russian adoption of the Gregorian calendar), depending on your use case. If you just want to store days as JDs to make them usable across different platforms (e.g. to simply display them), the usage of different calendars might be too much anyway. I have worked extensively with Early Modern sources and it can be quite hard to grasp which source states what date in which calendar system (also note that the 1st of January might not be the first day of a year in every region back then...). For more information on the topic, you might want to have a look into "Calendrical Calculations" by Nachum Dershowitz and Edward Reingold - they cover much more than just these two calendar systems, though :-)

ronix75
  • 1
  • 1
-1

As you say in your comment to Lasitha Ishan Petthawadu's answer, you need to floor values A, B, C and E. A version that is a pretty literal implementation of the algorithm linked from the OP without using a library is:

function toJulianDate(date) {
  var floor = Math.floor;
  var y = date.getUTCFullYear();
  var m = date.getUTCMonth() + 1;
  var d = date.getUTCDate() + (date % 8.64e7) / 8.64e7;
  
  if (m < 3) {
    y -= 1;
    m += 12;
  }
  
  var a = floor(y/100);
  var b = date < new Date(Date.UTC(1582,9,15))? 0 : 2 - a + floor(a/4);
  var c = floor(y < 0? 365.25 * y - 0.75 : 365.25 * y);
  var e = floor(30.6001 * (m + 1));
  
  return b + c + d + e + 1720994.5;
}

console.log(toJulianDate(new Date('2018-04-07T23:45:16-03:00'))); // 2458216.6147685186

console.log(toJulianDate(new Date('2018-04-08T02:45:16Z'))); // 2458216.6147685186

When creating the Dates, I've used strict ISO 8601 extended format. Anything else should not use the built-in parser.

RobG
  • 142,382
  • 31
  • 172
  • 209
  • From my experiments, Javascript Date function does not seem to recognize Julian calendar and treats all dates as Gregorian, even those before October 15, 1582. http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15 states "YYYY is the decimal digits of the year 0000 to 9999 in the Gregorian calendar." – Gerard Ashton Apr 15 '18 at 14:41
  • @GerardAshton—I don't understand the reason for your comment. This is an implementation of the algorithm provided by the OP to generate a Julian date string from an ECMAScript Date object. There is no statement or inference that the built-in parser understands Julian dates, quite the opposite. – RobG Apr 15 '18 at 20:52
  • I have not deciphered all the magic numbers in the algorithm. But I don't understand why RobG's algorithm cares whether the date is before or after the date the Gregorian calendar was adopted in Rome. – Gerard Ashton Apr 16 '18 at 23:36
  • @GerardAshton—as I keep saying, it's not my algorithm, it's the one [*linked by the OP*](http://129.79.46.40/~foxd/cdrom/musings/formulas/formulas.htm). It seems to be 1 year and 1 day out to me, but that might just be because ECMAScript has a year 0000, which is not generally recognised. Issues with the algorithm, or dates before 15 October, 1582 should be discussed with the OP or the author of the linked algorithm. – RobG Apr 17 '18 at 01:42