dlowe-net / local-time

Time manipulation library for Common Lisp
Other
102 stars 43 forks source link

Incorrectly calculated Julian Dates #119

Open hajovonta opened 7 months ago

hajovonta commented 7 months ago

Hi there,

I'm trying to calculate current JD according to this article: https://en.wikipedia.org/wiki/Julian_day It states that JD must be calculated relative to 12:00 January 1, 4713 BC, but the library states the offset is calculated from 00:00 January 1, 4713 BC:

;; The astronomical julian date offset is the number of days between ;; the current date and -4713-01-01T00:00:00+00:00

I feel the function "astronomical-julian-date" is also a bit sloppy, since it only calculates the days, without fractions.

This is not a post to criticize, just wanted your thoughts or maybe a bit of history on the library.

dlowe-net commented 7 months ago

Yes, it's totally sloppy. The library uses 00:00:00Z as an indicator for naive dates, and in that context, it makes sense to use a simple offset to compute the JD. It would be better to have the correct JD with its fractional components. It wouldn't be that hard to compute a naive offset if one really needed it.

hajovonta commented 7 months ago

Thanks for the answer, @dlowe-net. I came up with the following approach which gives correct results:

(defun current-jd (&optional adjustment)
  ;; The 2000-01-01 12:00 offset constant is from this article: https://en.wikipedia.org/wiki/Julian_day
  ;; reference: McCarthy & Guinot 2013, 91–2
  (let* ((jd-offset 2451545)        ;; 2000-01-01 12:00
         (julian-offset 3155713200) ;; universal-time of 2000-01-01 12:00
         (elapsed-since-2000 (- (get-universal-time) julian-offset))
         (elapsed-days (/ elapsed-since-2000 60 60 24))
         (adjustment (or adjustment 0)))
    (float (+ jd-offset
              elapsed-days
              adjustment)
           0.0d0)))

This allows calculations like this:

(values
 :jd (current-jd)
 :reduced-jd (current-jd -2400000)
 :modified-jd (current-jd -2400000.5)
 :truncated-jd (floor (current-jd -2440000.5))
 :dublin-jd (current-jd -2415020)
 :cnes-jd (current-jd -2433282.5)
 :ccsds-jd (current-jd -2436204.5)
 :lilian-date (floor (current-jd -2299159.5))
 :rata-die (floor (current-jd -1721424.5))
 :mars-sol-date (/ (current-jd -2405522) 1.02749)
 :unix-time (* (current-jd -2440587.5) 86400)
 :dotnet-datetime (* (current-jd -1721425.5) 864000000000))

(these are the calculations in the article)

This still uses an offset and I think it would be better to use another one, 1977 probably, as this would allow better calculations towards the TAI (International Atomic Time) according to this article: https://en.wikipedia.org/wiki/Terrestrial_Time

But I'm not an expert, possibly further discussions are needed.

dlowe-net commented 5 months ago

We do have a TODO item near +modified-julian-date-offset+ to fix this.