aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2008-03-13 04:04:14 +0000
committerGlenn Morris2008-03-13 04:04:14 +0000
commitf575f9aba955d32111ef6487aa64317b28e653f4 (patch)
treeb59385dcc531a24b3f98ef64749b7c77fedf7fe8
parent43d671a398a332b580ed42e8b9c45d27c38c3c5d (diff)
downloademacs-f575f9aba955d32111ef6487aa64317b28e653f4.tar.gz
emacs-f575f9aba955d32111ef6487aa64317b28e653f4.zip
(solar-moment, solar-exact-local-noon)
(solar-sunrise-sunset, solar-sunrise-sunset-string) (solar-ephemeris-time, solar-date-next-longitude, solar-sidereal-time): (diary-sabbath-candles, solar-equinoxes/solstices) (solar-equinoxes-solstices): Use cadr, cdar, nth, zerop. (solar-time-equation, solar-date-to-et): Simplify.
-rw-r--r--lisp/calendar/solar.el482
1 files changed, 234 insertions, 248 deletions
diff --git a/lisp/calendar/solar.el b/lisp/calendar/solar.el
index fe61c0d8562..90cebd59d2e 100644
--- a/lisp/calendar/solar.el
+++ b/lisp/calendar/solar.el
@@ -4,11 +4,10 @@
4;; 2006, 2007, 2008 Free Software Foundation, Inc. 4;; 2006, 2007, 2008 Free Software Foundation, Inc.
5 5
6;; Author: Edward M. Reingold <reingold@cs.uiuc.edu> 6;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
7;; Denis B. Roegel <Denis.Roegel@loria.fr> 7;; Denis B. Roegel <Denis.Roegel@loria.fr>
8;; Maintainer: Glenn Morris <rgm@gnu.org> 8;; Maintainer: Glenn Morris <rgm@gnu.org>
9;; Keywords: calendar 9;; Keywords: calendar
10;; Human-Keywords: sunrise, sunset, equinox, solstice, calendar, diary, 10;; Human-Keywords: sunrise, sunset, equinox, solstice, calendar, diary, holidays
11;; holidays
12 11
13;; This file is part of GNU Emacs. 12;; This file is part of GNU Emacs.
14 13
@@ -68,7 +67,7 @@
68 67
69(defcustom calendar-time-display-form 68(defcustom calendar-time-display-form
70 '(12-hours ":" minutes am-pm 69 '(12-hours ":" minutes am-pm
71 (if time-zone " (") time-zone (if time-zone ")")) 70 (if time-zone " (") time-zone (if time-zone ")"))
72 "The pseudo-pattern that governs the way a time of day is formatted. 71 "The pseudo-pattern that governs the way a time of day is formatted.
73 72
74A pseudo-pattern is a list of expressions that can involve the keywords 73A pseudo-pattern is a list of expressions that can involve the keywords
@@ -93,13 +92,13 @@ York City.
93 92
94This variable should be set in `site-start'.el." 93This variable should be set in `site-start'.el."
95 :type '(choice (const nil) 94 :type '(choice (const nil)
96 (number :tag "Exact") 95 (number :tag "Exact")
97 (vector :value [0 0 north] 96 (vector :value [0 0 north]
98 (integer :tag "Degrees") 97 (integer :tag "Degrees")
99 (integer :tag "Minutes") 98 (integer :tag "Minutes")
100 (choice :tag "Position" 99 (choice :tag "Position"
101 (const north) 100 (const north)
102 (const south)))) 101 (const south))))
103 :group 'calendar) 102 :group 'calendar)
104 103
105(defcustom calendar-longitude nil 104(defcustom calendar-longitude nil
@@ -111,13 +110,13 @@ York City.
111 110
112This variable should be set in `site-start'.el." 111This variable should be set in `site-start'.el."
113 :type '(choice (const nil) 112 :type '(choice (const nil)
114 (number :tag "Exact") 113 (number :tag "Exact")
115 (vector :value [0 0 west] 114 (vector :value [0 0 west]
116 (integer :tag "Degrees") 115 (integer :tag "Degrees")
117 (integer :tag "Minutes") 116 (integer :tag "Minutes")
118 (choice :tag "Position" 117 (choice :tag "Position"
119 (const east) 118 (const east)
120 (const west)))) 119 (const west))))
121 :group 'calendar) 120 :group 'calendar)
122 121
123(defcustom calendar-location-name 122(defcustom calendar-location-name
@@ -146,7 +145,7 @@ This variable should be set in `site-start'.el."
146 :group 'calendar) 145 :group 'calendar)
147 146
148(defcustom solar-error 0.5 147(defcustom solar-error 0.5
149"Tolerance (in minutes) for sunrise/sunset calculations. 148 "Tolerance (in minutes) for sunrise/sunset calculations.
150 149
151A larger value makes the calculations for sunrise/sunset faster, but less 150A larger value makes the calculations for sunrise/sunset faster, but less
152accurate. The default is half a minute (30 seconds), so that sunrise/sunset 151accurate. The default is half a minute (30 seconds), so that sunrise/sunset
@@ -179,8 +178,8 @@ delta. At present, delta = 0.01 degrees, so the value of the variable
179 "List of season changes for the southern hemisphere.") 178 "List of season changes for the southern hemisphere.")
180 179
181(defvar solar-sidereal-time-greenwich-midnight 180(defvar solar-sidereal-time-greenwich-midnight
182 nil 181 nil
183 "Sidereal time at Greenwich at midnight (universal time).") 182 "Sidereal time at Greenwich at midnight (universal time).")
184 183
185(defvar solar-northern-spring-or-summer-season nil 184(defvar solar-northern-spring-or-summer-season nil
186 "Non-nil if northern spring or summer and nil otherwise. 185 "Non-nil if northern spring or summer and nil otherwise.
@@ -202,7 +201,7 @@ Needed for polar areas, in order to know whether the day lasts 0 or 24 hours.")
202 (if (numberp calendar-longitude) 201 (if (numberp calendar-longitude)
203 calendar-longitude 202 calendar-longitude
204 (let ((long (+ (aref calendar-longitude 0) 203 (let ((long (+ (aref calendar-longitude 0)
205 (/ (aref calendar-longitude 1) 60.0)))) 204 (/ (aref calendar-longitude 1) 60.0))))
206 (if (equal (aref calendar-longitude 2) 'east) 205 (if (equal (aref calendar-longitude 2) 'east)
207 long 206 long
208 (- long))))) 207 (- long)))))
@@ -221,8 +220,8 @@ Needed for polar areas, in order to know whether the day lasts 0 or 24 hours.")
221 (or calendar-time-zone 220 (or calendar-time-zone
222 (setq calendar-time-zone 221 (setq calendar-time-zone
223 (solar-get-number 222 (solar-get-number
224 "Enter difference from Coordinated Universal Time (in \ 223 "Enter difference from Coordinated Universal Time (in minutes): ")
225minutes): ")))) 224 )))
226 225
227(defun solar-get-number (prompt) 226(defun solar-get-number (prompt)
228 "Return a number from the minibuffer, prompting with PROMPT. 227 "Return a number from the minibuffer, prompting with PROMPT.
@@ -247,7 +246,7 @@ Returns nil if nothing was entered."
247 "Determine the quadrant of the point X, Y." 246 "Determine the quadrant of the point X, Y."
248 (if (> x 0) 247 (if (> x 0)
249 (if (> y 0) 1 4) 248 (if (> y 0) 1 4)
250 (if (> y 0) 2 3))) 249 (if (> y 0) 2 3)))
251 250
252(defun solar-degrees-to-quadrant (angle) 251(defun solar-degrees-to-quadrant (angle)
253 "Determine the quadrant of ANGLE degrees." 252 "Determine the quadrant of ANGLE degrees."
@@ -256,16 +255,16 @@ Returns nil if nothing was entered."
256(defun solar-arctan (x quad) 255(defun solar-arctan (x quad)
257 "Arctangent of X in quadrant QUAD." 256 "Arctangent of X in quadrant QUAD."
258 (let ((deg (radians-to-degrees (atan x)))) 257 (let ((deg (radians-to-degrees (atan x))))
259 (cond ((equal quad 2) (+ deg 180)) 258 (cond ((equal quad 2) (+ deg 180))
260 ((equal quad 3) (+ deg 180)) 259 ((equal quad 3) (+ deg 180))
261 ((equal quad 4) (+ deg 360)) 260 ((equal quad 4) (+ deg 360))
262 (t deg)))) 261 (t deg))))
263 262
264(defun solar-atn2 (x y) 263(defun solar-atn2 (x y)
265 "Arctangent of point X, Y." 264 "Arctangent of point X, Y."
266 (if (zerop x) 265 (if (zerop x)
267 (if (> y 0) 90 270) 266 (if (> y 0) 90 270)
268 (solar-arctan (/ y x) (solar-xy-to-quadrant x y)))) 267 (solar-arctan (/ y x) (solar-xy-to-quadrant x y))))
269 268
270(defun solar-arccos (x) 269(defun solar-arccos (x)
271 "Arccosine of X." 270 "Arccosine of X."
@@ -325,7 +324,7 @@ degrees to find out if polar regions have 24 hours of sun or only night."
325 (and (< latitude 0) 324 (and (< latitude 0)
326 (not solar-northern-spring-or-summer-season))) 325 (not solar-northern-spring-or-summer-season)))
327 (setq day-length 24) 326 (setq day-length 24)
328 (setq day-length 0)) 327 (setq day-length 0))
329 (setq day-length (- set-time rise-time))) 328 (setq day-length (- set-time rise-time)))
330 (list (if rise-time (+ rise-time (/ calendar-time-zone 60.0)) nil) 329 (list (if rise-time (+ rise-time (/ calendar-time-zone 60.0)) nil)
331 (if set-time (+ set-time (/ calendar-time-zone 60.0)) nil) 330 (if set-time (+ set-time (/ calendar-time-zone 60.0)) nil)
@@ -347,7 +346,7 @@ we are trying to find. For sunrise and sunset, it is usually -0.61 degrees,
347accounting for the edge of the sun being on the horizon. 346accounting for the edge of the sun being on the horizon.
348 347
349Uses binary search." 348Uses binary search."
350 (let* ((ut (car (cdr time))) 349 (let* ((ut (cadr time))
351 (possible t) ; we assume that rise or set are possible 350 (possible t) ; we assume that rise or set are possible
352 (utmin (+ ut (* direction 12.0))) 351 (utmin (+ ut (* direction 12.0)))
353 (utmax ut) ; the time searched is between utmin and utmax 352 (utmax ut) ; the time searched is between utmin and utmax
@@ -356,41 +355,37 @@ Uses binary search."
356 (utmoment 1.0) ; rise or set approximation 355 (utmoment 1.0) ; rise or set approximation
357 (hut 0) ; sun height at utmoment 356 (hut 0) ; sun height at utmoment
358 (t0 (car time)) 357 (t0 (car time))
359 (hmin (car (cdr 358 (hmin (cadr (solar-horizontal-coordinates (list t0 utmin)
360 (solar-horizontal-coordinates (list t0 utmin) 359 latitude longitude t)))
361 latitude longitude t)))) 360 (hmax (cadr (solar-horizontal-coordinates (list t0 utmax)
362 (hmax (car (cdr 361 latitude longitude t))))
363 (solar-horizontal-coordinates (list t0 utmax)
364 latitude longitude t)))))
365 ;; -0.61 degrees is the height of the middle of the sun, when it 362 ;; -0.61 degrees is the height of the middle of the sun, when it
366 ;; rises or sets. 363 ;; rises or sets.
367 (if (< hmin height) 364 (if (< hmin height)
368 (if (> hmax height) 365 (if (> hmax height)
369 (while ;;; (< i 20) ; we perform a simple dichotomy 366 (while ;;; (< i 20) ; we perform a simple dichotomy
370 ;;; (> (abs (- hut height)) epsilon) 367;;; (> (abs (- hut height)) epsilon)
371 (>= (abs (- utmoment utmoment-old)) 368 (>= (abs (- utmoment utmoment-old))
372 (/ solar-error 60)) 369 (/ solar-error 60))
373 (setq utmoment-old utmoment) 370 (setq utmoment-old utmoment
374 (setq utmoment (/ (+ utmin utmax) 2)) 371 utmoment (/ (+ utmin utmax) 2)
375 (setq hut (car (cdr 372 hut (cadr (solar-horizontal-coordinates
376 (solar-horizontal-coordinates 373 (list t0 utmoment) latitude longitude t)))
377 (list t0 utmoment) latitude longitude t)))) 374 (if (< hut height) (setq utmin utmoment))
378 (if (< hut height) (setq utmin utmoment)) 375 (if (> hut height) (setq utmax utmoment)))
379 (if (> hut height) (setq utmax utmoment)) 376 (setq possible nil)) ; the sun never rises
380 ) 377 (setq possible nil)) ; the sun never sets
381 (setq possible nil)) ; the sun never rises 378 (if possible utmoment)))
382 (setq possible nil)) ; the sun never sets
383 (if (not possible) nil utmoment)))
384 379
385(defun solar-time-string (time time-zone) 380(defun solar-time-string (time time-zone)
386 "Printable form for decimal fraction TIME in TIME-ZONE. 381 "Printable form for decimal fraction TIME in TIME-ZONE.
387Format used is given by `calendar-time-display-form'." 382Format used is given by `calendar-time-display-form'."
388 (let* ((time (round (* 60 time))) 383 (let* ((time (round (* 60 time)))
389 (24-hours (/ time 60)) 384 (24-hours (/ time 60))
390 (minutes (format "%02d" (% time 60))) 385 (minutes (format "%02d" (% time 60)))
391 (12-hours (format "%d" (1+ (% (+ 24-hours 11) 12)))) 386 (12-hours (format "%d" (1+ (% (+ 24-hours 11) 12))))
392 (am-pm (if (>= 24-hours 12) "pm" "am")) 387 (am-pm (if (>= 24-hours 12) "pm" "am"))
393 (24-hours (format "%02d" 24-hours))) 388 (24-hours (format "%02d" 24-hours)))
394 (mapconcat 'eval calendar-time-display-form ""))) 389 (mapconcat 'eval calendar-time-display-form "")))
395 390
396 391
@@ -409,18 +404,15 @@ local date. The second component of date should be an integer."
409 (te (solar-time-equation date ut))) 404 (te (solar-time-equation date ut)))
410 (setq ut (- ut te)) 405 (setq ut (- ut te))
411 (if (>= ut 24) 406 (if (>= ut 24)
412 (progn 407 (setq nd (list (car date) (1+ (cadr date))
413 (setq nd (list (car date) (+ 1 (car (cdr date))) 408 (nth 2 date))
414 (car (cdr (cdr date))))) 409 ut (- ut 24)))
415 (setq ut (- ut 24))))
416 (if (< ut 0) 410 (if (< ut 0)
417 (progn 411 (setq nd (list (car date) (1- (cadr date))
418 (setq nd (list (car date) (- (car (cdr date)) 1) 412 (nth 2 date))
419 (car (cdr (cdr date))))) 413 ut (+ ut 24)))
420 (setq ut (+ ut 24)))) 414 (setq nd (calendar-gregorian-from-absolute ; date standardization
421 (setq nd (calendar-gregorian-from-absolute 415 (calendar-absolute-from-gregorian nd)))
422 (calendar-absolute-from-gregorian nd)))
423 ; date standardization
424 (list nd ut))) 416 (list nd ut)))
425 417
426(defun solar-sunrise-sunset (date) 418(defun solar-sunrise-sunset (date)
@@ -436,7 +428,7 @@ Corresponding value is nil if there is no sunrise/sunset."
436 (progn (setq solar-sidereal-time-greenwich-midnight 428 (progn (setq solar-sidereal-time-greenwich-midnight
437 (solar-sidereal-time t0)) 429 (solar-sidereal-time t0))
438 (solar-sunrise-and-sunset 430 (solar-sunrise-and-sunset
439 (list t0 (car (cdr exact-local-noon))) 431 (list t0 (cadr exact-local-noon))
440 1.0 432 1.0
441 (calendar-longitude) 0))) 433 (calendar-longitude) 0)))
442 ;; Store the spring/summer information, compute sunrise and 434 ;; Store the spring/summer information, compute sunrise and
@@ -446,16 +438,16 @@ Corresponding value is nil if there is no sunrise/sunset."
446 (rise-set 438 (rise-set
447 (progn 439 (progn
448 (setq solar-northern-spring-or-summer-season 440 (setq solar-northern-spring-or-summer-season
449 (if (> (car (cdr (cdr equator-rise-set))) 12) t nil)) 441 (> (nth 2 equator-rise-set) 12))
450 (solar-sunrise-and-sunset 442 (solar-sunrise-and-sunset
451 (list t0 (car (cdr exact-local-noon))) 443 (list t0 (cadr exact-local-noon))
452 (calendar-latitude) 444 (calendar-latitude)
453 (calendar-longitude) -0.61))) 445 (calendar-longitude) -0.61)))
454 (rise (car rise-set)) 446 (rise (car rise-set))
455 (adj-rise (if rise (dst-adjust-time date rise) nil)) 447 (adj-rise (if rise (dst-adjust-time date rise)))
456 (set (car (cdr rise-set))) 448 (set (cadr rise-set)) ; FIXME ?
457 (adj-set (if set (dst-adjust-time date set) nil)) 449 (adj-set (if set (dst-adjust-time date set)))
458 (length (car (cdr (cdr rise-set)))) ) 450 (length (nth 2 rise-set)))
459 (list 451 (list
460 (and rise (calendar-date-equal date (car adj-rise)) (cdr adj-rise)) 452 (and rise (calendar-date-equal date (car adj-rise)) (cdr adj-rise))
461 (and set (calendar-date-equal date (car adj-set)) (cdr adj-set)) 453 (and set (calendar-date-equal date (car adj-set)) (cdr adj-set))
@@ -469,11 +461,11 @@ Corresponding value is nil if there is no sunrise/sunset."
469 (if (car l) 461 (if (car l)
470 (concat "Sunrise " (apply 'solar-time-string (car l))) 462 (concat "Sunrise " (apply 'solar-time-string (car l)))
471 "No sunrise") 463 "No sunrise")
472 (if (car (cdr l)) 464 (if (cadr l)
473 (concat "sunset " (apply 'solar-time-string (car (cdr l)))) 465 (concat "sunset " (apply 'solar-time-string (cadr l)))
474 "no sunset") 466 "no sunset")
475 (eval calendar-location-name) 467 (eval calendar-location-name)
476 (car (cdr (cdr l)))))) 468 (nth 2 l))))
477 469
478(defun solar-julian-ut-centuries (date) 470(defun solar-julian-ut-centuries (date)
479 "Number of Julian centuries since 1 Jan, 2000 at noon UT for Gregorian DATE." 471 "Number of Julian centuries since 1 Jan, 2000 at noon UT for Gregorian DATE."
@@ -491,11 +483,11 @@ Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT.
491 483
492Result is in Julian centuries of ephemeris time." 484Result is in Julian centuries of ephemeris time."
493 (let* ((t0 (car time)) 485 (let* ((t0 (car time))
494 (ut (car (cdr time))) 486 (ut (cadr time))
495 (t1 (+ t0 (/ (/ ut 24.0) 36525))) 487 (t1 (+ t0 (/ (/ ut 24.0) 36525)))
496 (y (+ 2000 (* 100 t1))) 488 (y (+ 2000 (* 100 t1)))
497 (dt (* 86400 (solar-ephemeris-correction (floor y))))) 489 (dt (* 86400 (solar-ephemeris-correction (floor y)))))
498 (+ t1 (/ (/ dt 86400) 36525)))) 490 (+ t1 (/ (/ dt 86400) 36525))))
499 491
500(defun solar-date-next-longitude (d l) 492(defun solar-date-next-longitude (d l)
501 "First time after day D when solar longitude is a multiple of L degrees. 493 "First time after day D when solar longitude is a multiple of L degrees.
@@ -518,15 +510,14 @@ and `calendar-time-zone' are used to interpret local time."
518 ;; start-long <= next < end-long when next != 0 510 ;; start-long <= next < end-long when next != 0
519 ;; when next = 0, we look for the discontinuity (start-long is near 360 511 ;; when next = 0, we look for the discontinuity (start-long is near 360
520 ;; and end-long is small (less than l). 512 ;; and end-long is small (less than l).
521 (setq d (/ (+ start end) 2.0)) 513 (setq d (/ (+ start end) 2.0)
522 (setq long (solar-longitude d)) 514 long (solar-longitude d))
523 (if (or (and (/= next 0) (< long next)) 515 (if (or (and (not (zerop next)) (< long next))
524 (and (= next 0) (< l long))) 516 (and (zerop next) (< l long)))
525 (progn 517 (setq start d
526 (setq start d) 518 start-long long)
527 (setq start-long long)) 519 (setq end d
528 (setq end d) 520 end-long long)))
529 (setq end-long long)))
530 (/ (+ start end) 2.0))) 521 (/ (+ start end) 2.0)))
531 522
532(defun solar-horizontal-coordinates (time latitude longitude sunrise-flag) 523(defun solar-horizontal-coordinates (time latitude longitude sunrise-flag)
@@ -547,9 +538,9 @@ height (between -180 and 180) are both in degrees."
547 (ah (- (* st 15) (* 15 (car ec)) (* -1 (calendar-longitude)))) 538 (ah (- (* st 15) (* 15 (car ec)) (* -1 (calendar-longitude))))
548 (de (cadr ec)) 539 (de (cadr ec))
549 (azimuth (solar-atn2 (- (* (solar-cosine-degrees ah) 540 (azimuth (solar-atn2 (- (* (solar-cosine-degrees ah)
550 (solar-sin-degrees latitude)) 541 (solar-sin-degrees latitude))
551 (* (solar-tangent-degrees de) 542 (* (solar-tangent-degrees de)
552 (solar-cosine-degrees latitude))) 543 (solar-cosine-degrees latitude)))
553 (solar-sin-degrees ah))) 544 (solar-sin-degrees ah)))
554 (height (solar-arcsin 545 (height (solar-arcsin
555 (+ (* (solar-sin-degrees latitude) (solar-sin-degrees de)) 546 (+ (* (solar-sin-degrees latitude) (solar-sin-degrees de))
@@ -568,10 +559,10 @@ corresponding to November 28, 1995 at 16 UT is (-0.040945 16),
568-0.040945 being the number of Julian centuries elapsed between 559-0.040945 being the number of Julian centuries elapsed between
569Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT. SUNRISE-FLAG is passed 560Jan 1, 2000 at 12 UT and November 28, 1995 at 0 UT. SUNRISE-FLAG is passed
570to `solar-ecliptic-coordinates'." 561to `solar-ecliptic-coordinates'."
571 (let* ((tm (solar-ephemeris-time time)) 562 (let* ((tm (solar-ephemeris-time time))
572 (ec (solar-ecliptic-coordinates tm sunrise-flag))) 563 (ec (solar-ecliptic-coordinates tm sunrise-flag)))
573 (list (solar-right-ascension (car ec) (car (cdr ec))) 564 (list (solar-right-ascension (car ec) (car (cdr ec)))
574 (solar-declination (car ec) (car (cdr ec)))))) 565 (solar-declination (car ec) (car (cdr ec))))))
575 566
576(defun solar-ecliptic-coordinates (time sunrise-flag) 567(defun solar-ecliptic-coordinates (time sunrise-flag)
577 "Return solar longitude, ecliptic inclination, equation of time, nutation. 568 "Return solar longitude, ecliptic inclination, equation of time, nutation.
@@ -623,12 +614,12 @@ If SUNRISE-FLAG is non-nil, only calculate longitude and inclination."
623 ;; Equation of time, in hours. 614 ;; Equation of time, in hours.
624 (time-eq (unless sunrise-flag 615 (time-eq (unless sunrise-flag
625 (/ (* 12 (+ (* y (solar-sin-degrees (* 2 l))) 616 (/ (* 12 (+ (* y (solar-sin-degrees (* 2 l)))
626 (* -2 ecc (solar-sin-degrees m)) 617 (* -2 ecc (solar-sin-degrees m))
627 (* 4 ecc y (solar-sin-degrees m) 618 (* 4 ecc y (solar-sin-degrees m)
628 (solar-cosine-degrees (* 2 l))) 619 (solar-cosine-degrees (* 2 l)))
629 (* -0.5 y y (solar-sin-degrees (* 4 l))) 620 (* -0.5 y y (solar-sin-degrees (* 4 l)))
630 (* -1.25 ecc ecc (solar-sin-degrees (* 2 m))))) 621 (* -1.25 ecc ecc (solar-sin-degrees (* 2 m)))))
631 3.1415926535)))) 622 3.1415926535))))
632 (list app i time-eq nut))) 623 (list app i time-eq nut)))
633 624
634(defconst solar-data-list 625(defconst solar-data-list
@@ -712,11 +703,11 @@ The values of `calendar-daylight-savings-starts',
712 (* 0.0000001 703 (* 0.0000001
713 (apply '+ 704 (apply '+
714 (mapcar (lambda (x) 705 (mapcar (lambda (x)
715 (* (car x) 706 (* (car x)
716 (sin (mod 707 (sin (mod
717 (+ (car (cdr x)) 708 (+ (car (cdr x))
718 (* (car (cdr (cdr x))) U)) 709 (* (car (cdr (cdr x))) U))
719 (* 2 pi))))) 710 (* 2 pi)))))
720 solar-data-list))))) 711 solar-data-list)))))
721 (aberration 712 (aberration
722 (* 0.0000001 (- (* 17 (cos (+ 3.10 (* 62830.14 U)))) 973))) 713 (* 0.0000001 (- (* 17 (cos (+ 3.10 (* 62830.14 U)))) 973)))
@@ -787,30 +778,27 @@ Result is in days. For the years 1800-1987, the maximum error is
787(defun solar-sidereal-time (t0) 778(defun solar-sidereal-time (t0)
788 "Sidereal time (in hours) in Greenwich at T0 Julian centuries. 779 "Sidereal time (in hours) in Greenwich at T0 Julian centuries.
789T0 must correspond to 0 hours UT." 780T0 must correspond to 0 hours UT."
790 (let* ((mean-sid-time (+ 6.6973746 781 (let* ((mean-sid-time (+ 6.6973746
791 (* 2400.051337 t0) 782 (* 2400.051337 t0)
792 (* 0.0000258622 t0 t0) 783 (* 0.0000258622 t0 t0)
793 (* -0.0000000017222 t0 t0 t0))) 784 (* -0.0000000017222 t0 t0 t0)))
794 (et (solar-ephemeris-time (list t0 0.0))) 785 (et (solar-ephemeris-time (list t0 0.0)))
795 (nut-i (solar-ecliptic-coordinates et nil)) 786 (nut-i (solar-ecliptic-coordinates et nil))
796 (nut (car (cdr (cdr (cdr nut-i))))) ; nutation 787 (nut (nth 3 nut-i)) ; nutation
797 (i (car (cdr nut-i)))) ; inclination 788 (i (cadr nut-i))) ; inclination
798 (mod (+ (mod (+ mean-sid-time 789 (mod (+ (mod (+ mean-sid-time
799 (/ (/ (* nut (solar-cosine-degrees i)) 15) 3600)) 24.0) 790 (/ (/ (* nut (solar-cosine-degrees i)) 15) 3600)) 24.0)
800 24.0) 791 24.0)
801 24.0))) 792 24.0)))
802 793
803(defun solar-time-equation (date ut) 794(defun solar-time-equation (date ut)
804 "Equation of time expressed in hours at Gregorian DATE at Universal time UT." 795 "Equation of time expressed in hours at Gregorian DATE at Universal time UT."
805 (let* ((et (solar-date-to-et date ut)) 796 (nth 2 (solar-ecliptic-coordinates (solar-date-to-et date ut) nil)))
806 (ec (solar-ecliptic-coordinates et nil)))
807 (car (cdr (cdr ec)))))
808 797
809(defun solar-date-to-et (date ut) 798(defun solar-date-to-et (date ut)
810 "Ephemeris Time at Gregorian DATE at Universal Time UT (in hours). 799 "Ephemeris Time at Gregorian DATE at Universal Time UT (in hours).
811Expressed in Julian centuries of Ephemeris Time." 800Expressed in Julian centuries of Ephemeris Time."
812 (let ((t0 (solar-julian-ut-centuries date))) 801 (solar-ephemeris-time (list (solar-julian-ut-centuries date) ut)))
813 (solar-ephemeris-time (list t0 ut))))
814 802
815;;;###autoload 803;;;###autoload
816(defun sunrise-sunset (&optional arg) 804(defun sunrise-sunset (&optional arg)
@@ -820,68 +808,68 @@ If called with an optional double prefix argument, prompt for
820longitude, latitude, time zone, and date, and always use standard time. 808longitude, latitude, time zone, and date, and always use standard time.
821 809
822This function is suitable for execution in a .emacs file." 810This function is suitable for execution in a .emacs file."
823 (interactive "p") 811 (interactive "p")
824 (or arg (setq arg 1)) 812 (or arg (setq arg 1))
825 (if (and (< arg 16) 813 (if (and (< arg 16)
826 (not (and calendar-latitude calendar-longitude calendar-time-zone))) 814 (not (and calendar-latitude calendar-longitude calendar-time-zone)))
827 (solar-setup)) 815 (solar-setup))
828 (let* ((calendar-longitude 816 (let* ((calendar-longitude
829 (if (< arg 16) calendar-longitude 817 (if (< arg 16) calendar-longitude
830 (solar-get-number 818 (solar-get-number
831 "Enter longitude (decimal fraction; + east, - west): "))) 819 "Enter longitude (decimal fraction; + east, - west): ")))
832 (calendar-latitude 820 (calendar-latitude
833 (if (< arg 16) calendar-latitude 821 (if (< arg 16) calendar-latitude
834 (solar-get-number 822 (solar-get-number
835 "Enter latitude (decimal fraction; + north, - south): "))) 823 "Enter latitude (decimal fraction; + north, - south): ")))
836 (calendar-time-zone 824 (calendar-time-zone
837 (if (< arg 16) calendar-time-zone 825 (if (< arg 16) calendar-time-zone
838 (solar-get-number 826 (solar-get-number
839 "Enter difference from Coordinated Universal Time (in minutes): "))) 827 "Enter difference from Coordinated Universal Time (in minutes): ")))
840 (calendar-location-name 828 (calendar-location-name
841 (if (< arg 16) calendar-location-name 829 (if (< arg 16) calendar-location-name
842 (let ((float-output-format "%.1f")) 830 (let ((float-output-format "%.1f"))
843 (format "%s%s, %s%s" 831 (format "%s%s, %s%s"
844 (if (numberp calendar-latitude) 832 (if (numberp calendar-latitude)
845 (abs calendar-latitude) 833 (abs calendar-latitude)
846 (+ (aref calendar-latitude 0) 834 (+ (aref calendar-latitude 0)
847 (/ (aref calendar-latitude 1) 60.0))) 835 (/ (aref calendar-latitude 1) 60.0)))
848 (if (numberp calendar-latitude) 836 (if (numberp calendar-latitude)
849 (if (> calendar-latitude 0) "N" "S") 837 (if (> calendar-latitude 0) "N" "S")
850 (if (equal (aref calendar-latitude 2) 'north) "N" "S")) 838 (if (equal (aref calendar-latitude 2) 'north) "N" "S"))
851 (if (numberp calendar-longitude) 839 (if (numberp calendar-longitude)
852 (abs calendar-longitude) 840 (abs calendar-longitude)
853 (+ (aref calendar-longitude 0) 841 (+ (aref calendar-longitude 0)
854 (/ (aref calendar-longitude 1) 60.0))) 842 (/ (aref calendar-longitude 1) 60.0)))
855 (if (numberp calendar-longitude) 843 (if (numberp calendar-longitude)
856 (if (> calendar-longitude 0) "E" "W") 844 (if (> calendar-longitude 0) "E" "W")
857 (if (equal (aref calendar-longitude 2) 'east) 845 (if (equal (aref calendar-longitude 2) 'east)
858 "E" "W")))))) 846 "E" "W"))))))
859 (calendar-standard-time-zone-name 847 (calendar-standard-time-zone-name
860 (if (< arg 16) calendar-standard-time-zone-name 848 (if (< arg 16) calendar-standard-time-zone-name
861 (cond ((= calendar-time-zone 0) "UTC") 849 (cond ((= calendar-time-zone 0) "UTC")
862 ((< calendar-time-zone 0) 850 ((< calendar-time-zone 0)
863 (format "UTC%dmin" calendar-time-zone)) 851 (format "UTC%dmin" calendar-time-zone))
864 (t (format "UTC+%dmin" calendar-time-zone))))) 852 (t (format "UTC+%dmin" calendar-time-zone)))))
865 (calendar-daylight-savings-starts 853 (calendar-daylight-savings-starts
866 (if (< arg 16) calendar-daylight-savings-starts)) 854 (if (< arg 16) calendar-daylight-savings-starts))
867 (calendar-daylight-savings-ends 855 (calendar-daylight-savings-ends
868 (if (< arg 16) calendar-daylight-savings-ends)) 856 (if (< arg 16) calendar-daylight-savings-ends))
869 (date (if (< arg 4) (calendar-current-date) (calendar-read-date))) 857 (date (if (< arg 4) (calendar-current-date) (calendar-read-date)))
870 (date-string (calendar-date-string date t)) 858 (date-string (calendar-date-string date t))
871 (time-string (solar-sunrise-sunset-string date)) 859 (time-string (solar-sunrise-sunset-string date))
872 (msg (format "%s: %s" date-string time-string)) 860 (msg (format "%s: %s" date-string time-string))
873 (one-window (one-window-p t))) 861 (one-window (one-window-p t)))
874 (if (<= (length msg) (frame-width)) 862 (if (<= (length msg) (frame-width))
875 (message "%s" msg) 863 (message "%s" msg)
876 (with-output-to-temp-buffer "*temp*" 864 (with-output-to-temp-buffer "*temp*"
877 (princ (concat date-string "\n" time-string))) 865 (princ (concat date-string "\n" time-string)))
878 (message "%s" 866 (message "%s"
879 (substitute-command-keys 867 (substitute-command-keys
880 (if one-window 868 (if one-window
881 (if pop-up-windows 869 (if pop-up-windows
882 "Type \\[delete-other-windows] to remove temp window." 870 "Type \\[delete-other-windows] to remove temp window."
883 "Type \\[switch-to-buffer] RET to remove temp window.") 871 "Type \\[switch-to-buffer] RET to remove temp window.")
884 "Type \\[switch-to-buffer-other-window] RET to restore old \ 872 "Type \\[switch-to-buffer-other-window] RET to restore old \
885contents of temp window.")))))) 873contents of temp window."))))))
886 874
887(defun calendar-sunrise-sunset () 875(defun calendar-sunrise-sunset ()
@@ -914,16 +902,16 @@ An optional parameter MARK specifies a face or single-character string to
914use when highlighting the day in the calendar." 902use when highlighting the day in the calendar."
915 (or (and calendar-latitude calendar-longitude calendar-time-zone) 903 (or (and calendar-latitude calendar-longitude calendar-time-zone)
916 (solar-setup)) 904 (solar-setup))
917 (if (= (% (calendar-absolute-from-gregorian date) 7) 5) ; Friday 905 (if (= (% (calendar-absolute-from-gregorian date) 7) 5) ; Friday
918 (let* ((sunset (car (cdr (solar-sunrise-sunset date)))) 906 (let* ((sunset (cadr (solar-sunrise-sunset date)))
919 (light (if sunset 907 (light (if sunset
920 (cons (- (car sunset) 908 (cons (- (car sunset)
921 (/ diary-sabbath-candles-minutes 60.0)) 909 (/ diary-sabbath-candles-minutes 60.0))
922 (cdr sunset))))) 910 (cdr sunset)))))
923 (if sunset 911 (if sunset
924 (cons mark 912 (cons mark
925 (format "%s Sabbath candle lighting" 913 (format "%s Sabbath candle lighting"
926 (apply 'solar-time-string light))))))) 914 (apply 'solar-time-string light)))))))
927 915
928;; From Meeus, 1991, page 167. 916;; From Meeus, 1991, page 167.
929(defconst solar-seasons-data 917(defconst solar-seasons-data
@@ -962,22 +950,20 @@ Accurate to within a minute between 1951 and 2050."
962 (T (/ (- JDE0 2451545.0) 36525)) 950 (T (/ (- JDE0 2451545.0) 36525))
963 (W (- (* 35999.373 T) 2.47)) 951 (W (- (* 35999.373 T) 2.47))
964 (Delta-lambda (+ 1 (* 0.0334 (solar-cosine-degrees W)) 952 (Delta-lambda (+ 1 (* 0.0334 (solar-cosine-degrees W))
965 (* 0.0007 (solar-cosine-degrees (* 2 W))))) 953 (* 0.0007 (solar-cosine-degrees (* 2 W)))))
966 (S (apply '+ (mapcar (lambda(x) 954 (S (apply '+ (mapcar (lambda(x)
967 (* (car x) (solar-cosine-degrees 955 (* (car x) (solar-cosine-degrees
968 (+ (* (car (cdr (cdr x))) T) 956 (+ (* (nth 2 x) T) (cadr x)))))
969 (car (cdr x))))))
970 solar-seasons-data))) 957 solar-seasons-data)))
971 (JDE (+ JDE0 (/ (* 0.00001 S) Delta-lambda))) 958 (JDE (+ JDE0 (/ (* 0.00001 S) Delta-lambda)))
972 ;; Ephemeris time correction. 959 ;; Ephemeris time correction.
973 (correction (+ 102.3 (* 123.5 T) (* 32.5 T T))) 960 (correction (+ 102.3 (* 123.5 T) (* 32.5 T T)))
974 (JD (- JDE (/ correction 86400))) 961 (JD (- JDE (/ correction 86400)))
975 (date (calendar-gregorian-from-absolute (floor (- JD 1721424.5)))) 962 (date (calendar-gregorian-from-absolute (floor (- JD 1721424.5))))
976 (time (- (- JD 0.5) (floor (- JD 0.5)))) 963 (time (- (- JD 0.5) (floor (- JD 0.5)))))
977 ) 964 (list (car date) (+ (cadr date) time
978 (list (car date) (+ (car (cdr date)) time 965 (/ (/ calendar-time-zone 60.0) 24.0))
979 (/ (/ calendar-time-zone 60.0) 24.0)) 966 (nth 2 date))))
980 (car (cdr (cdr date))))))
981 967
982;; From Meeus, 1991, page 166. 968;; From Meeus, 1991, page 166.
983(defun solar-mean-equinoxes/solstices (k year) 969(defun solar-mean-equinoxes/solstices (k year)
@@ -987,47 +973,47 @@ solstice. These formulas are only to be used between 1000 BC and 3000 AD."
987 (let ((y (/ year 1000.0)) 973 (let ((y (/ year 1000.0))
988 (z (/ (- year 2000) 1000.0))) 974 (z (/ (- year 2000) 1000.0)))
989 (if (< year 1000) ; actually between -1000 and 1000 975 (if (< year 1000) ; actually between -1000 and 1000
990 (cond ((equal k 0) (+ 1721139.29189 976 (cond ((equal k 0) (+ 1721139.29189
991 (* 365242.13740 y) 977 (* 365242.13740 y)
992 (* 0.06134 y y) 978 (* 0.06134 y y)
993 (* 0.00111 y y y) 979 (* 0.00111 y y y)
994 (* -0.00071 y y y y))) 980 (* -0.00071 y y y y)))
995 ((equal k 1) (+ 1721233.25401 981 ((equal k 1) (+ 1721233.25401
996 (* 365241.72562 y) 982 (* 365241.72562 y)
997 (* -0.05323 y y) 983 (* -0.05323 y y)
998 (* 0.00907 y y y) 984 (* 0.00907 y y y)
999 (* 0.00025 y y y y))) 985 (* 0.00025 y y y y)))
1000 ((equal k 2) (+ 1721325.70455 986 ((equal k 2) (+ 1721325.70455
1001 (* 365242.49558 y) 987 (* 365242.49558 y)
1002 (* -0.11677 y y) 988 (* -0.11677 y y)
1003 (* -0.00297 y y y) 989 (* -0.00297 y y y)
1004 (* 0.00074 y y y y))) 990 (* 0.00074 y y y y)))
1005 ((equal k 3) (+ 1721414.39987 991 ((equal k 3) (+ 1721414.39987
1006 (* 365242.88257 y) 992 (* 365242.88257 y)
1007 (* -0.00769 y y) 993 (* -0.00769 y y)
1008 (* -0.00933 y y y) 994 (* -0.00933 y y y)
1009 (* -0.00006 y y y y)))) 995 (* -0.00006 y y y y))))
1010 ; actually between 1000 and 3000 996 ; actually between 1000 and 3000
1011 (cond ((equal k 0) (+ 2451623.80984 997 (cond ((equal k 0) (+ 2451623.80984
1012 (* 365242.37404 z) 998 (* 365242.37404 z)
1013 (* 0.05169 z z) 999 (* 0.05169 z z)
1014 (* -0.00411 z z z) 1000 (* -0.00411 z z z)
1015 (* -0.00057 z z z z))) 1001 (* -0.00057 z z z z)))
1016 ((equal k 1) (+ 2451716.56767 1002 ((equal k 1) (+ 2451716.56767
1017 (* 365241.62603 z) 1003 (* 365241.62603 z)
1018 (* 0.00325 z z) 1004 (* 0.00325 z z)
1019 (* 0.00888 z z z) 1005 (* 0.00888 z z z)
1020 (* -0.00030 z z z z))) 1006 (* -0.00030 z z z z)))
1021 ((equal k 2) (+ 2451810.21715 1007 ((equal k 2) (+ 2451810.21715
1022 (* 365242.01767 z) 1008 (* 365242.01767 z)
1023 (* -0.11575 z z) 1009 (* -0.11575 z z)
1024 (* 0.00337 z z z) 1010 (* 0.00337 z z z)
1025 (* 0.00078 z z z z))) 1011 (* 0.00078 z z z z)))
1026 ((equal k 3) (+ 2451900.05952 1012 ((equal k 3) (+ 2451900.05952
1027 (* 365242.74049 z) 1013 (* 365242.74049 z)
1028 (* -0.06223 z z) 1014 (* -0.06223 z z)
1029 (* -0.00823 z z z) 1015 (* -0.00823 z z z)
1030 (* 0.00032 z z z z))))))) 1016 (* 0.00032 z z z z)))))))
1031 1017
1032(defun solar-equinoxes-solstices () 1018(defun solar-equinoxes-solstices ()
1033 "Local date and time of equinoxes and solstices, if visible in the calendar. 1019 "Local date and time of equinoxes and solstices, if visible in the calendar.
@@ -1035,8 +1021,8 @@ Requires floating point."
1035 (let ((m displayed-month) 1021 (let ((m displayed-month)
1036 (y displayed-year)) 1022 (y displayed-year))
1037 (increment-calendar-month m y (cond ((= 1 (% m 3)) -1) 1023 (increment-calendar-month m y (cond ((= 1 (% m 3)) -1)
1038 ((= 2 (% m 3)) 1) 1024 ((= 2 (% m 3)) 1)
1039 (t 0))) 1025 (t 0)))
1040 (let* ((calendar-standard-time-zone-name 1026 (let* ((calendar-standard-time-zone-name
1041 (if calendar-time-zone calendar-standard-time-zone-name "UTC")) 1027 (if calendar-time-zone calendar-standard-time-zone-name "UTC"))
1042 (calendar-daylight-savings-starts 1028 (calendar-daylight-savings-starts
@@ -1049,12 +1035,12 @@ Requires floating point."
1049 (d1 (list (car d0) (floor (car (cdr d0))) (car (cdr (cdr d0))))) 1035 (d1 (list (car d0) (floor (car (cdr d0))) (car (cdr (cdr d0)))))
1050 (h0 (* 24 (- (car (cdr d0)) (floor (car (cdr d0)))))) 1036 (h0 (* 24 (- (car (cdr d0)) (floor (car (cdr d0))))))
1051 (adj (dst-adjust-time d1 h0)) 1037 (adj (dst-adjust-time d1 h0))
1052 (d (list (car (car adj)) 1038 (d (list (caar adj)
1053 (+ (car (cdr (car adj)) ) 1039 (+ (car (cdar adj))
1054 (/ (car (cdr adj)) 24.0)) 1040 (/ (cadr adj) 24.0))
1055 (car (cdr (cdr (car adj)))))) 1041 (cadr (cdar adj))))
1056 ;; The following is nearly as accurate, but not quite: 1042 ;; The following is nearly as accurate, but not quite:
1057 ;; (d0 (solar-date-next-longitude 1043 ;; (d0 (solar-date-next-longitude
1058 ;; (calendar-astro-from-absolute 1044 ;; (calendar-astro-from-absolute
1059 ;; (calendar-absolute-from-gregorian 1045 ;; (calendar-absolute-from-gregorian
1060 ;; (list (+ 3 (* k 3)) 15 y))) 1046 ;; (list (+ 3 (* k 3)) 15 y)))