1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-06 03:40:56 -08:00

Fix various Calc date conversions (bug#36822)

* lisp/calc/calc-forms.el (math-absolute-from-gregorian-dt):
Rewrite in a way that I understand, and that actually seems to work.
(math-absolute-from-julian-dt): Use Julian, not Gregorian, leap year
rules for counting days within a year.
(math-julian-date-beginning, math-julian-date-beginning-int):
Change constants to be consistent with their doc strings and the code:
use Rata Die epoch at Dec 31, 1 BC Gregorian proleptic, not Julian.
* doc/misc/calc.texi (Date Forms): Correct difference between Julian
Day and Rata Die.
* test/lisp/calc/calc-tests.el (calc-test-calendar): New test.
This commit is contained in:
Mattias Engdegård 2019-07-30 17:33:19 +02:00
parent c676444a43
commit 4ce9c6d0b5
3 changed files with 35 additions and 28 deletions

View file

@ -587,29 +587,15 @@ A DT is a list of the form (YEAR MONTH DAY)."
"Return the DATE of the day given by the Gregorian day YEAR MONTH DAY.
Recall that DATE is the number of days since December 31, -1
in the Gregorian calendar."
(if (eq year 0) (setq year -1))
(let ((yearm1 (math-sub year 1)))
(math-sub
;; Add the number of days of the year and the numbers of days
;; in the previous years (leap year days to be added separately)
(math-add (math-day-in-year year month day)
(math-add (math-mul 365 yearm1)
;; Add the number of Julian leap years
(if (math-posp year)
(math-quotient yearm1 4)
(math-sub 365
(math-quotient (math-sub 3 year)
4)))))
;; Subtract the number of Julian leap years which are not
;; Gregorian leap years. In C=4N+r centuries, there will
;; be 3N+r of these days. The following will compute
;; 3N+r.
(let* ((correction (math-mul (math-quotient yearm1 100) 3))
(res (math-idivmod correction 4)))
(math-add (if (= (cdr res) 0)
0
1)
(car res))))))
(when (zerop year) ; Year -1 precedes year 1.
(setq year -1))
(let* ((y (if (> year 0) year (+ year 1))) ; Astronomical year (with 0).
(y1 (- y 1))) ; Previous year.
(+ (* y1 365) ; Days up to the previous year...
(floor y1 4) ; ... including leap days.
(- (floor y1 100))
(floor y1 400)
(math-day-in-year year month day))))
(defun math-absolute-from-julian-dt (year month day)
"Return the DATE of the day given by the Julian day YEAR MONTH DAY.
@ -620,7 +606,7 @@ in the Gregorian calendar."
(math-sub
;; Add the number of days of the year and the numbers of days
;; in the previous years (leap year days to be added separately)
(math-add (math-day-in-year year month day)
(math-add (math-day-in-year year month day t)
(math-add (math-mul 365 yearm1)
;; Add the number of Julian leap years
(if (math-posp year)
@ -714,11 +700,11 @@ in the Gregorian calendar."
(setcdr math-fd-dt nil))
fmt))))
(defconst math-julian-date-beginning '(float 17214225 -1)
(defconst math-julian-date-beginning '(float 17214245 -1)
"The beginning of the Julian date calendar,
as measured in the number of days before December 31, 1 BC (Gregorian).")
(defconst math-julian-date-beginning-int 1721423
(defconst math-julian-date-beginning-int 1721425
"The beginning of the Julian date calendar,
as measured in the integer number of days before December 31, 1 BC (Gregorian).")