;;; solar.el --- calendar functions for solar events
-;; Copyright (C) 1992, 1993, 1995, 1997, 2001, 2002, 2003, 2004, 2005,
-;; 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1993, 1995, 1997, 2001-2016 Free Software
+;; Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Denis B. Roegel <Denis.Roegel@loria.fr>
;; Maintainer: Glenn Morris <rgm@gnu.org>
;; Keywords: calendar
;; Human-Keywords: sunrise, sunset, equinox, solstice, calendar, diary, holidays
+;; Package: calendar
;; This file is part of GNU Emacs.
:type 'number
:group 'calendar)
-;;; End of user options.
-
-
-(defconst solar-n-hemi-seasons
+(defcustom solar-n-hemi-seasons
'("Vernal Equinox" "Summer Solstice" "Autumnal Equinox" "Winter Solstice")
- "List of season changes for the northern hemisphere.")
+ "List of season changes for the northern hemisphere."
+ :type '(list
+ (string :tag "Vernal Equinox")
+ (string :tag "Summer Solstice")
+ (string :tag "Autumnal Equinox")
+ (string :tag "Winter Solstice"))
+ :group 'calendar)
-(defconst solar-s-hemi-seasons
+(defcustom solar-s-hemi-seasons
'("Autumnal Equinox" "Winter Solstice" "Vernal Equinox" "Summer Solstice")
- "List of season changes for the southern hemisphere.")
+ "List of season changes for the southern hemisphere."
+ :type '(list
+ (string :tag "Autumnal Equinox")
+ (string :tag "Winter Solstice")
+ (string :tag "Vernal Equinox")
+ (string :tag "Summer Solstice"))
+ :group 'calendar)
+
+;;; End of user options.
(defvar solar-sidereal-time-greenwich-midnight nil
"Sidereal time at Greenwich at midnight (universal time).")
(solar-cosine-degrees (* 2 l)))
(* -0.5 y y (solar-sin-degrees (* 4 l)))
(* -1.25 ecc ecc (solar-sin-degrees (* 2 m)))))
- 3.1415926535))))
+ float-pi))))
(list app i time-eq nut)))
(defun solar-ephemeris-correction (year)
(st (+ solar-sidereal-time-greenwich-midnight
(* ut 1.00273790935)))
;; Hour angle (in degrees).
- (ah (- (* st 15) (* 15 (car ec)) (* -1 (calendar-longitude))))
+ (ah (- (* st 15) (* 15 (car ec)) (* -1 longitude)))
(de (cadr ec))
(azimuth (solar-atn2 (- (* (solar-cosine-degrees ah)
(solar-sin-degrees latitude))
(and set-time (calendar-date-equal date (car adj-set)) (cdr adj-set))
(solar-daylight length))))
-(defun solar-sunrise-sunset-string (date)
- "String of *local* times of sunrise, sunset, and daylight on Gregorian DATE."
+(defun solar-sunrise-sunset-string (date &optional nolocation)
+ "String of *local* times of sunrise, sunset, and daylight on Gregorian DATE.
+Optional NOLOCATION non-nil means do not print the location."
(let ((l (solar-sunrise-sunset date)))
(format
- "%s, %s at %s (%s hours daylight)"
+ "%s, %s%s (%s hrs daylight)"
(if (car l)
(concat "Sunrise " (apply 'solar-time-string (car l)))
"No sunrise")
(if (cadr l)
(concat "sunset " (apply 'solar-time-string (cadr l)))
"no sunset")
- (eval calendar-location-name)
+ (if nolocation ""
+ (format " at %s" (eval calendar-location-name)))
(nth 2 l))))
(defconst solar-data-list
(sin (mod
(+ (cadr x)
(* (nth 2 x) U))
- (* 2 pi)))))
+ (* 2 float-pi)))))
solar-data-list)))))
(aberration
(* 0.0000001 (- (* 17 (cos (+ 3.10 (* 62830.14 U)))) 973)))
- (A1 (mod (+ 2.18 (* U (+ -3375.70 (* 0.36 U)))) (* 2 pi)))
- (A2 (mod (+ 3.51 (* U (+ 125666.39 (* 0.10 U)))) (* 2 pi)))
+ (A1 (mod (+ 2.18 (* U (+ -3375.70 (* 0.36 U)))) (* 2 float-pi)))
+ (A2 (mod (+ 3.51 (* U (+ 125666.39 (* 0.10 U)))) (* 2 float-pi)))
(nutation (* -0.0000001 (+ (* 834 (sin A1)) (* 64 (sin A2))))))
(mod (radians-to-degrees (+ longitude aberration nutation)) 360.0)))
`calendar-daylight-savings-starts-time', `calendar-daylight-savings-ends',
`calendar-daylight-savings-ends-time', `calendar-daylight-time-offset',
and `calendar-time-zone' are used to interpret local time."
- (let* ((long)
- (start d)
- (start-long (solar-longitude d))
- (next (mod (* l (1+ (floor (/ start-long l)))) 360))
- (end (+ d (* (/ l 360.0) 400)))
- (end-long (solar-longitude end)))
- (while ; bisection search for nearest minute
- (< 0.00001 (- end start))
- ;; start <= d < end
+ (let ((start d)
+ (next (mod (* l (1+ (floor (/ (solar-longitude d) l)))) 360))
+ (end (+ d (* (/ l 360.0) 400)))
+ long)
+ ;; Bisection search for nearest minute.
+ (while (< 0.00001 (- end start))
+ ;; start <= d < end
;; start-long <= next < end-long when next != 0
- ;; when next = 0, we look for the discontinuity (start-long is near 360
- ;; and end-long is small (less than l).
+ ;; when next = 0, look for the discontinuity (start-long is near 360
+ ;; and end-long is small (less than l)).
(setq d (/ (+ start end) 2.0)
long (solar-longitude d))
(if (or (and (not (zerop next)) (< long next))
(and (zerop next) (< l long)))
- (setq start d
- start-long long)
- (setq end d
- end-long long)))
+ (setq start d)
+ (setq end d)))
(/ (+ start end) 2.0)))
;; FIXME but there already is solar-sunrise-sunset.
If called with an optional double prefix argument, prompt for
longitude, latitude, time zone, and date, and always use standard time.
-This function is suitable for execution in a .emacs file."
+This function is suitable for execution in an init file."
(interactive "p")
(or arg (setq arg 1))
(if (and (< arg 16)
(date (if (< arg 4) (calendar-current-date) (calendar-read-date)))
(date-string (calendar-date-string date t))
(time-string (solar-sunrise-sunset-string date))
- (msg (format "%s: %s" date-string time-string))
- (one-window (one-window-p t)))
- (if (<= (length msg) (frame-width))
- (message "%s" msg)
- (with-output-to-temp-buffer "*temp*"
- (princ (concat date-string "\n" time-string)))
- (message "%s"
- (substitute-command-keys
- (if one-window
- (if pop-up-windows
- "Type \\[delete-other-windows] to remove temp window."
- "Type \\[switch-to-buffer] RET to remove temp window.")
- "Type \\[switch-to-buffer-other-window] RET to restore old \
-contents of temp window."))))))
+ (msg (format "%s%s"
+ (if (< arg 4) "" ; don't print date if it's today's
+ (format "%s: " date-string))
+ time-string)))
+ (message "%s" msg)
+ msg))
;;;###cal-autoload
-(defun calendar-sunrise-sunset ()
+(defun calendar-sunrise-sunset (&optional event)
"Local time of sunrise and sunset for date under cursor.
Accurate to a few seconds."
- (interactive)
+ (interactive (list last-nonmenu-event))
(or (and calendar-latitude calendar-longitude calendar-time-zone)
(solar-setup))
- (let ((date (calendar-cursor-to-date t)))
+ (let ((date (calendar-cursor-to-date t event)))
(message "%s: %s"
(calendar-date-string date t t)
(solar-sunrise-sunset-string date))))
+;;;###cal-autoload
+(defun calendar-sunrise-sunset-month (&optional event)
+ "Local time of sunrise and sunset for month under cursor or at EVENT."
+ (interactive (list last-nonmenu-event))
+ (or (and calendar-latitude calendar-longitude calendar-time-zone)
+ (solar-setup))
+ (let* ((date (calendar-cursor-to-date t event))
+ (month (car date))
+ (year (nth 2 date))
+ (last (calendar-last-day-of-month month year))
+ (title (format "Sunrise/sunset times for %s %d at %s"
+ (calendar-month-name month) year
+ (eval calendar-location-name))))
+ (calendar-in-read-only-buffer solar-sunrises-buffer
+ (calendar-set-mode-line title)
+ (insert title ":\n\n")
+ (dotimes (i last)
+ (setq date (list month (1+ i) year))
+ (insert (format "%s %2d: " (calendar-month-name month t) (1+ i))
+ (solar-sunrise-sunset-string date t) "\n")))))
+
(defvar date)
;; To be called from diary-list-sexp-entries, where DATE is bound.
(defun solar-mean-equinoxes/solstices (k year)
"Julian day of mean equinox/solstice K for YEAR.
K=0, spring equinox; K=1, summer solstice; K=2, fall equinox; K=3, winter
-solstice. These formulae are only to be used between 1000 BC and 3000 AD."
+solstice. These formulas are only to be used between 1000 BC and 3000 AD."
(let ((y (/ year 1000.0))
(z (/ (- year 2000) 1000.0)))
(if (< year 1000) ; actually between -1000 and 1000
(provide 'solar)
-;; arch-tag: bc0ff693-df58-4666-bde4-2a7837ccb8fe
;;; solar.el ends here