ユリウス日からグレゴリオ暦を計算する


Tags: 日付けと時刻, SRFI

 (import (rnrs))
 (define (julian-day->gregorian jd)
   (let* ((j (+ jd 32044))
          (g (div j 146097)) (dg (mod j 146097))
          (c (div (* (+ (div dg 36524) 1) 3) 4)) (dc (- dg (* c 36524)))
          (b (div dc 1461)) (db (mod dc 1461))
          (a (div (* (+ (div db 365) 1) 3) 4)) (da (- db (* a 365)))
          (y (+ (* g 400) (* c 100) (* b 4) a))
          (m (- (div (+ (* da 5) 308) 153) 2))
          (d (+ (- da (div (* (+ m 4) 153) 5)) 122))
          (year (+ (- y 4800) (div (+ m 2) 12)))
          (month (+ (mod (+ m 2) 12) 1))
          (day (+ d 1)))
     (values year month day)))

SRFI-19 を使うと次のように書ける。

(import (rnrs) (srfi :19))

(define (julian-day->gregorian jd)
  (let ((d (julian-day->date jd)))
    (values (date-year d)
            (date-month d)
            (date-day d))))

ただし、上のアルゴリズム(WikipediaEn:Julian_day#Gregorian_calendar_from_Julian_day_number?)では西暦 1 年の前年を 0 年とするのに対し、 SRFI-19 では西暦 1 年の前年を -1 年(= 紀元前 1 年。WikipediaJa:紀元前)と表現することから、紀元前の日付けに対して、このふたつは異なる値を返す。

(julian-day->gregorian
 (exact (ceiling (date->julian-day (make-date 0 0 0 0 1 1 -1 0)))))
;; => 0 1 1

;; SRFI-19 版
(julian-day->gregorian
 (exact (ceiling (date->julian-day (make-date 0 0 0 0 1 1 -1 0)))))
;; => -1 1 1