Mercurial > emacs
comparison lisp/calendar/lunar.el @ 92924:31862b15d5bb
(date, displayed-month, displayed-year): Move declarations where needed.
(lunar-phase-list): Move definition after functions it uses.
(calendar-phases-of-moon, diary-phases-of-moon)
(lunar-new-moon-on-or-after): Use cadr, nth.
(lunar-new-moon-on-or-after): Doc fix.
author | Glenn Morris <rgm@gnu.org> |
---|---|
date | Fri, 14 Mar 2008 07:08:37 +0000 |
parents | 2dc17223fab7 |
children | 1e2a7548f004 |
comparison
equal
deleted
inserted
replaced
92923:c009a4916c6a | 92924:31862b15d5bb |
---|---|
43 ;; ``Calendrical Calculations: The Millennium Edition'' by Edward M. Reingold | 43 ;; ``Calendrical Calculations: The Millennium Edition'' by Edward M. Reingold |
44 ;; and Nachum Dershowitz, Cambridge University Press (2001). | 44 ;; and Nachum Dershowitz, Cambridge University Press (2001). |
45 | 45 |
46 ;;; Code: | 46 ;;; Code: |
47 | 47 |
48 (defvar date) | |
49 (defvar displayed-month) | |
50 (defvar displayed-year) | |
51 | |
52 (if (fboundp 'atan) | 48 (if (fboundp 'atan) |
53 (require 'lisp-float-type) | 49 (require 'lisp-float-type) |
54 (error "Lunar calculations impossible since floating point is unavailable")) | 50 (error "Lunar calculations impossible since floating point is unavailable")) |
55 | 51 |
56 (require 'solar) | 52 (require 'solar) |
57 | |
58 (defun lunar-phase-list (month year) | |
59 "List of lunar phases for three months starting with Gregorian MONTH, YEAR." | |
60 (let ((end-month month) | |
61 (end-year year) | |
62 (start-month month) | |
63 (start-year year)) | |
64 (increment-calendar-month end-month end-year 3) | |
65 (increment-calendar-month start-month start-year -1) | |
66 (let* ((end-date (list (list end-month 1 end-year))) | |
67 (start-date (list (list start-month | |
68 (calendar-last-day-of-month | |
69 start-month start-year) | |
70 start-year))) | |
71 (index (* 4 | |
72 (truncate | |
73 (* 12.3685 | |
74 (+ year | |
75 ( / (calendar-day-number (list month 1 year)) | |
76 366.0) | |
77 -1900))))) | |
78 (new-moon (lunar-phase index)) | |
79 (list)) | |
80 (while (calendar-date-compare new-moon end-date) | |
81 (if (calendar-date-compare start-date new-moon) | |
82 (setq list (append list (list new-moon)))) | |
83 (setq index (1+ index)) | |
84 (setq new-moon (lunar-phase index))) | |
85 list))) | |
86 | 53 |
87 (defun lunar-phase (index) | 54 (defun lunar-phase (index) |
88 "Local date and time of lunar phase INDEX. | 55 "Local date and time of lunar phase INDEX. |
89 Integer below INDEX/4 gives the lunation number, counting from Jan 1, 1900; | 56 Integer below INDEX/4 gives the lunation number, counting from Jan 1, 1900; |
90 remainder mod 4 gives the phase: 0 new moon, 1 first quarter, 2 full moon, | 57 remainder mod 4 gives the phase: 0 new moon, 1 first quarter, 2 full moon, |
153 (* 0.0003 (solar-sin-degrees | 120 (* 0.0003 (solar-sin-degrees |
154 (+ (* 2 moon-anomaly) sun-anomaly))) | 121 (+ (* 2 moon-anomaly) sun-anomaly))) |
155 (* 0.0004 (solar-sin-degrees | 122 (* 0.0004 (solar-sin-degrees |
156 (- sun-anomaly (* 2 moon-anomaly)))) | 123 (- sun-anomaly (* 2 moon-anomaly)))) |
157 (* -0.0003 (solar-sin-degrees | 124 (* -0.0003 (solar-sin-degrees |
158 (+ (* 2 sun-anomaly) moon-anomaly)))))) | 125 (+ (* 2 sun-anomaly) moon-anomaly)))))) |
159 (adj (+ 0.0028 | 126 (adj (+ 0.0028 |
160 (* -0.0004 (solar-cosine-degrees | 127 (* -0.0004 (solar-cosine-degrees |
161 sun-anomaly)) | 128 sun-anomaly)) |
162 (* 0.0003 (solar-cosine-degrees | 129 (* 0.0003 (solar-cosine-degrees |
163 moon-anomaly)))) | 130 moon-anomaly)))) |
174 (time (* 24 (- date (truncate date)))) | 141 (time (* 24 (- date (truncate date)))) |
175 (date (calendar-gregorian-from-absolute (truncate date))) | 142 (date (calendar-gregorian-from-absolute (truncate date))) |
176 (adj (dst-adjust-time date time))) | 143 (adj (dst-adjust-time date time))) |
177 (list (car adj) (apply 'solar-time-string (cdr adj)) phase))) | 144 (list (car adj) (apply 'solar-time-string (cdr adj)) phase))) |
178 | 145 |
146 (defun lunar-phase-list (month year) | |
147 "List of lunar phases for three months starting with Gregorian MONTH, YEAR." | |
148 (let ((end-month month) | |
149 (end-year year) | |
150 (start-month month) | |
151 (start-year year)) | |
152 (increment-calendar-month end-month end-year 3) | |
153 (increment-calendar-month start-month start-year -1) | |
154 (let* ((end-date (list (list end-month 1 end-year))) | |
155 (start-date (list (list start-month | |
156 (calendar-last-day-of-month | |
157 start-month start-year) | |
158 start-year))) | |
159 (index (* 4 | |
160 (truncate | |
161 (* 12.3685 | |
162 (+ year | |
163 ( / (calendar-day-number (list month 1 year)) | |
164 366.0) | |
165 -1900))))) | |
166 (new-moon (lunar-phase index)) | |
167 (list)) | |
168 (while (calendar-date-compare new-moon end-date) | |
169 (if (calendar-date-compare start-date new-moon) | |
170 (setq list (append list (list new-moon)))) | |
171 (setq index (1+ index) | |
172 new-moon (lunar-phase index))) | |
173 list))) | |
174 | |
179 (defun lunar-phase-name (phase) | 175 (defun lunar-phase-name (phase) |
180 "Name of lunar PHASE. | 176 "Name of lunar PHASE. |
181 0 = new moon, 1 = first quarter, 2 = full moon, 3 = last quarter." | 177 0 = new moon, 1 = first quarter, 2 = full moon, 3 = last quarter." |
182 (cond ((= 0 phase) "New Moon") | 178 (cond ((= 0 phase) "New Moon") |
183 ((= 1 phase) "First Quarter Moon") | 179 ((= 1 phase) "First Quarter Moon") |
184 ((= 2 phase) "Full Moon") | 180 ((= 2 phase) "Full Moon") |
185 ((= 3 phase) "Last Quarter Moon"))) | 181 ((= 3 phase) "Last Quarter Moon"))) |
182 | |
183 (defvar displayed-month) ; from generate-calendar | |
184 (defvar displayed-year) | |
186 | 185 |
187 ;;;###cal-autoload | 186 ;;;###cal-autoload |
188 (defun calendar-phases-of-moon () | 187 (defun calendar-phases-of-moon () |
189 "Create a buffer with the lunar phases for the current calendar window." | 188 "Create a buffer with the lunar phases for the current calendar window." |
190 (interactive) | 189 (interactive) |
205 (calendar-month-name m1) y1 (calendar-month-name m2) y2))) | 204 (calendar-month-name m1) y1 (calendar-month-name m2) y2))) |
206 (erase-buffer) | 205 (erase-buffer) |
207 (insert | 206 (insert |
208 (mapconcat | 207 (mapconcat |
209 (lambda (x) | 208 (lambda (x) |
210 (let ((date (car x)) | 209 (let ((date (car x)) |
211 (time (car (cdr x))) | 210 (time (cadr x)) |
212 (phase (car (cdr (cdr x))))) | 211 (phase (nth 2 x))) |
213 (concat (calendar-date-string date) | 212 (concat (calendar-date-string date) |
214 ": " | 213 ": " |
215 (lunar-phase-name phase) | 214 (lunar-phase-name phase) |
216 " " | 215 " " |
217 time))) | 216 time))) |
218 (lunar-phase-list m1 y1) "\n")) | 217 (lunar-phase-list m1 y1) "\n")) |
219 (goto-char (point-min)) | 218 (goto-char (point-min)) |
220 (set-buffer-modified-p nil) | 219 (set-buffer-modified-p nil) |
221 (setq buffer-read-only t) | 220 (setq buffer-read-only t) |
222 (display-buffer lunar-phases-buffer) | 221 (display-buffer lunar-phases-buffer) |
227 "Display the quarters of the moon for last month, this month, and next month. | 226 "Display the quarters of the moon for last month, this month, and next month. |
228 If called with an optional prefix argument ARG, prompts for month and year. | 227 If called with an optional prefix argument ARG, prompts for month and year. |
229 This function is suitable for execution in a .emacs file." | 228 This function is suitable for execution in a .emacs file." |
230 (interactive "P") | 229 (interactive "P") |
231 (save-excursion | 230 (save-excursion |
232 (let* ((date (if arg | 231 (let* ((date (if arg (calendar-read-date t) |
233 (calendar-read-date t) | |
234 (calendar-current-date))) | 232 (calendar-current-date))) |
235 (displayed-month (extract-calendar-month date)) | 233 (displayed-month (extract-calendar-month date)) |
236 (displayed-year (extract-calendar-year date))) | 234 (displayed-year (extract-calendar-year date))) |
237 (calendar-phases-of-moon)))) | 235 (calendar-phases-of-moon)))) |
238 | 236 |
237 (defvar date) | |
238 | |
239 ;; To be called from list-sexp-diary-entries, where DATE is bound. | |
240 | |
239 ;;;###diary-autoload | 241 ;;;###diary-autoload |
240 (defun diary-phases-of-moon (&optional mark) | 242 (defun diary-phases-of-moon (&optional mark) |
241 "Moon phases diary entry. | 243 "Moon phases diary entry. |
242 An optional parameter MARK specifies a face or single-character string to | 244 An optional parameter MARK specifies a face or single-character string to |
243 use when highlighting the day in the calendar." | 245 use when highlighting the day in the calendar." |
244 (let* ((index (* 4 | 246 (let* ((index (* 4 |
245 (truncate | 247 (truncate |
246 (* 12.3685 | 248 (* 12.3685 |
248 ( / (calendar-day-number date) | 250 ( / (calendar-day-number date) |
249 366.0) | 251 366.0) |
250 -1900))))) | 252 -1900))))) |
251 (phase (lunar-phase index))) | 253 (phase (lunar-phase index))) |
252 (while (calendar-date-compare phase (list date)) | 254 (while (calendar-date-compare phase (list date)) |
253 (setq index (1+ index)) | 255 (setq index (1+ index) |
254 (setq phase (lunar-phase index))) | 256 phase (lunar-phase index))) |
255 (if (calendar-date-equal (car phase) date) | 257 (if (calendar-date-equal (car phase) date) |
256 (cons mark (concat (lunar-phase-name (car (cdr (cdr phase)))) " " | 258 (cons mark (concat (lunar-phase-name (nth 2 phase)) " " |
257 (car (cdr phase))))))) | 259 (cadr phase)))))) |
258 | 260 |
259 ;; For the Chinese calendar the calculations for the new moon need to be more | 261 ;; For the Chinese calendar the calculations for the new moon need to be more |
260 ;; accurate than those above, so we use more terms in the approximation. | 262 ;; accurate than those above, so we use more terms in the approximation. |
261 (defun lunar-new-moon-time (k) | 263 (defun lunar-new-moon-time (k) |
262 "Astronomical (Julian) day number of K th new moon." | 264 "Astronomical (Julian) day number of K th new moon." |
263 (let* ((T (/ k 1236.85)) | 265 (let* ((T (/ k 1236.85)) |
264 (T2 (* T T)) | 266 (T2 (* T T)) |
265 (T3 (* T T T)) | 267 (T3 (* T T T)) |
301 (A11 (+ 291.34 (* 1.844379 k))) | 303 (A11 (+ 291.34 (* 1.844379 k))) |
302 (A12 (+ 161.72 (* 24.198154 k))) | 304 (A12 (+ 161.72 (* 24.198154 k))) |
303 (A13 (+ 239.56 (* 25.513099 k))) | 305 (A13 (+ 239.56 (* 25.513099 k))) |
304 (A14 (+ 331.55 (* 3.592518 k))) | 306 (A14 (+ 331.55 (* 3.592518 k))) |
305 (correction | 307 (correction |
306 (+ (* -0.40720 (solar-sin-degrees moon-anomaly)) | 308 (+ (* -0.40720 (solar-sin-degrees moon-anomaly)) |
307 (* 0.17241 E (solar-sin-degrees sun-anomaly)) | 309 (* 0.17241 E (solar-sin-degrees sun-anomaly)) |
308 (* 0.01608 (solar-sin-degrees (* 2 moon-anomaly))) | 310 (* 0.01608 (solar-sin-degrees (* 2 moon-anomaly))) |
309 (* 0.01039 (solar-sin-degrees (* 2 moon-argument))) | 311 (* 0.01039 (solar-sin-degrees (* 2 moon-argument))) |
310 (* 0.00739 E (solar-sin-degrees (- moon-anomaly sun-anomaly))) | 312 (* 0.00739 E (solar-sin-degrees (- moon-anomaly sun-anomaly))) |
311 (* -0.00514 E (solar-sin-degrees (+ moon-anomaly sun-anomaly))) | 313 (* -0.00514 E (solar-sin-degrees (+ moon-anomaly sun-anomaly))) |
312 (* 0.00208 E E (solar-sin-degrees (* 2 sun-anomaly))) | 314 (* 0.00208 E E (solar-sin-degrees (* 2 sun-anomaly))) |
313 (* -0.00111 (solar-sin-degrees | 315 (* -0.00111 (solar-sin-degrees |
314 (- moon-anomaly (* 2 moon-argument)))) | 316 (- moon-anomaly (* 2 moon-argument)))) |
315 (* -0.00057 (solar-sin-degrees | 317 (* -0.00057 (solar-sin-degrees |
316 (+ moon-anomaly (* 2 moon-argument)))) | 318 (+ moon-anomaly (* 2 moon-argument)))) |
317 (* 0.00056 E (solar-sin-degrees | 319 (* 0.00056 E (solar-sin-degrees |
318 (+ (* 2 moon-anomaly) sun-anomaly))) | 320 (+ (* 2 moon-anomaly) sun-anomaly))) |
319 (* -0.00042 (solar-sin-degrees (* 3 moon-anomaly))) | 321 (* -0.00042 (solar-sin-degrees (* 3 moon-anomaly))) |
320 (* 0.00042 E (solar-sin-degrees | 322 (* 0.00042 E (solar-sin-degrees |
321 (+ sun-anomaly (* 2 moon-argument)))) | 323 (+ sun-anomaly (* 2 moon-argument)))) |
322 (* 0.00038 E (solar-sin-degrees | 324 (* 0.00038 E (solar-sin-degrees |
323 (- sun-anomaly (* 2 moon-argument)))) | 325 (- sun-anomaly (* 2 moon-argument)))) |
324 (* -0.00024 E (solar-sin-degrees | 326 (* -0.00024 E (solar-sin-degrees |
325 (- (* 2 moon-anomaly) sun-anomaly))) | 327 (- (* 2 moon-anomaly) sun-anomaly))) |
326 (* -0.00017 (solar-sin-degrees omega)) | 328 (* -0.00017 (solar-sin-degrees omega)) |
327 (* -0.00007 (solar-sin-degrees | 329 (* -0.00007 (solar-sin-degrees |
328 (+ moon-anomaly (* 2 sun-anomaly)))) | 330 (+ moon-anomaly (* 2 sun-anomaly)))) |
329 (* 0.00004 (solar-sin-degrees | 331 (* 0.00004 (solar-sin-degrees |
330 (- (* 2 moon-anomaly) (* 2 moon-argument)))) | 332 (- (* 2 moon-anomaly) (* 2 moon-argument)))) |
331 (* 0.00004 (solar-sin-degrees (* 3 sun-anomaly))) | 333 (* 0.00004 (solar-sin-degrees (* 3 sun-anomaly))) |
332 (* 0.00003 (solar-sin-degrees (+ moon-anomaly sun-anomaly | 334 (* 0.00003 (solar-sin-degrees (+ moon-anomaly sun-anomaly |
333 (* -2 moon-argument)))) | 335 (* -2 moon-argument)))) |
334 (* 0.00003 (solar-sin-degrees | 336 (* 0.00003 (solar-sin-degrees |
335 (+ (* 2 moon-anomaly) (* 2 moon-argument)))) | 337 (+ (* 2 moon-anomaly) (* 2 moon-argument)))) |
336 (* -0.00003 (solar-sin-degrees (+ moon-anomaly sun-anomaly | 338 (* -0.00003 (solar-sin-degrees (+ moon-anomaly sun-anomaly |
337 (* 2 moon-argument)))) | 339 (* 2 moon-argument)))) |
338 (* 0.00003 (solar-sin-degrees (- moon-anomaly sun-anomaly | 340 (* 0.00003 (solar-sin-degrees (- moon-anomaly sun-anomaly |
339 (* -2 moon-argument)))) | 341 (* -2 moon-argument)))) |
340 (* -0.00002 (solar-sin-degrees (- moon-anomaly sun-anomaly | 342 (* -0.00002 (solar-sin-degrees (- moon-anomaly sun-anomaly |
341 (* 2 moon-argument)))) | 343 (* 2 moon-argument)))) |
342 (* -0.00002 (solar-sin-degrees | 344 (* -0.00002 (solar-sin-degrees |
343 (+ (* 3 moon-anomaly) sun-anomaly))) | 345 (+ (* 3 moon-anomaly) sun-anomaly))) |
344 (* 0.00002 (solar-sin-degrees (* 4 moon-anomaly))))) | 346 (* 0.00002 (solar-sin-degrees (* 4 moon-anomaly))))) |
345 (additional | 347 (additional |
346 (+ (* 0.000325 (solar-sin-degrees A1)) | 348 (+ (* 0.000325 (solar-sin-degrees A1)) |
347 (* 0.000165 (solar-sin-degrees A2)) | 349 (* 0.000165 (solar-sin-degrees A2)) |
348 (* 0.000164 (solar-sin-degrees A3)) | 350 (* 0.000164 (solar-sin-degrees A3)) |
349 (* 0.000126 (solar-sin-degrees A4)) | 351 (* 0.000126 (solar-sin-degrees A4)) |
350 (* 0.000110 (solar-sin-degrees A5)) | 352 (* 0.000110 (solar-sin-degrees A5)) |
351 (* 0.000062 (solar-sin-degrees A6)) | 353 (* 0.000062 (solar-sin-degrees A6)) |
352 (* 0.000060 (solar-sin-degrees A7)) | 354 (* 0.000060 (solar-sin-degrees A7)) |
353 (* 0.000056 (solar-sin-degrees A8)) | 355 (* 0.000056 (solar-sin-degrees A8)) |
354 (* 0.000047 (solar-sin-degrees A9)) | 356 (* 0.000047 (solar-sin-degrees A9)) |
355 (* 0.000042 (solar-sin-degrees A10)) | 357 (* 0.000042 (solar-sin-degrees A10)) |
356 (* 0.000040 (solar-sin-degrees A11)) | 358 (* 0.000040 (solar-sin-degrees A11)) |
357 (* 0.000037 (solar-sin-degrees A12)) | 359 (* 0.000037 (solar-sin-degrees A12)) |
358 (* 0.000035 (solar-sin-degrees A13)) | 360 (* 0.000035 (solar-sin-degrees A13)) |
359 (* 0.000023 (solar-sin-degrees A14)))) | 361 (* 0.000023 (solar-sin-degrees A14)))) |
360 (newJDE (+ JDE correction additional))) | 362 (newJDE (+ JDE correction additional))) |
361 (+ newJDE | 363 (+ newJDE |
362 (- (solar-ephemeris-correction | 364 (- (solar-ephemeris-correction |
363 (extract-calendar-year | 365 (extract-calendar-year |
364 (calendar-gregorian-from-absolute | 366 (calendar-gregorian-from-absolute |
368 (defun lunar-new-moon-on-or-after (d) | 370 (defun lunar-new-moon-on-or-after (d) |
369 "Julian day number of first new moon on or after Julian day number D. | 371 "Julian day number of first new moon on or after Julian day number D. |
370 The fractional part is the time of day. | 372 The fractional part is the time of day. |
371 | 373 |
372 The date and time are local time, including any daylight saving rules, | 374 The date and time are local time, including any daylight saving rules, |
373 as governed by the values of calendar-daylight-savings-starts, | 375 as governed by the values of `calendar-daylight-savings-starts', |
374 calendar-daylight-savings-starts-time, calendar-daylight-savings-ends, | 376 `calendar-daylight-savings-starts-time', `calendar-daylight-savings-ends', |
375 calendar-daylight-savings-ends-time, calendar-daylight-time-offset, and | 377 `calendar-daylight-savings-ends-time', `calendar-daylight-time-offset', and |
376 calendar-time-zone." | 378 `calendar-time-zone'." |
377 (let* ((date (calendar-gregorian-from-absolute | 379 (let* ((date (calendar-gregorian-from-absolute |
378 (floor (calendar-absolute-from-astro d)))) | 380 (floor (calendar-absolute-from-astro d)))) |
379 (year (+ (extract-calendar-year date) | 381 (year (+ (extract-calendar-year date) |
380 (/ (calendar-day-number date) 365.25))) | 382 (/ (calendar-day-number date) 365.25))) |
381 (k (floor (* (- year 2000.0) 12.3685))) | 383 (k (floor (* (- year 2000.0) 12.3685))) |
382 (date (lunar-new-moon-time k))) | 384 (date (lunar-new-moon-time k))) |
383 (while (< date d) | 385 (while (< date d) |
384 (setq k (1+ k)) | 386 (setq k (1+ k) |
385 (setq date (lunar-new-moon-time k))) | 387 date (lunar-new-moon-time k))) |
386 (let* ((a-date (calendar-absolute-from-astro date)) | 388 (let* ((a-date (calendar-absolute-from-astro date)) |
387 (time (* 24 (- a-date (truncate a-date)))) | 389 (time (* 24 (- a-date (truncate a-date)))) |
388 (date (calendar-gregorian-from-absolute (truncate a-date))) | 390 (date (calendar-gregorian-from-absolute (truncate a-date))) |
389 (adj (dst-adjust-time date time))) | 391 (adj (dst-adjust-time date time))) |
390 (calendar-astro-from-absolute | 392 (calendar-astro-from-absolute |
391 (+ (calendar-absolute-from-gregorian (car adj)) | 393 (+ (calendar-absolute-from-gregorian (car adj)) |
392 (/ (car (cdr adj)) 24.0)))))) | 394 (/ (cadr adj) 24.0)))))) |
393 | 395 |
394 (provide 'lunar) | 396 (provide 'lunar) |
395 | 397 |
396 ;; arch-tag: 72f0b8a4-7bcc-4a1b-b67a-ff53c4a1d222 | 398 ;; arch-tag: 72f0b8a4-7bcc-4a1b-b67a-ff53c4a1d222 |
397 ;;; lunar.el ends here | 399 ;;; lunar.el ends here |