diff options
| -rw-r--r-- | lisp/calendar/cal-china.el | 136 |
1 files changed, 53 insertions, 83 deletions
diff --git a/lisp/calendar/cal-china.el b/lisp/calendar/cal-china.el index 59c6d061a18..df6c19534a0 100644 --- a/lisp/calendar/cal-china.el +++ b/lisp/calendar/cal-china.el | |||
| @@ -29,12 +29,12 @@ | |||
| 29 | ;; used for the Chinese calendar are those of Baolin Liu (see L. E. Doggett's | 29 | ;; used for the Chinese calendar are those of Baolin Liu (see L. E. Doggett's |
| 30 | ;; article "Calendars" in the Explanatory Supplement to the Astronomical | 30 | ;; article "Calendars" in the Explanatory Supplement to the Astronomical |
| 31 | ;; Almanac, second edition, 1992) for the calendar as revised at the beginning | 31 | ;; Almanac, second edition, 1992) for the calendar as revised at the beginning |
| 32 | ;; of the Qing dynasty in 1644. Liu's rules produce a calendar for 2033 which | 32 | ;; of the Qing dynasty in 1644. The nature of the astronomical calculations |
| 33 | ;; is not accepted by all authorities. Furthermore, the nature of the | 33 | ;; is such that precise calculations cannot be made without great expense in |
| 34 | ;; astronomical calculations is such that precise calculations cannot be made | 34 | ;; time, so that the calendars produced may not agree perfectly with published |
| 35 | ;; without great expense in time, so that the calendars produced may not agree | 35 | ;; tables--but no two pairs of published tables agree perfectly either! Liu's |
| 36 | ;; perfectly with published tables--but no two pairs of published tables agree | 36 | ;; rules produce a calendar for 2033 which is not accepted by all authorities. |
| 37 | ;; perfectly either! | 37 | ;; The date of Chinese New Year is correct from 1644-2051. |
| 38 | 38 | ||
| 39 | ;; Comments, corrections, and improvements should be sent to | 39 | ;; Comments, corrections, and improvements should be sent to |
| 40 | ;; Edward M. Reingold Department of Computer Science | 40 | ;; Edward M. Reingold Department of Computer Science |
| @@ -64,10 +64,7 @@ UT+7:45:40 to UT+8.") | |||
| 64 | (defvar chinese-calendar-location-name "Beijing" | 64 | (defvar chinese-calendar-location-name "Beijing" |
| 65 | "*Name of location used for calculation of Chinese calendar.") | 65 | "*Name of location used for calculation of Chinese calendar.") |
| 66 | 66 | ||
| 67 | (defvar chinese-calendar-daylight-time-offset 0 | 67 | (defvar chinese-calendar-daylight-time-offset 60 |
| 68 | ; The correct value is as follows, but I don't believe the Chinese calendrical | ||
| 69 | ; authorities would use DST in determining astronomical events: | ||
| 70 | ; 60 | ||
| 71 | "*Number of minutes difference between daylight savings and standard time | 68 | "*Number of minutes difference between daylight savings and standard time |
| 72 | for Chinese calendar. Default is for no daylight savings time.") | 69 | for Chinese calendar. Default is for no daylight savings time.") |
| 73 | 70 | ||
| @@ -80,20 +77,16 @@ for Chinese calendar. Default is for no daylight savings time.") | |||
| 80 | (defvar chinese-calendar-daylight-time-zone-name "CDT" | 77 | (defvar chinese-calendar-daylight-time-zone-name "CDT" |
| 81 | "*Abbreviated name of daylight-savings time zone used for Chinese calendar.") | 78 | "*Abbreviated name of daylight-savings time zone used for Chinese calendar.") |
| 82 | 79 | ||
| 83 | (defvar chinese-calendar-daylight-savings-starts nil | 80 | (defvar chinese-calendar-daylight-savings-starts |
| 84 | ; The correct value is as follows, but I don't believe the Chinese calendrical | 81 | '(cond ((< 1986 year) (calendar-nth-named-day 1 0 4 year 10)) |
| 85 | ; authorities would use DST in determining astronomical events: | 82 | ((= 1986 year) '(5 4 1986)) |
| 86 | ; '(cond ((< 1986 year) (calendar-nth-named-day 1 0 4 year 10)) | 83 | (t nil)) |
| 87 | ; ((= 1986 year) '(5 4 1986)) | ||
| 88 | ; (t nil)) | ||
| 89 | "*Sexp giving the date on which daylight savings time starts for Chinese | 84 | "*Sexp giving the date on which daylight savings time starts for Chinese |
| 90 | calendar. Default is for no daylight savings time. See documentation of | 85 | calendar. Default is for no daylight savings time. See documentation of |
| 91 | `calendar-daylight-savings-starts'.") | 86 | `calendar-daylight-savings-starts'.") |
| 92 | 87 | ||
| 93 | (defvar chinese-calendar-daylight-savings-ends nil | 88 | (defvar chinese-calendar-daylight-savings-ends |
| 94 | ; The correct value is as follows, but I don't believe the Chinese calendrical | 89 | '(if (<= 1986 year) (calendar-nth-named-day 1 0 9 year 11)) |
| 95 | ; authorities would use DST in determining astronomical events: | ||
| 96 | ; '(if (<= 1986 year) (calendar-nth-named-day 1 0 9 year 11)) | ||
| 97 | "*Sexp giving the date on which daylight savings time ends for Chinese | 90 | "*Sexp giving the date on which daylight savings time ends for Chinese |
| 98 | calendar. Default is for no daylight savings time. See documentation of | 91 | calendar. Default is for no daylight savings time. See documentation of |
| 99 | `calendar-daylight-savings-ends'.") | 92 | `calendar-daylight-savings-ends'.") |
| @@ -159,7 +152,7 @@ The Zodiac signs begin when the sun's longitude is a multiple of 30 degrees." | |||
| 159 | (defvar chinese-year-cache | 152 | (defvar chinese-year-cache |
| 160 | '((1989 (12 . 726110) (1 . 726139) (2 . 726169) (3 . 726198) (4 . 726227) | 153 | '((1989 (12 . 726110) (1 . 726139) (2 . 726169) (3 . 726198) (4 . 726227) |
| 161 | (5 . 726257) (6 . 726286) (7 . 726316) (8 . 726345) (9 . 726375) | 154 | (5 . 726257) (6 . 726286) (7 . 726316) (8 . 726345) (9 . 726375) |
| 162 | (10 . 726404) (11 . 726434)) | 155 | (10 . 726404) (11 . 726434)) |
| 163 | (1990 (12 . 726464) (1 . 726494) (2 . 726523) (3 . 726553) (4 . 726582) | 156 | (1990 (12 . 726464) (1 . 726494) (2 . 726523) (3 . 726553) (4 . 726582) |
| 164 | (5 . 726611) (5.5 . 726641) (6 . 726670) (7 . 726699) (8 . 726729) | 157 | (5 . 726611) (5.5 . 726641) (6 . 726670) (7 . 726699) (8 . 726729) |
| 165 | (9 . 726758) (10 . 726788) (11 . 726818)) | 158 | (9 . 726758) (10 . 726788) (11 . 726818)) |
| @@ -214,30 +207,31 @@ The list is cached for further use." | |||
| 214 | (append chinese-year-cache (list (cons y list)))))) | 207 | (append chinese-year-cache (list (cons y list)))))) |
| 215 | list)) | 208 | list)) |
| 216 | 209 | ||
| 217 | (defun number-chinese-months (list start &optional no-leap-months) | 210 | (defun number-chinese-months (list start) |
| 218 | "Assign month numbers to the lunar months in LIST, starting with START. | 211 | "Assign month numbers to the lunar months in LIST, starting with START. |
| 212 | Numbers are assigned sequentially, START, START+1, ..., 11, with half | ||
| 213 | numbers used for leap months. | ||
| 219 | 214 | ||
| 220 | If optional parameter NO-LEAP-MONTHS is true, just number the months | 215 | If optional parameter NO-LEAP-MONTHS is true, just number the months |
| 221 | sequentially, ignoring the usual leap month rule. | 216 | sequentially, ignoring the usual leap month rule. |
| 222 | 217 | ||
| 223 | First month of list will never be a leap month, nor will the last. | 218 | First month of list will never be a leap month, nor will the last." |
| 224 | |||
| 225 | Numbers are assigned sequentially mod 12 (but using 12 instead of 0)." | ||
| 226 | (if list | 219 | (if list |
| 227 | (if no-leap-months | 220 | (if (zerop (- 12 start (length list))) |
| 228 | (cons (cons (calendar-mod start 12) (car list)) | 221 | ;; List is too short for a leap month |
| 229 | (number-chinese-months (cdr list) (1+ start) t)) | 222 | (cons (cons start (car list)) |
| 223 | (number-chinese-months (cdr list) (1+ start))) | ||
| 230 | (cons | 224 | (cons |
| 231 | ;; first month | 225 | ;; First month |
| 232 | (cons (calendar-mod start 12) (car list)) | 226 | (cons start (car list)) |
| 233 | ;; remaining months | 227 | ;; Remaining months |
| 234 | (if (and (cdr (cdr list));; at least two more months... | 228 | (if (and (cdr (cdr list));; at least two more months... |
| 235 | ;; ... and next one is a leap month | ||
| 236 | (<= (car (cdr (cdr list))) | 229 | (<= (car (cdr (cdr list))) |
| 237 | (chinese-zodiac-sign-on-or-after (car (cdr list))))) | 230 | (chinese-zodiac-sign-on-or-after (car (cdr list))))) |
| 238 | (cons (cons (+ (calendar-mod start 12) 0.5) (car (cdr list))) | 231 | ;; Next month is a leap month |
| 239 | (number-chinese-months (cdr (cdr list)) (1+ start) t)) | 232 | (cons (cons (+ start 0.5) (car (cdr list))) |
| 240 | ;; Otherwise, just number the months | 233 | (number-chinese-months (cdr (cdr list)) (1+ start))) |
| 234 | ;; Next month is not a leap month | ||
| 241 | (number-chinese-months (cdr list) (1+ start))))))) | 235 | (number-chinese-months (cdr list) (1+ start))))))) |
| 242 | 236 | ||
| 243 | (defun chinese-month-list (start end) | 237 | (defun chinese-month-list (start end) |
| @@ -248,18 +242,6 @@ Numbers are assigned sequentially mod 12 (but using 12 instead of 0)." | |||
| 248 | (append (list new-moon) | 242 | (append (list new-moon) |
| 249 | (chinese-month-list (1+ new-moon) end)))))) | 243 | (chinese-month-list (1+ new-moon) end)))))) |
| 250 | 244 | ||
| 251 | (defun chinese-leap-months (list low high) | ||
| 252 | "Return list of leap months in LIST with indices in range LOW to HIGH. | ||
| 253 | |||
| 254 | A leap month has a non-integer index." | ||
| 255 | (if list | ||
| 256 | (let ((index (car (car list)))) | ||
| 257 | (if (and (/= index (floor index)) | ||
| 258 | (<= low index) | ||
| 259 | (<= index high)) | ||
| 260 | (cons index (chinese-leap-months (cdr list) low high)) | ||
| 261 | (chinese-leap-months (cdr list) low high))))) | ||
| 262 | |||
| 263 | (defun compute-chinese-year (y) | 245 | (defun compute-chinese-year (y) |
| 264 | "Compute the structure of the Chinese year for Gregorian year Y. | 246 | "Compute the structure of the Chinese year for Gregorian year Y. |
| 265 | The result is a list of pairs (i . d), where month i begins on absolute date d, | 247 | The result is a list of pairs (i . d), where month i begins on absolute date d, |
| @@ -271,43 +253,28 @@ Gregorian year Y-1 to the Chinese month of the solstice of Gregorian year Y." | |||
| 271 | (list (chinese-month-list (1+ (chinese-zodiac-sign-on-or-after | 253 | (list (chinese-month-list (1+ (chinese-zodiac-sign-on-or-after |
| 272 | (calendar-absolute-from-gregorian | 254 | (calendar-absolute-from-gregorian |
| 273 | (list 12 15 (1- y))))) | 255 | (list 12 15 (1- y))))) |
| 274 | next-solstice))) | 256 | next-solstice)) |
| 257 | (next-sign (chinese-zodiac-sign-on-or-after (car list)))) | ||
| 275 | (if (= (length list) 12) | 258 | (if (= (length list) 12) |
| 276 | ;; No room for a leap month, just number them 12, 1, 2, ..., 11 | 259 | ;; No room for a leap month, just number them 12, 1, 2, ..., 11 |
| 277 | (number-chinese-months list 0 t) | 260 | (cons (cons 12 (car list)) |
| 278 | (let* ((had-leap-month (chinese-leap-months (chinese-year (1- y)) 1 10)) | 261 | (number-chinese-months (cdr list) 1)) |
| 279 | (numbered-list) | 262 | ;; Now we can assign numbers to the list for y |
| 280 | (next-sign;; On or after first month on list | 263 | ;; The first month or two are special |
| 281 | (chinese-zodiac-sign-on-or-after (car list)))) | 264 | (if (or (> (car list) next-sign) (>= next-sign (car (cdr list)))) |
| 282 | ;; Now we can assign numbers to the list for y | 265 | ;; First month on list is a leap month, second is not |
| 283 | ;; The first month or two are special | 266 | (append (list (cons 11.5 (car list)) |
| 284 | (if (and (<= (car list) next-sign) (< next-sign (car (cdr list)))) | 267 | (cons 12 (car (cdr list)))) |
| 285 | (progn;; First month on list is not a leap month | 268 | (number-chinese-months (cdr (cdr list)) 1)) |
| 286 | (setq numbered-list (list (cons 12 (car list)))) | 269 | ;; First month on list is not a leap month |
| 287 | (setq list (cdr list)) | 270 | (append (list (cons 12 (car list))) |
| 288 | (setq next-sign (chinese-zodiac-sign-on-or-after (car list)))) | 271 | (if (>= (chinese-zodiac-sign-on-or-after (car (cdr list))) |
| 289 | ;; First month on list might be a leap month... | 272 | (car (cdr (cdr list)))) |
| 290 | (if (not had-leap-month);; ... it is a leap month | 273 | ;; Second month on list is a leap month |
| 291 | (progn;; First month on list is a leap month, so second is not | 274 | (list (cons 12.5 (car (cdr list))) |
| 292 | (setq numbered-list (list (cons 11.5 (car list)) | 275 | (number-chinese-months (cdr (cdr list)) 1)) |
| 293 | (cons 12 (car (cdr list))))) | 276 | ;; Second month on list is not a leap month |
| 294 | (setq list (cdr (cdr list))) | 277 | (number-chinese-months (cdr list) 1))))))) |
| 295 | (setq had-leap-month t)))) | ||
| 296 | (if (and (>= next-sign (car (cdr list))) | ||
| 297 | (not had-leap-month)) | ||
| 298 | (progn;; Second month on list is a leap month | ||
| 299 | (setq numbered-list | ||
| 300 | (append numbered-list (list (cons 12.5 (car list))))) | ||
| 301 | (setq list (cdr list)))) | ||
| 302 | ;; At this point we have a list of new moons for months 1 to 11 for y. | ||
| 303 | ;; We need to see which are leap months. | ||
| 304 | (if (= (length list) 11) | ||
| 305 | ;; There can be no leap months, just number them 1..11 | ||
| 306 | (append numbered-list (number-chinese-months list 1 t)) | ||
| 307 | ;; There is a leap month, but it can't be the first one because that | ||
| 308 | ;; would be 12.5 which we already considered. It also can't be the | ||
| 309 | ;; last one because that has the solstice in it. | ||
| 310 | (append numbered-list (number-chinese-months list 1))))))) | ||
| 311 | 278 | ||
| 312 | (defun calendar-absolute-from-chinese (date) | 279 | (defun calendar-absolute-from-chinese (date) |
| 313 | "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE. | 280 | "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE. |
| @@ -374,7 +341,10 @@ Defaults to today's date if DATE is not given." | |||
| 374 | (this-month (calendar-absolute-from-chinese | 341 | (this-month (calendar-absolute-from-chinese |
| 375 | (list cycle year month 1))) | 342 | (list cycle year month 1))) |
| 376 | (next-month (calendar-absolute-from-chinese | 343 | (next-month (calendar-absolute-from-chinese |
| 377 | (list cycle year (1+ (floor month)) 1))) | 344 | (list (if (= year 60) (1+ cycle) cycle) |
| 345 | (if (= (floor month) 12) (1+ year) year) | ||
| 346 | (calendar-mod (1+ (floor month)) 12) | ||
| 347 | 1))) | ||
| 378 | (m-cycle (% (+ (* year 5) (floor month)) 60))) | 348 | (m-cycle (% (+ (* year 5) (floor month)) 60))) |
| 379 | (format "Cycle %s, year %s (%s-%s), %smonth %s, day %s (%s-%s)" | 349 | (format "Cycle %s, year %s (%s-%s), %smonth %s, day %s (%s-%s)" |
| 380 | cycle | 350 | cycle |