Calculating Jday(Julian Day) in javascript

Viewed 27983
8 Answers

JD =>

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

There seems to be confusion about what a Julian-Day is, and how to calculate one.

Javascript time is measured as GMT/UTC milliseconds UInt64 from Jan 1, 1970 at midnight.

The Month, Day, Year aspects of the JavaScript Date function are all implemented using Gregorian Calendar rules. But Julian "Days" are unaffected by that; however mapping a "day-count" to a Julian Month, Day, Year would be.

Calculating Julian-Day conversions are therefore a relative day count from that point in time (Jan 1, 1970 GMT/UTC Gregorian).

The Julian-Day for Jan 1, 1970 is 2440587.5 (0.5 because JulianDays started at NOON).

The 864e5 constant is JavaScript notation for 86,400,000 (milliseconds/day).

The only complexities are in calculating Julian dates (days) prior to adoption of the 1582 Gregorian calendar whose changes mandated from Pope Gregory were to correct for Leap Year drift inaccuracies affecting Easter. It took until around 1752 to be fully adopted throughout most countries in the world which were using the Julian Calendar system or a derivative (Russia and China took until the 20th century).

And the more egregious errors in the first 60 years of Julian date implementation from Julius Caesar's 46BC "reform" mandate where priests made mistakes and people misunderstood as they folded a 14/15 month calendar. (hence errors in many religious dates and times of that period).

None of which applies in JavaScript computation of Julian Day values.

See also: (from AfEE EdgeS/EdgeShell scripting core notes)

There is a separate subtlety "leap-second" which applies to astronomical calculations and the use of atomic clocks that has to do with earth orbital path and rotational drift.

i.e., 86,400.000 seconds per day needs "adjustment" to keep calendars (TimeZones, GPS satellites) in sync as it is currently 86,400.002.

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:00 is 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 -120 result 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 -60 here too
And also, same thing in Firefox, worse in IE/Edge (01‎/‎07‎/‎1970‎ ‎02:‎00‎:‎00).

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;

// 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);
Related