Skip to content

Gregorian (and related) epochs are off by one from the civil Julian Day Number #23

Description

@hosni

DateObject#toJulianDay() is toDays() + calendar.epoch. For Gregorian dates the result is one less than the standard civil Julian Day Number (ICU / astronomical midnight-based civil JDN).

Date Current toJulianDay Civil JDN
Gregorian 0001-01-01 1721425 1721426
Gregorian 2024-03-20 2460389 2460390

Jalali is a special case: with the current Birashk leapsLength it also lands on 2460389 for 1403-01-01, so Jalali↔Gregorian conversions stay consistent while both are wrong relative to civil JDN.

After fixing Jalali leapsLength to match isLeap (see #21 and #22), Jalali 1403-01-01 becomes 2460390 (civil-correct) while Gregorian stays at 2460389, so the two calendars diverge by one day until this fix lands.

Reproduction

const gregorian = require("./calendars/cjs/gregorian");

function jd(cal, y, m, d) {
  return cal.getAllDays({ year: y, month: { index: m - 1 }, day: d }) + cal.epoch;
}

console.log(jd(gregorian, 2024, 3, 20)); // 2460389 (civil: 2460390)

Suggested fix

  1. Add 1 to these epochs: gregorian, julian, indian, arabic
    (leave jalali / persian at 1948319 once leapsLength matches isLeap).
  2. Update the weekday formula in index.js so Wednesday stays Wednesday when JDNs move to the civil scale:
// before
let index = (this.toJulianDay() + 3) % 7;
// after
let index = (this.toJulianDay() + 2) % 7;

Impact

Breaking change for callers who stored raw Gregorian/Julian/Indian/Arabic toJulianDay() values.
Improves ICU / civil-JDN interoperability.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions