diff lisp/calendar/holidays.el @ 17891:6eb7095ca7ab

(holiday-float): Rewritten to fix bug when base date of holiday and holiday date are in different months.
author Richard M. Stallman <rms@gnu.org>
date Tue, 20 May 1997 05:17:49 +0000
parents fd27882450bd
children d179de7ad92e
line wrap: on
line diff
--- a/lisp/calendar/holidays.el	Tue May 20 04:03:24 1997 +0000
+++ b/lisp/calendar/holidays.el	Tue May 20 05:17:49 1997 +0000
@@ -310,20 +310,57 @@
       (list (list (list month day y) string)))))
 
 (defun holiday-float (month dayname n string &optional day)
-  "Holiday on MONTH, DAYNAME (Nth occurrence, Gregorian) called STRING.
+  "Holiday on MONTH, DAYNAME (Nth occurrence) called STRING.
 If the Nth DAYNAME in MONTH is visible, the value returned is the list
 \(((MONTH DAY year) STRING)).
 
 If N<0, count backward from the end of MONTH.
 
-An optional parameter DAY means the Nth DAYNAME after/before MONTH DAY.
+An optional parameter DAY means the Nth DAYNAME on or after/before MONTH DAY.
 
 Returns nil if it is not visible in the current calendar window."
-  (let ((m displayed-month)
-        (y displayed-year))
-    (increment-calendar-month m y (- 11 month))
-    (if (> m 9)
-      (list (list (calendar-nth-named-day n dayname month y day) string)))))
+;; This is messy because the holiday may be visible, while the date on which
+;; it is based is not.  For example, the first Monday after December 30 may be
+;; visible when January is not.  For large values of |n| the problem is more
+;; grotesque.  If we didn't have to worry about such cases, we could just use
+
+;;  (let ((m displayed-month)
+;;        (y displayed-year))
+;;    (increment-calendar-month m y (- 11 month))
+;;    (if (> m 9); month in year y is visible
+;;      (list (list (calendar-nth-named-day n dayname month y day) string)))))
+
+;; which is the way the function was originally written.
+
+  (let* ((m1 displayed-month)
+         (y1 displayed-year)
+         (m2 m1)
+         (y2 y1))
+    (increment-calendar-month m1 y1 -1)
+    (increment-calendar-month m2 y2 1)
+    (let* ((d1;  first possible base date for holiday
+            (+ (calendar-nth-named-absday 1 dayname m1 y1)
+               (* -7 n)
+               (if (> n 0) 1 -7)))
+           (d2;  last possible base date for holiday
+            (+ (calendar-nth-named-absday -1 dayname m2 y2)
+               (* -7 n)
+               (if (> n 0) 7 -1)))
+           (y1 (extract-calendar-year (calendar-gregorian-from-absolute d1)))
+           (y2 (extract-calendar-year (calendar-gregorian-from-absolute d2)))
+           (y; year of base date
+            (if (or (= y1 y2) (> month 9))
+                  y1
+                y2))
+           (d; day of base date
+            (or day (if (> n 0)
+                        1
+                      (calendar-last-day-of-month month y))))
+           (date; base date for holiday
+            (calendar-absolute-from-gregorian (list month d y))))
+      (if (and (<= d1 date) (<= date d2))
+          (list (list (calendar-nth-named-day n dayname month y d)
+                      string))))))
 
 (defun holiday-sexp (sexp string)
   "Sexp holiday for dates in the calendar window.