comparison lisp/calendar/solar.el @ 3866:c97c63c1a920

* solar.el (calendar-holiday-solar-equinoxes-solstices): Renamed solar-equinoxes-solstices. (calendar-time-display-form, calendar-latitude, calendar-longitude): Moved from calendar.el. (calendar-time-zone, calendar-standard-time-zone-name, calendar-daylight-time-zone-name, calendar-daylight-savings-starts, calendar-daylight-savings-ends): Take default values from calendar-current-time-zone, instead of being overwritten in open code if they were set to nil. (solar-time-string): Subtract calendar-daylight-time-offset when computing dst-ends. Avoid rounding errors when rounding time to the nearest minute.
author Jim Blandy <jimb@redhat.com>
date Tue, 22 Jun 1993 03:22:40 +0000
parents e9961fa24193
children 72da559fedd2
comparison
equal deleted inserted replaced
3865:2c6883d0a1b2 3866:c97c63c1a920
25 ;; and this notice must be preserved on all copies. 25 ;; and this notice must be preserved on all copies.
26 26
27 ;;; Commentary: 27 ;;; Commentary:
28 28
29 ;; This collection of functions implements the features of calendar.el and 29 ;; This collection of functions implements the features of calendar.el and
30 ;; diary.el that deal with sunrise/sunset and equinoxes/solstices. 30 ;; diary.el that deal with times of day, sunrise/sunset, and
31 ;; eqinoxes/solstices.
31 32
32 ;; Based on the ``Almanac for Computers 1984,'' prepared by the Nautical 33 ;; Based on the ``Almanac for Computers 1984,'' prepared by the Nautical
33 ;; Almanac Office, United States Naval Observatory, Washington, 1984 and 34 ;; Almanac Office, United States Naval Observatory, Washington, 1984 and
34 ;; on ``Astronomical Formulae for Calculators,'' 3rd ed., by Jean Meeus, 35 ;; on ``Astronomical Formulae for Calculators,'' 3rd ed., by Jean Meeus,
35 ;; Willmann-Bell, Inc., 1985. 36 ;; Willmann-Bell, Inc., 1985.
54 55
55 (if (fboundp 'atan) 56 (if (fboundp 'atan)
56 (require 'lisp-float-type) 57 (require 'lisp-float-type)
57 (error "Solar calculations impossible since floating point is unavailable.")) 58 (error "Solar calculations impossible since floating point is unavailable."))
58 59
59 (require 'calendar) 60 (require 'cal-dst)
61
62 ;;;###autoload
63 (defvar calendar-time-display-form
64 '(12-hours ":" minutes am-pm
65 (if time-zone " (") time-zone (if time-zone ")"))
66 "*The pseudo-pattern that governs the way a time of day is formatted.
67
68 A pseudo-pattern is a list of expressions that can involve the keywords
69 `12-hours', `24-hours', and `minutes', all numbers in string form,
70 and `am-pm' and `time-zone', both alphabetic strings.
71
72 For example, the form
73
74 '(24-hours \":\" minutes
75 (if time-zone \" (\") time-zone (if time-zone \")\"))
76
77 would give military-style times like `21:07 (UTC)'.")
78
79 ;;;###autoload
80 (defvar calendar-latitude nil
81 "*Latitude of `calendar-location-name' in degrees, + north, - south.
82 For example, 40.7 for New York City.")
83
84 ;;;###autoload
85 (defvar calendar-longitude nil
86 "*Longitude of `calendar-location-name' in degrees, + east, - west.
87 For example, -74.0 for New York City.")
88
89 ;;;###autoload
90 (defvar calendar-location-name
91 '(let ((float-output-format "%.1f"))
92 (format "%s%s, %s%s"
93 (abs calendar-latitude)
94 (if (> calendar-latitude 0) "N" "S")
95 (abs calendar-longitude)
96 (if (> calendar-longitude 0) "E" "W")))
97 "*Expression evaluating to name of `calendar-longitude', calendar-latitude'.
98 Default value is just the latitude, longitude pair.")
60 99
61 (defun solar-setup () 100 (defun solar-setup ()
62 "Prompt user for latitude, longitude, and time zone." 101 "Prompt user for latitude, longitude, and time zone."
63 (beep) 102 (beep)
64 (if (not calendar-longitude) 103 (if (not calendar-longitude)
235 Format used is given by `calendar-time-display-form'. Converted to daylight 274 Format used is given by `calendar-time-display-form'. Converted to daylight
236 savings time according to `calendar-daylight-savings-starts', 275 savings time according to `calendar-daylight-savings-starts',
237 `calendar-daylight-savings-ends', `calendar-daylight-switchover-time', and 276 `calendar-daylight-savings-ends', `calendar-daylight-switchover-time', and
238 `calendar-daylight-savings-offset'." 277 `calendar-daylight-savings-offset'."
239 (let* ((year (extract-calendar-year date)) 278 (let* ((year (extract-calendar-year date))
240 (abs-date-and-time (+ (calendar-absolute-from-gregorian date) 279 (time (round (* 60 time)))
241 (/ time 24.0))) 280 (rounded-abs-date (+ (calendar-absolute-from-gregorian date)
242 (rounded-abs-date (+ abs-date-and-time (/ 1.0 60 24 2)));; half min 281 (/ time 60.0 24.0)))
243 (dst-change-over
244 (/ (eval calendar-daylight-savings-switchover-time) 60.0 24.0))
245 (dst-starts (and calendar-daylight-savings-starts 282 (dst-starts (and calendar-daylight-savings-starts
246 (+ (calendar-absolute-from-gregorian 283 (+ (calendar-absolute-from-gregorian
247 (eval calendar-daylight-savings-starts)) 284 (eval calendar-daylight-savings-starts))
248 dst-change-over))) 285 (/ calendar-daylight-savings-switchover-time
286 60.0 24.0))))
249 (dst-ends (and calendar-daylight-savings-ends 287 (dst-ends (and calendar-daylight-savings-ends
250 (+ (calendar-absolute-from-gregorian 288 (+ (calendar-absolute-from-gregorian
251 (eval calendar-daylight-savings-ends)) 289 (eval calendar-daylight-savings-ends))
252 dst-change-over))) 290 (/ (- calendar-daylight-savings-switchover-time
291 calendar-daylight-time-offset)
292 60.0 24.0))))
253 (dst (and (not (eq style 'standard)) 293 (dst (and (not (eq style 'standard))
254 (or (eq style 'daylight) 294 (or (eq style 'daylight)
255 (and dst-starts dst-ends 295 (and dst-starts dst-ends
256 (or (and (< dst-starts dst-ends);; northern hemi. 296 (or (and (< dst-starts dst-ends);; northern hemi.
257 (<= dst-starts rounded-abs-date) 297 (<= dst-starts rounded-abs-date)
261 (<= dst-starts rounded-abs-date))))) 301 (<= dst-starts rounded-abs-date)))))
262 (and dst-starts (not dst-ends) 302 (and dst-starts (not dst-ends)
263 (<= dst-starts rounded-abs-date)) 303 (<= dst-starts rounded-abs-date))
264 (and dst-ends (not dst-starts) 304 (and dst-ends (not dst-starts)
265 (< rounded-abs-date dst-ends))))) 305 (< rounded-abs-date dst-ends)))))
266 (time (if dst
267 (+ time (/ (eval calendar-daylight-time-offset) 60.0))
268 time))
269 (time-zone (if dst 306 (time-zone (if dst
270 calendar-daylight-time-zone-name 307 calendar-daylight-time-zone-name
271 calendar-standard-time-zone-name)) 308 calendar-standard-time-zone-name))
272 (24-hours (truncate time)) 309 (time (+ time (if dst calendar-daylight-time-offset 0)))
273 (minutes (round (* 60 (- time 24-hours)))) 310 (24-hours (/ time 60))
274 (24-hours (if (= minutes 60) (1+ 24-hours) 24-hours)) 311 (minutes (format "%02d" (% time 60)))
275 (minutes (if (= minutes 60) 0 minutes)) 312 (12-hours (format "%d" (1+ (% (+ 24-hours 11) 12))))
276 (minutes (format "%02d" minutes))
277 (12-hours (format "%d" (if (> 24-hours 12)
278 (- 24-hours 12)
279 (if (= 24-hours 0) 12 24-hours))))
280 (am-pm (if (>= 24-hours 12) "pm" "am")) 313 (am-pm (if (>= 24-hours 12) "pm" "am"))
281 (24-hours (format "%02d" 24-hours))) 314 (24-hours (format "%02d" 24-hours)))
282 (mapconcat 'eval calendar-time-display-form ""))) 315 (mapconcat 'eval calendar-time-display-form "")))
283 316
284 (defun solar-sunrise-sunset (date) 317 (defun solar-sunrise-sunset (date)
333 (defun solar-equinoxes/solstices (k year) 366 (defun solar-equinoxes/solstices (k year)
334 "Date of equinox/solstice K for YEAR. K=0, spring equinox; K=1, summer 367 "Date of equinox/solstice K for YEAR. K=0, spring equinox; K=1, summer
335 solstice; K=2, fall equinox; K=3, winter solstice. Accurate to within 368 solstice; K=2, fall equinox; K=3, winter solstice. Accurate to within
336 several minutes." 369 several minutes."
337 (let ((date (list (+ 3 (* k 3)) 21 year)) 370 (let ((date (list (+ 3 (* k 3)) 21 year))
371 app
338 (correction 1000)) 372 (correction 1000))
339 (while (> correction 0.00001) 373 (while (> correction 0.00001)
340 (setq app (solar-mod (solar-apparent-longitude-of-sun date) 360.0)) 374 (setq app (solar-mod (solar-apparent-longitude-of-sun date) 360.0))
341 (setq correction (* 58 (solar-sin-degrees (- (* k 90) app)))) 375 (setq correction (* 58 (solar-sin-degrees (- (* k 90) app))))
342 (setq date (list (extract-calendar-month date) 376 (setq date (list (extract-calendar-month date)
380 (if (> calendar-latitude 0) "N" "S") 414 (if (> calendar-latitude 0) "N" "S")
381 (abs calendar-longitude) 415 (abs calendar-longitude)
382 (if (> calendar-longitude 0) "E" "W"))))) 416 (if (> calendar-longitude 0) "E" "W")))))
383 (calendar-standard-time-zone-name 417 (calendar-standard-time-zone-name
384 (if (< arg 16) calendar-standard-time-zone-name 418 (if (< arg 16) calendar-standard-time-zone-name
385 (cond ((= calendar-time-zone 0) "UT") 419 (cond ((= calendar-time-zone 0) "UTC")
386 ((< calendar-time-zone 0) 420 ((< calendar-time-zone 0)
387 (format "UT%dmin" calendar-time-zone)) 421 (format "UTC%dmin" calendar-time-zone))
388 (t (format "UT+%dmin" calendar-time-zone))))) 422 (t (format "UTC+%dmin" calendar-time-zone)))))
389 (calendar-daylight-savings-starts 423 (calendar-daylight-savings-starts
390 (if (< arg 16) calendar-daylight-savings-starts)) 424 (if (< arg 16) calendar-daylight-savings-starts))
391 (calendar-daylight-savings-ends 425 (calendar-daylight-savings-ends
392 (if (< arg 16) calendar-daylight-savings-ends)) 426 (if (< arg 16) calendar-daylight-savings-ends))
393 (date (if (< arg 4) (calendar-current-date) (calendar-read-date))) 427 (date (if (< arg 4) (calendar-current-date) (calendar-read-date)))
433 (let* ((sunset (solar-sunset date)) 467 (let* ((sunset (solar-sunset date))
434 (light (if sunset (- sunset (/ 18.0 60.0))))) 468 (light (if sunset (- sunset (/ 18.0 60.0)))))
435 (if light (format "%s Sabbath candle lighting" 469 (if light (format "%s Sabbath candle lighting"
436 (solar-time-string light date)))))) 470 (solar-time-string light date))))))
437 471
438 (defun calendar-holiday-function-solar-equinoxes-solstices () 472 (defun solar-equinoxes-solstices ()
439 "Date and time of equinoxes and solstices, if visible in the calendar window. 473 "Date and time of equinoxes and solstices, if visible in the calendar window.
440 Requires floating point." 474 Requires floating point."
441 (let* ((m displayed-month) 475 (let ((m displayed-month)
442 (y displayed-year)) 476 (y displayed-year))
443 (increment-calendar-month m y (cond ((= 1 (% m 3)) -1) 477 (increment-calendar-month m y (cond ((= 1 (% m 3)) -1)
444 ((= 2 (% m 3)) 1) 478 ((= 2 (% m 3)) 1)
445 (t 0))) 479 (t 0)))
446 (let* ((calendar-standard-time-zone-name 480 (let* ((calendar-standard-time-zone-name
447 (if calendar-time-zone calendar-standard-time-zone-name "UT")) 481 (if calendar-time-zone calendar-standard-time-zone-name "UTC"))
448 (calendar-daylight-savings-starts 482 (calendar-daylight-savings-starts
449 (if calendar-time-zone calendar-daylight-savings-starts)) 483 (if calendar-time-zone calendar-daylight-savings-starts))
450 (calendar-daylight-savings-ends 484 (calendar-daylight-savings-ends
451 (if calendar-time-zone calendar-daylight-savings-ends)) 485 (if calendar-time-zone calendar-daylight-savings-ends))
452 (calendar-time-zone (if calendar-time-zone calendar-time-zone 0)) 486 (calendar-time-zone (if calendar-time-zone calendar-time-zone 0))