; ; yahr.cl calculate yahrzeit dates ; ; adapted from calendar.el ; ;(setq lisp:*floating-point-contagion-ansi* t) ;(setq lisp:*default-float-format* 'double-float) (defvar calendar-latitude +45.44) (defvar calendar-longitude -75.695) (defvar calendar-location-name "Ottawa, Ont.") (defvar calendar-time-zone -300) (defvar calendar-standard-time-zone-name "EST") (defvar calendar-daylight-time-zone-name "EDT") (setq date (multiple-value-bind (sec min hr day mon year dow dstp tz) (get-decoded-time) (list mon day year))) (defvar year (multiple-value-bind (sec min hr day mon year dow dstp tz) (get-decoded-time) year)) (defvar month (multiple-value-bind (sec min hr day mon year dow dstp tz) (get-decoded-time) mon)) (setq calendar-daylight-savings-starts '(calendar-nth-named-day 1 0 4 year)) (setq calendar-daylight-savings-ends '(calendar-nth-named-day -1 0 10 year)) (setq all-hebrew-calendar-holidays t) (defvar calendar-day-name-array (vector "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday")) (defvar calendar-day-name-abbr-array (vector "Sun" "Mon" "Tues" "Wed" "Thurs" "Fri" "Sat")) (defun calendar-day-name (date) "Returns a string with the name of the day of the week of DATE." (aref calendar-day-name-array (calendar-day-of-week date))) (defvar calendar-month-name-array (vector "January" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "December")) (defmacro % ( n d ) "Redefine % as the REM function." `(rem ,n ,d)) (defvar european-calendar-style nil "*Use the European style of dates in the diary and in any displays. If this variable is t, a date 1/2/1990 would be interpreted as February 1, 1990. The accepted European date styles are DAY/MONTH DAY/MONTH/YEAR DAY MONTHNAME DAY MONTHNAME YEAR DAYNAME Names can be capitalized or not, written in full, or abbreviated to three characters with or without a period." ) (defmacro calendar-sum (index initial condition expression) "For INDEX = INITIAL et seq, as long as CONDITION holds, sum EXPRESSION." `(do ((sum 0) (,index ,initial (1+ ,index))) ((not ,condition) sum) (setq sum (+ sum ,expression )))) (declaim (inline extract-calendar-month)) (defun extract-calendar-month (date) "Extract the month part of DATE which has the form (month day year)." (car date)) (declaim (inline extract-calendar-day)) (defun extract-calendar-day (date) "Extract the day part of DATE which has the form (month day year)." (car (cdr date))) (declaim (inline extract-calendar-year)) (defun extract-calendar-year (date) "Extract the year part of DATE which has the form (month day year)." (car (cdr (cdr date)))) (declaim (inline calendar-leap-year-p)) (defun calendar-leap-year-p (year) "Returns t if YEAR is a Gregorian leap year." (and (zerop (% year 4)) (or (not (zerop (% year 100))) (zerop (% year 400))))) (declaim (inline calendar-last-day-of-month)) (defun calendar-last-day-of-month (month year) "The last day in MONTH during YEAR." (if (and (= month 2) (calendar-leap-year-p year)) 29 (aref (vector 31 28 31 30 31 30 31 31 30 31 30 31) (1- month)))) (declaim (inline calendar-day-number)) (defun calendar-day-number (date) "Return the day number within the year of the date DATE. For example, (calendar-day-number '(1 1 1987)) returns the value 1, while (calendar-day-number '(12 31 1980)) returns 366." (let* ((month (extract-calendar-month date)) (day (extract-calendar-day date)) (year (extract-calendar-year date)) (day-of-year (+ day (* 31 (1- month))))) (if (> month 2) (progn (setq day-of-year (- day-of-year (truncate (+ 23 (* 4 month)) 10))) (if (calendar-leap-year-p year) (setq day-of-year (1+ day-of-year))))) day-of-year)) (declaim (inline calendar-absolute-from-gregorian)) (defun calendar-absolute-from-gregorian (date) "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE. The Gregorian date Sunday, December 31, 1 BC is imaginary." (let ((prior-years (1- (extract-calendar-year date)))) (+ (calendar-day-number date);; Days this year (* 365 prior-years);; + Days in prior years (truncate prior-years 4);; + Julian leap years (- (truncate prior-years 100));; - century years (truncate prior-years 400))));; + Gregorian leap years (defvar european-calendar-display-form '((list 'if dayname (concatenate (format nil "~A" dayname) ", ")) day " " monthname " " year) "*Pseudo-pattern governing the way a date appears in the European style. See the documentation of calendar-date-display-form for an explanation.") (defvar american-calendar-display-form '((if dayname (concatenate dayname ", ")) monthname " " day ", " year) ; '((list 'if dayname (concatenate (format nil "~A" dayname) ", ")) monthname " " day ", " year) "*Pseudo-pattern governing the way a date appears in the American style. See the documentation of `calendar-date-display-form' for an explanation.") (defvar calendar-date-display-form (if european-calendar-style european-calendar-display-form american-calendar-display-form) "*Pseudo-pattern governing the way a date appears. Used by the function `calendar-date-string', a pseudo-pattern is a list of expressions that can involve the keywords `month', `day', and `year', all numbers in string form, and `monthname' and `dayname', both alphabetic strings. For example, the ISO standard would use the pseudo- pattern '(year \"-\" month \"-\" day) while a typical American form would be '(month \"/\" day \"/\" (substring year -2)) and '((format \"%9s, %9s %2s, %4s\" dayname monthname day year)) would give the usual American style in fixed-length fields. See the documentation of the function `calendar-date-string'.") (defun european-calendar () "Set the interpretation and display of dates to the European style." (interactive) (setq european-calendar-style t) (setq calendar-date-display-form european-calendar-display-form) (setq diary-date-forms european-date-diary-pattern) (update-calendar-mode-line)) (defun american-calendar () "Set the interpretation and display of dates to the American style." (interactive) (setq european-calendar-style nil) (setq calendar-date-display-form american-calendar-display-form) (setq diary-date-forms american-date-diary-pattern) (update-calendar-mode-line)) (defun calendar-current-date () "Returns the current date in a list (month day year)." (multiple-value-bind(s m h d mo yr)(get-decoded-time) (list mo d yr))) (defun calendar-date-equal (date1 date2) "Returns t if the DATE1 and DATE2 are the same." (and (= (extract-calendar-month date1) (extract-calendar-month date2)) (= (extract-calendar-day date1) (extract-calendar-day date2)) (= (extract-calendar-year date1) (extract-calendar-year date2)))) (defun calendar-dayname-on-or-before (dayname date) "Returns the absolute date of the DAYNAME on or before absolute DATE. DAYNAME=0 means Sunday, DAYNAME=1 means Monday, and so on. Note: Applying this function to d+6 gives us the DAYNAME on or after an absolute day d. Similarly, applying it to d+3 gives the DAYNAME nearest to absolute date d, applying it to d-1 gives the DAYNAME previous to absolute date d, and applying it to d+7 gives the DAYNAME following absolute date d." (- date (% (- date dayname) 7))) (defun calendar-gregorian-from-absolute (date) "Compute the list (month day year) corresponding to the absolute DATE. The absolute date is the number of days elapsed since the (imaginary) Gregorian date Sunday, December 31, 1 BC." ;; See the footnote on page 384 of ``Calendrical Calculations, Part II: ;; Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M. ;; Clamen, Software--Practice and Experience, Volume 23, Number 4 ;; (April, 1993), pages 383-404 for an explanation. (let* ((d0 (1- date)) (n400 (truncate d0 146097)) (d1 (% d0 146097)) (n100 (truncate d1 36524)) (d2 (% d1 36524)) (n4 (truncate d2 1461)) (d3 (% d2 1461)) (n1 (truncate d3 365)) (day (1+ (% d3 365))) (year (+ (* 400 n400) (* 100 n100) (* n4 4) n1))) (if (or (= n100 4) (= n1 4)) (list 12 31 year) (let ((year (1+ year)) (month 1)) (loop (let (( mdays (calendar-last-day-of-month month year))) (when (not (and (< mdays day) (setq day (- day mdays)))) (return)) (setq month (1+ month)))) (list month day year))))) (defun calendar-month-name (month) "The name of MONTH." (aref calendar-month-name-array (1- month))) (defun calendar-day-of-week (date) "Returns the day-of-the-week index of DATE, 0 for Sunday, 1 for Monday, etc." (% (calendar-absolute-from-gregorian date) 7)) (defun calendar-print-hebrew-date () "Show the Hebrew calendar equivalent of the date under the cursor." (format t "Hebrew date (until sunset): ~A" (calendar-hebrew-date-string (calendar-cursor-to-date t)))) (defun hebrew-calendar-last-month-of-year (year) "The last month of the Hebrew calendar YEAR." (if (hebrew-calendar-leap-year-p year) 13 12)) (defun calendar-hebrew-from-absolute (date) "Compute the Hebrew date (month day year) corresponding to absolute DATE. The absolute date is the number of days elapsed since the (imaginary) Gregorian date Sunday, December 31, 1 BC." (let* ((greg-date (calendar-gregorian-from-absolute date)) (month (aref (vector 9 10 11 12 1 2 3 4 7 7 7 8 ) (1- (extract-calendar-month greg-date)))) (day) (year (+ 3760 (extract-calendar-year greg-date)))) (loop (when (not (>= date (calendar-absolute-from-hebrew (list 7 1 (1+ year))))) (return)) (setq year (1+ year))) (let ((length (hebrew-calendar-last-month-of-year year))) (loop (when (not (> date (calendar-absolute-from-hebrew (list month (hebrew-calendar-last-day-of-month month year) year)))) (return)) (setq month (1+ (% month length))))) (setq day (1+ (- date (calendar-absolute-from-hebrew (list month 1 year))))) (list month day year))) (defun hebrew-calendar-leap-year-p (year) "t if YEAR is a Hebrew calendar leap year." (< (% (1+ (* 7 year)) 19) 7)) (defun hebrew-calendar-last-day-of-month (month year) "The last day of MONTH in YEAR." (if (or (member month (list 2 4 6 10 13)) (and (= month 12) (not (hebrew-calendar-leap-year-p year))) (and (= month 8) (not (hebrew-calendar-long-heshvan-p year))) (and (= month 9) (hebrew-calendar-short-kislev-p year))) 29 30)) (defun hebrew-calendar-elapsed-days (year) "Days from Sun. prior to start of Hebrew calendar to mean conjunction of Tishri of Hebrew YEAR." (let* ((months-elapsed (+ (* 235 (truncate (1- year) 19));; Months in complete cycles so far. (* 12 (% (1- year) 19)) ;; Regular months in this cycle (truncate (1+ (* 7 (% (1- year) 19))) 19)));; Leap months this cycle (parts-elapsed (+ 204 (* 793 (% months-elapsed 1080)))) (hours-elapsed (+ 5 (* 12 months-elapsed) (* 793 (truncate months-elapsed 1080)) (truncate parts-elapsed 1080))) (parts ;; Conjunction parts (+ (* 1080 (% hours-elapsed 24)) (% parts-elapsed 1080))) (day ;; Conjunction day (+ 1 (* 29 months-elapsed) (truncate hours-elapsed 24))) (alternative-day (if (or (>= parts 19440) ;; If the new moon is at or after midday, (and (= (% day 7) 2);; ...or is on a Tuesday... (>= parts 9924) ;; at 9 hours, 204 parts or later... (not (hebrew-calendar-leap-year-p year)));; of a ;; common year, (and (= (% day 7) 1);; ...or is on a Monday... (>= parts 16789) ;; at 15 hours, 589 parts or later... (hebrew-calendar-leap-year-p (1- year))));; at the end ;; of a leap year ;; Then postpone Rosh HaShanah one day (1+ day) ;; Else day))) (if ;; If Rosh HaShanah would occur on Sunday, Wednesday, or Friday (member (% alternative-day 7) (list 0 3 5)) ;; Then postpone it one (more) day and return (1+ alternative-day) ;; Else return alternative-day))) (defun hebrew-calendar-days-in-year (year) "Number of days in Hebrew YEAR." (- (hebrew-calendar-elapsed-days (1+ year)) (hebrew-calendar-elapsed-days year))) (defun hebrew-calendar-long-heshvan-p (year) "t if Heshvan is long in Hebrew YEAR." (= (% (hebrew-calendar-days-in-year year) 10) 5)) (defun hebrew-calendar-short-kislev-p (year) "t if Kislev is short in Hebrew YEAR." (= (% (hebrew-calendar-days-in-year year) 10) 3)) (defun calendar-absolute-from-hebrew (date) "Absolute date of Hebrew DATE. The absolute date is the number of days elapsed since the (imaginary) Gregorian date Sunday, December 31, 1 BC." (let* ((month (extract-calendar-month date)) (day (extract-calendar-day date)) (year (extract-calendar-year date))) (+ day ;; Days so far this month. (if (< month 7);; before Tishri ;; Then add days in prior months this year before and after Nisan (+ (calendar-sum m 7 (<= m (hebrew-calendar-last-month-of-year year)) (hebrew-calendar-last-day-of-month m year)) (calendar-sum m 1 (< m month) (hebrew-calendar-last-day-of-month m year))) ;; Else add days in prior months this year (calendar-sum m 7 (< m month) (hebrew-calendar-last-day-of-month m year))) (hebrew-calendar-elapsed-days year);; Days in prior years. -1373429))) ;; Days elapsed before absolute date 1. (defvar calendar-hebrew-month-name-array-common-year (vector "Nisan" "Iyar" "Sivan" "Tammuz" "Av" "Elul" "Tishri" "Heshvan" "Kislev" "Teveth" "Shevat" "Adar")) (defvar calendar-hebrew-month-name-array-leap-year (vector "Nisan" "Iyar" "Sivan" "Tammuz" "Av" "Elul" "Tishri" "Heshvan" "Kislev" "Teveth" "Shevat" "Adar I" "Adar II")) (defun calendar-date-display-form (if european-calendar-style european-calendar-display-form american-calendar-display-form) "*Pseudo-pattern governing the way a date appears. Used by the function `calendar-date-string', a pseudo-pattern is a list of expressions that can involve the keywords `month', `day', and `year', all numbers in string form, and `monthname' and `dayname', both alphabetic strings. For example, the ISO standard would use the pseudo- pattern '(year \"-\" month \"-\" day) while a typical American form would be '(month \"/\" day \"/\" (substring year -2)) and '((format \"%9s, %9s %2s, %4s\" dayname monthname day year)) would give the usual American style in fixed-length fields. See the documentation of the function `calendar-date-string'.") (defun calendar-date-string (date &optional abbreviate nodayname) "A string form of DATE, driven by the variable `calendar-date-display-form'. An optional parameter ABBREVIATE, when t, causes the month and day names to be abbreviated to three characters. An optional parameter NODAYNAME, when t, omits the name of the day of the week." (let* ((dayname (if nodayname nil (if abbreviate (substring (calendar-day-name date) 0 3) (calendar-day-name date)))) (month (extract-calendar-month date)) (monthname (if abbreviate (substring (calendar-month-name month) 0 3) (calendar-month-name month))) (day (format nil "~A" (extract-calendar-day date))) (month (format nil "~A" month)) (year (format nil "~A" (extract-calendar-year date)))) (concatenate 'string (and (boundp 'dayname) dayname (concatenate 'string dayname ", ")) monthname " " day ", " year))) (defun calendar-dayname-on-or-before (dayname date) "Returns the absolute date of the DAYNAME on or before absolute DATE. DAYNAME=0 means Sunday, DAYNAME=1 means Monday, and so on. Note: Applying this function to d+6 gives us the DAYNAME on or after an absolute day d. Similarly, applying it to d+3 gives the DAYNAME nearest to absolute date d, applying it to d-1 gives the DAYNAME previous to absolute date d, and applying it to d+7 gives the DAYNAME following absolute date d." (- date (% (- date dayname) 7))) (defun calendar-nth-named-absday (n dayname month year &optional day) "The absolute date of Nth DAYNAME in MONTH, YEAR before/after optional DAY. A DAYNAME of 0 means Sunday, 1 means Monday, and so on. If N<0, return the Nth DAYNAME before MONTH DAY, YEAR (inclusive). If N>0, return the Nth DAYNAME after MONTH DAY, YEAR (inclusive). If DAY is omitted, it defaults to 1 if N>0, and MONTH's last day otherwise." (if (> n 0) (+ (* 7 (1- n)) (calendar-dayname-on-or-before dayname (+ 6 (calendar-absolute-from-gregorian (list month (or day 1) year))))) (+ (* 7 (1+ n)) (calendar-dayname-on-or-before dayname (calendar-absolute-from-gregorian (list month (or day (calendar-last-day-of-month month year)) year)))))) (defun calendar-nth-named-day (n dayname month year &optional day) "The date of Nth DAYNAME in MONTH, YEAR before/after optional DAY. A DAYNAME of 0 means Sunday, 1 means Monday, and so on. If N<0, return the Nth DAYNAME before MONTH DAY, YEAR (inclusive). If N>0, return the Nth DAYNAME after MONTH DAY, YEAR (inclusive). If DAY is omitted, it defaults to 1 if N>0, and MONTH's last day otherwise." (calendar-gregorian-from-absolute (calendar-nth-named-absday n dayname month year day))) (defun calendar-hebrew-date-string (&optional date) "String of Hebrew date before sunset of Gregorian DATE. Defaults to today's date if DATE is not given. Driven by the variable `calendar-date-display-form'." (let* ((hebrew-date (calendar-hebrew-from-absolute (calendar-absolute-from-gregorian (or date (calendar-current-date))))) (calendar-month-name-array (if (hebrew-calendar-leap-year-p (extract-calendar-year hebrew-date)) calendar-hebrew-month-name-array-leap-year calendar-hebrew-month-name-array-common-year))) (calendar-date-string hebrew-date nil t))) ;;; ;;; functions from diary-lib.el ;;; (defun diary-day-of-year () "Day of year and number of days remaining in the year of date diary entry." (calendar-day-of-year-string date)) (defun diary-iso-date () "ISO calendar equivalent of date diary entry." (format nil "ISO date: ~A" (calendar-iso-date-string date))) (defun diary-islamic-date () "Islamic calendar equivalent of date diary entry." (let ((i (calendar-islamic-date-string (calendar-cursor-to-date t)))) (if (string-equal i "") "Date is pre-Islamic" (format nil "Islamic date (until sunset): ~A" i)))) (defun diary-hebrew-date () "Hebrew calendar equivalent of date diary entry." (format nil "Today's date (until sunset): ~A" (calendar-hebrew-date-string date))) (defun diary-julian-date () "Julian calendar equivalent of date diary entry." (format nil "Julian date: ~A" (calendar-julian-date-string date))) (defun diary-astro-day-number () "Astronomical (Julian) day number diary entry." (format nil "Astronomical (Julian) day number ~A" (calendar-astro-date-string date))) (defun all-holidays () "Check date against all Jewish Calendar Holidays" (let ((l (append (holiday-rosh-hashanah-etc) (holiday-hanukkah) (holiday-passover-etc) (holiday-tisha-b-av-etc)))) l)) (defun holiday-rosh-hashanah-etc () "List of dates related to Rosh Hashanah, as visible in calendar window." (let* ((abs-r-h (calendar-absolute-from-hebrew (list 7 1 (+ year 3761)))) (mandatory (list (list (calendar-gregorian-from-absolute abs-r-h) (format nil "Rosh HaShanah ~d" (+ 3761 year))) (list (calendar-gregorian-from-absolute (+ abs-r-h 9)) "Yom Kippur") (list (calendar-gregorian-from-absolute (+ abs-r-h 14)) "Succos") (list (calendar-gregorian-from-absolute (+ abs-r-h 21)) "Shemini Atzeres") (list (calendar-gregorian-from-absolute (+ abs-r-h 22)) "Simchas Torah"))) (optional (list (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 (- abs-r-h 4))) "Selichos (night)") (list (calendar-gregorian-from-absolute (1- abs-r-h)) "Erev Rosh HaShannah") (list (calendar-gregorian-from-absolute (1+ abs-r-h)) "Rosh HaShanah (second day)") (list (calendar-gregorian-from-absolute (if (= (% abs-r-h 7) 4) (+ abs-r-h 3) (+ abs-r-h 2))) "Tzom Gedaliah") (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 (+ 7 abs-r-h))) "Shabbos Shuvah") (list (calendar-gregorian-from-absolute (+ abs-r-h 8)) "Erev Yom Kippur") (list (calendar-gregorian-from-absolute (+ abs-r-h 13)) "Erev Succos") (list (calendar-gregorian-from-absolute (+ abs-r-h 15)) "Succos (second day)") (list (calendar-gregorian-from-absolute (+ abs-r-h 16)) "Chol Hamoed Succos (first day)") (list (calendar-gregorian-from-absolute (+ abs-r-h 17)) "Chol Hamoed Succos (second day)") (list (calendar-gregorian-from-absolute (+ abs-r-h 18)) "Chol Hamoed Succos (third day)") (list (calendar-gregorian-from-absolute (+ abs-r-h 19)) "Chol Hamoed Succos (fourth day)") (list (calendar-gregorian-from-absolute (+ abs-r-h 20)) "Hoshannah Rabbah"))) (output-list (filter-visible-calendar-holidays mandatory))) (if all-hebrew-calendar-holidays (setq output-list (append (filter-visible-calendar-holidays optional) output-list))) output-list)) (defmacro increment-calendar-month (mon yr n) "Move the variables MON and YR to the month and year by N months. Forward if N is positive or backward if N is negative." `(let (( macro-y (+ (* ,yr 12) , mon -1 ,n)) ) (setq ,mon (1+ (% macro-y 12) )) (setq ,yr (floor macro-y 12)))) (defun holiday-hanukkah () "List of dates related to Hanukkah, as visible in calendar window." (let ((m month) (y year)) (increment-calendar-month m y 1) (let* ((h-y (extract-calendar-year (calendar-hebrew-from-absolute (calendar-absolute-from-gregorian (list m (calendar-last-day-of-month m y) y))))) (abs-h (calendar-absolute-from-hebrew (list 9 25 h-y)))) (filter-visible-calendar-holidays (list (list (calendar-gregorian-from-absolute (1- abs-h)) "Erev Chanuka") (list (calendar-gregorian-from-absolute abs-h) "Chanuka (first day)") (list (calendar-gregorian-from-absolute (1+ abs-h)) "Chanuka (second day)") (list (calendar-gregorian-from-absolute (+ abs-h 2)) "Chanuka (third day)") (list (calendar-gregorian-from-absolute (+ abs-h 3)) "Chanuka (fourth day)") (list (calendar-gregorian-from-absolute (+ abs-h 4)) "Chanuka (fifth day)") (list (calendar-gregorian-from-absolute (+ abs-h 5)) "Chanuka (sixth day)") (list (calendar-gregorian-from-absolute (+ abs-h 6)) "Chanuka (seventh day)") (list (calendar-gregorian-from-absolute (+ abs-h 7)) "Chanuka (eighth day)")))))) (defun holiday-passover-etc () "List of dates related to Passover, as visible in calendar window." (let* ((abs-p (calendar-absolute-from-hebrew (list 1 15 (+ year 3760)))) (mandatory (list (list (calendar-gregorian-from-absolute abs-p) "Pesach") (list (calendar-gregorian-from-absolute (+ abs-p 50)) "Shavuot"))) (optional (list (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 (- abs-p 43))) "Shabbos Shekalim") (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 (- abs-p 30))) "Shabbos Zachor") (list (calendar-gregorian-from-absolute (if (= (% abs-p 7) 2) (- abs-p 33) (- abs-p 31))) "Fast of Esther") (list (calendar-gregorian-from-absolute (- abs-p 31)) "Erev Purim") (list (calendar-gregorian-from-absolute (- abs-p 30)) "Purim") (list (calendar-gregorian-from-absolute (if (zerop (% abs-p 7)) (- abs-p 28) (- abs-p 29))) "Shushan Purim") (list (calendar-gregorian-from-absolute (- (calendar-dayname-on-or-before 6 (- abs-p 14)) 7)) "Shabbos Parah") (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 (- abs-p 14))) "Shabbos HaHodesh") (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 (1- abs-p))) "Shabbos HaGadol") (list (calendar-gregorian-from-absolute (1- abs-p)) "Erev Pesach") (list (calendar-gregorian-from-absolute (1+ abs-p)) "Pesach (second day)") (list (calendar-gregorian-from-absolute (+ abs-p 2)) "Chol Hamoed Pesach (first day)") (list (calendar-gregorian-from-absolute (+ abs-p 3)) "Chol Hamoed Pesach (second day)") (list (calendar-gregorian-from-absolute (+ abs-p 4)) "Chol Hamoed Pesach (third day)") (list (calendar-gregorian-from-absolute (+ abs-p 5)) "Chol Hamoed Pesach (fourth day)") (list (calendar-gregorian-from-absolute (+ abs-p 6)) "Pesach (seventh day)") (list (calendar-gregorian-from-absolute (+ abs-p 7)) "Pesach (eighth day)") (list (calendar-gregorian-from-absolute (+ abs-p 12)) "Yom HaShoah") (list (calendar-gregorian-from-absolute (if (zerop (% abs-p 7)) (+ abs-p 18) (if (= (% abs-p 7) 6) (+ abs-p 19) (+ abs-p 20)))) "Yom HaAtzma'ut") (list (calendar-gregorian-from-absolute (+ abs-p 33)) "Lag BaOmer") (list (calendar-gregorian-from-absolute (+ abs-p 43)) "Yom Yerushalim") (list (calendar-gregorian-from-absolute (+ abs-p 49)) "Erev Shavuos") (list (calendar-gregorian-from-absolute (+ abs-p 51)) "Shavuos (second day)"))) (output-list (filter-visible-calendar-holidays mandatory))) (if all-hebrew-calendar-holidays (setq output-list (append (filter-visible-calendar-holidays optional) output-list))) output-list)) (defun holiday-tisha-b-av-etc () "List of dates around Tisha B'Av, as visible in calendar window." nil;; None of the dates is visible (let* ((abs-t-a (calendar-absolute-from-hebrew (list 5 9 (+ year 3760))))) (filter-visible-calendar-holidays (list (list (calendar-gregorian-from-absolute (if (= (% abs-t-a 7) 6) (- abs-t-a 20) (- abs-t-a 21))) "Tzom Tammuz") (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 abs-t-a)) "Shabbos Chazon") (list (calendar-gregorian-from-absolute (if (= (% abs-t-a 7) 6) (1+ abs-t-a) abs-t-a)) "Tisha B'Av") (list (calendar-gregorian-from-absolute (calendar-dayname-on-or-before 6 (+ abs-t-a 7))) "Shabbos Nachamu"))))) (defun filter-visible-calendar-holidays (l) "Return a list of all visible holidays of those on L." (let ((visible) (p l) (abs-date (calendar-absolute-from-gregorian date))) (loop while p do (and (car (car p)) (eql abs-date (calendar-absolute-from-gregorian (car (car p)))) (setq visible (append (list (car p)) visible))) (setq p (cdr p))) visible)) (defun diary-omer () "Omer count diary entry. Entry applies if date is within 50 days after Passover." (let* ((passover (calendar-absolute-from-hebrew (list 1 15 (+ (extract-calendar-year date) 3760)))) (omer (- (calendar-absolute-from-gregorian date) passover)) (week (truncate omer 7)) (day (% omer 7))) (if (and (> omer 0) (< omer 50)) (format nil "Day ~D~A of the omer." omer (if (zerop week) "" (format nil ", that is, ~D week~A~A" week (if (= week 1) "" "s") (if (zerop day) "" (format nil " and ~D day~A" day (if (= day 1) "" "s"))))))))) (defun diary-yahrzeit (death-month death-day death-year) "Yahrzeit diary entry--entry applies if date is yahrzeit or the day before. Parameters are DEATH-MONTH, DEATH-DAY, DEATH-YEAR; the diary entry is assumed to be the name of the person. Date of death is on the *civil* calendar; although the date of death is specified by the civil calendar, the proper Hebrew calendar yahrzeit is determined. If `european-calendar-style' is t, the order of the parameters is changed to DEATH-DAY, DEATH-MONTH, DEATH-YEAR." (let* ((h-date (calendar-hebrew-from-absolute (calendar-absolute-from-gregorian (if european-calendar-style (list death-day death-month death-year) (list death-month death-day death-year))))) (h-month (extract-calendar-month h-date)) (h-day (extract-calendar-day h-date)) (h-year (extract-calendar-year h-date)) (d (calendar-absolute-from-gregorian date)) (yr (extract-calendar-year (calendar-hebrew-from-absolute d))) (diff (- yr h-year)) (y (hebrew-calendar-yahrzeit h-date yr))) (if (and (> diff 0) (or (= y d) (= y (1+ d)))) (format nil "Yahrzeit of ~A~A: ~d~A anniversary" entry (if (= y d) "" " (evening)") diff (cond ((= (% diff 10) 1) "st") ((= (% diff 10) 2) "nd") ((= (% diff 10) 3) "rd") (t "th")))))) (defun diary-rosh-hodesh () "Rosh Hodesh diary entry. Entry applies if date is Rosh Hodesh, the day before, or the Saturday before." (let* ((d (calendar-absolute-from-gregorian date)) (h-date (calendar-hebrew-from-absolute d)) (h-month (extract-calendar-month h-date)) (h-day (extract-calendar-day h-date)) (h-year (extract-calendar-year h-date)) (leap-year (hebrew-calendar-leap-year-p h-year)) (last-day (hebrew-calendar-last-day-of-month h-month h-year)) (h-month-names (if leap-year calendar-hebrew-month-name-array-leap-year calendar-hebrew-month-name-array-common-year)) (this-month (aref h-month-names (1- h-month))) (h-yesterday (extract-calendar-day (calendar-hebrew-from-absolute (1- d))))) (if (or (= h-day 30) (and (= h-day 1) (/= h-month 7))) (format nil "Rosh Hodesh ~A" (if (= h-day 30) (format nil "~A (first day)" ;; next month must be in the same year since this ;; month can't be the last month of the year since ;; it has 30 days (aref h-month-names h-month)) (if (= h-yesterday 30) (format nil "~A (second day)" this-month) this-month))) (if (= (% d 7) 6);; Saturday--check for Shabbos Mevarhim (cond ((and (> h-day 22) (/= h-month 6) (= 29 last-day)) (format nil "Mevarhim Rosh Hodesh ~A (~A)" (aref h-month-names (if (= h-month (hebrew-calendar-last-month-of-year h-year)) 0 h-month)) (aref calendar-day-name-array (- 29 h-day)))) ((and (< h-day 30) (> h-day 22) (= 30 last-day)) (format nil "Mevarhim Rosh Hodesh ~A (~A-~A)" (aref h-month-names h-month) (if (= h-day 29) "tomorrow" (aref calendar-day-name-array (- 29 h-day))) (aref calendar-day-name-array (% (- 30 h-day) 7))))) (if (and (= h-day 29) (/= h-month 6)) (format nil "Erev Rosh Hodesh ~A" (aref h-month-names (if (= h-month (hebrew-calendar-last-month-of-year h-year)) 0 h-month)))))))) (defun diary-parasha () "Parasha diary entry--entry applies if date is a Saturday." (let ((d (calendar-absolute-from-gregorian date))) (if (= (% d 7) 6);; Saturday (let* ((h-year (extract-calendar-year (calendar-hebrew-from-absolute d))) (rosh-hashannah (calendar-absolute-from-hebrew (list 7 1 h-year))) (passover (calendar-absolute-from-hebrew (list 1 15 h-year))) (rosh-hashannah-day (aref calendar-day-name-array (% rosh-hashannah 7))) (passover-day (aref calendar-day-name-array (% passover 7))) (long-h (hebrew-calendar-long-heshvan-p h-year)) (short-k (hebrew-calendar-short-kislev-p h-year)) (type (cond ((and long-h (not short-k)) "complete") ((and (not long-h) short-k) "incomplete") (t "regular"))) (year-format (symbol-value (intern (string-upcase (format nil "hebrew-calendar-year-~A-~A-~A";; keviah rosh-hashannah-day type passover-day))))) (first-saturday;; of Hebrew year (calendar-dayname-on-or-before 6 (+ 6 rosh-hashannah))) (saturday;; which Saturday of the Hebrew year (truncate (- d first-saturday) 7)) (parasha (aref year-format saturday))) (if parasha (format nil "~A" (if (listp parasha);; Israel differs from diaspora (if (car parasha) (format nil "Shabbos Parashas ~A" (hebrew-calendar-parasha-name (car parasha)) ) (format nil "Yom Tov")) (format nil "Shabbos Parashas ~A" (hebrew-calendar-parasha-name parasha))))))))) (defun add-to-diary-list (date string) "Add the entry (DATE STRING) to `diary-entries-list'. Do nothing if DATE or STRING is nil." (and date string (setq diary-entries-list (append diary-entries-list (list (list date string)))))) (defvar hebrew-calendar-parashiot-names (vector "Bereshith" "Noah" "Lech L'cha" "Vayera" "Hayei Sarah" "Toldos" "Vayetze" "Vayishlach" "Vayeshev" "Mikketz" "Vayiggash" "Vayhi" "Shemoth" "Vaera" "Bo" "Beshallah" "Yithro" "Mishpatim" "Terumah" "Tetzavveh" "Ki Tissa" "Vayakhel" "Pekudei" "Vayikra" "Tzav" "Shemini" "Tazria" "Metzora" "Aharei Mos" "Kedoshim" "Emor" "Behar" "Behukkosai" "Bamidbar" "Naso" "Behaalot'cha" "Shelach L'cha" "Korah" "Chukas" "Balak" "Pinhas" "Mattos" "Masei" "Devarim" "Vaethanan" "Ekev" "Reeh" "Shofetim" "Ki Tetze" "Ki Tavo" "Nitzavim" "Vayelech" "Haazinu") "The names of the parashiot in the Torah.") ;; The seven ordinary year types (keviot) (setq hebrew-calendar-year-Saturday-incomplete-Sunday (vector nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (vector 21 22) 23 24 nil 25 (vector 26 27) (vector 28 29) 30 (vector 31 32) 33 34 35 36 37 38 39 40 (vector 41 42) 43 44 45 46 47 48 49 50)) ; "The structure of the parashiot. ;Hebrew year starts on Saturday, is `incomplete' (Heshvan and Kislev each have ;29 days), and has Passover start on Sunday.") (setq hebrew-calendar-year-Saturday-complete-Tuesday (vector nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (vector 21 22) 23 24 nil 25 (vector 26 27) (vector 28 29) 30 (vector 31 32) 33 34 35 36 37 38 39 40 (vector 41 42) 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot. ;Hebrew year that starts on Saturday, is `complete' (Heshvan and Kislev each ;have 30 days), and has Passover start on Tuesday.") (setq hebrew-calendar-year-Monday-incomplete-Tuesday (vector 51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (vector 21 22) 23 24 nil 25 (vector 26 27) (vector 28 29) 30 (vector 31 32) 33 34 35 36 37 38 39 40 (vector 41 42) 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot. ;Hebrew year that starts on Monday, is `incomplete' (Heshvan and Kislev each ;have 29 days), and has Passover start on Tuesday.") (setq hebrew-calendar-year-Monday-complete-Thursday (vector 51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (vector 21 22) 23 24 nil 25 (vector 26 27) (vector 28 29) 30 (vector 31 32) 33 (cons nil 34) (cons 34 35) (cons 35 36) (cons 36 37) (cons 37 38) (cons (vector 38 39) 39) 40 (vector 41 42) 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot. ;Hebrew year that starts on Monday, is `complete' (Heshvan and Kislev each have ;30 days), and has Passover start on Thursday.") (setq hebrew-calendar-year-Tuesday-regular-Thursday (vector 51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (vector 21 22) 23 24 nil 25 (vector 26 27) (vector 28 29) 30 (vector 31 32) 33 (cons nil 34) (cons 34 35) (cons 35 36) (cons 36 37) (cons 37 38) (cons (vector 38 39) 39) 40 (vector 41 42) 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot. ;Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 days and ;Kislev has 30 days), and has Passover start on Thursday.") (setq hebrew-calendar-year-Thursday-regular-Saturday (vector 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 (vector 21 22) 23 24 nil (cons nil 25) (cons 25 (vector 26 27)) (cons (vector 26 27) (vector 28 29)) (cons (vector 28 29) 30) (cons 30 31) (cons (vector 31 32) 32) 33 34 35 36 37 38 39 40 (vector 41 42) 43 44 45 46 47 48 49 50)) ; "The structure of the parashiot. ;Hebrew year that starts on Thursday, is `regular' (Heshvan has 29 days and ;Kislev has 30 days), and has Passover start on Saturday.") (setq hebrew-calendar-year-Thursday-complete-Sunday (vector 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 nil 25 (vector 26 27) (vector 28 29) 30 (vector 31 32) 33 34 35 36 37 38 39 40 (vector 41 42) 43 44 45 46 47 48 49 50)) ; "The structure of the parashiot. ;Hebrew year that starts on Thursday, is `complete' (Heshvan and Kislev each ;have 30 days), and has Passover start on Sunday.") ;; The seven leap year types (keviot) (setq hebrew-calendar-year-Saturday-incomplete-Tuesday (vector nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 nil 28 29 30 31 32 33 34 35 36 37 38 39 40 (vector 41 42) 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot. ;Hebrew year that starts on Saturday, is `incomplete' (Heshvan and Kislev each ;have 29 days), and has Passover start on Tuesday.") (setq hebrew-calendar-year-Saturday-complete-Thursday (vector nil 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 nil 28 29 30 31 32 33 (cons nil 34) (cons 34 35) (cons 35 36) (cons 36 37) (cons 37 38) (cons (vector 38 39) 39) 40 (vector 41 42) 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot ; Hebrew year that starts on Saturday, is `complete' (Heshvan and Kislev each ; have 30 days), and has Passover start on Thursday.") (setq hebrew-calendar-year-Monday-incomplete-Thursday (vector 51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 nil 28 29 30 31 32 33 (cons nil 34) (cons 34 35) (cons 35 36) (cons 36 37) (cons 37 38) (cons (vector 38 39) 39) 40 (vector 41 42) 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot. ;Hebrew year that starts on Monday, is `incomplete' (Heshvan and Kislev each ;have 29 days), and has Passover start on Thursday.") (setq hebrew-calendar-year-Monday-complete-Saturday (vector 51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 nil (cons nil 28) (cons 28 29) (cons 29 30) (cons 30 31) (cons 31 32) (cons 32 33) (cons 33 34) (cons 34 35) (cons 35 36) (cons 36 37) (cons 37 38) (cons 38 39) (cons 39 40) (cons 40 41) (cons (vector 41 42) 42) 43 44 45 46 47 48 49 50)) ; "The structure of the parashiot. ; Hebrew year that starts on Monday, is `complete' (Heshvan and Kislev each have ; 30 days), and has Passover start on Saturday.") (setq hebrew-calendar-year-Tuesday-regular-Saturday (vector 51 52 nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 nil (cons nil 28) (cons 28 29) (cons 29 30) (cons 30 31) (cons 31 32) (cons 32 33) (cons 33 34) (cons 34 35) (cons 35 36) (cons 36 37) (cons 37 38) (cons 38 39) (cons 39 40) (cons 40 41) (cons (vector 41 42) 42) 43 44 45 46 47 48 49 50)) ; "The structure of the parashiot. ; Hebrew year that starts on Tuesday, is `regular' (Heshvan has 29 days and ; Kislev has 30 days), and has Passover start on Saturday.") (setq hebrew-calendar-year-Thursday-incomplete-Sunday (vector 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 nil 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50)) ; "The structure of the parashiot. ;Hebrew year that starts on Thursday, is `incomplete' (Heshvan and Kislev both ;have 29 days), and has Passover start on Sunday.") (setq hebrew-calendar-year-Thursday-complete-Tuesday (vector 52 nil nil 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 nil 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 (vector 50 51))) ; "The structure of the parashiot. ; Hebrew year that starts on Thursday, is `complete' (Heshvan and Kislev both ; have 30 days), and has Passover start on Tuesday.") (defun hebrew-calendar-parasha-name (p) "Name(s) corresponding to parasha P." (if (arrayp p);; combined parasha (format nil "~A/~A" (aref hebrew-calendar-parashiot-names (aref p 0)) (aref hebrew-calendar-parashiot-names (aref p 1))) (aref hebrew-calendar-parashiot-names p))) (defun hebrew-calendar-yahrzeit (death-date year) "Absolute date of the anniversary of Hebrew DEATH-DATE in Hebrew YEAR." (let* ((death-day (extract-calendar-day death-date)) (death-month (extract-calendar-month death-date)) (death-year (extract-calendar-year death-date))) (cond ;; If it's Heshvan 30 it depends on the first anniversary; if ;; that was not Heshvan 30, use the day before Kislev 1. ((and (= death-month 8) (= death-day 30) (not (hebrew-calendar-long-heshvan-p (1+ death-year)))) (1- (calendar-absolute-from-hebrew (list 9 1 year)))) ;; If it's Kislev 30 it depends on the first anniversary; if ;; that was not Kislev 30, use the day before Teveth 1. ((and (= death-month 9) (= death-day 30) (hebrew-calendar-short-kislev-p (1+ death-year))) (1- (calendar-absolute-from-hebrew (list 10 1 year)))) ;; If it's Adar II, use the same day in last month of ;; year (Adar or Adar II). ((= death-month 13) (calendar-absolute-from-hebrew (list (hebrew-calendar-last-month-of-year year) death-day year))) ;; If it's the 30th in Adar I and year is not a leap year ;; (so Adar has only 29 days), use the last day in Shevat. ((and (= death-day 30) (= death-month 12) (not (hebrew-calendar-leap-year-p year))) (calendar-absolute-from-hebrew (list 11 30 year))) ;; In all other cases, use the normal anniversary of the date of death. (t (calendar-absolute-from-hebrew (list death-month death-day year)))))) (defun calendar-make-alist (sequence &optional start-index filter) "Make an assoc list corresponding to SEQUENCE. Start at index 1, unless optional START-INDEX is provided. If FILTER is provided, apply it to each item in the list." (let ((index (if start-index (1- start-index) 0))) (mapcar '(lambda (x) (setq index (1+ index)) (cons (if filter (funcall filter x) x) index)) (append sequence nil)))) (defun list-yahrzeit-dates (death-date start-year) "List Yahrzeit dates for *Gregorian* DEATH-DATE from START-YEAR to END-YEAR. When called interactively from the calendar window, the date of death is taken from the cursor position." ;(format t "~A~%" "Computing yahrzeits...") (let* ((h-date (calendar-hebrew-from-absolute (calendar-absolute-from-gregorian death-date))) (h-month (extract-calendar-month h-date)) (h-day (extract-calendar-day h-date)) (h-year (extract-calendar-year h-date)) ) (do ((p-date nil) (y-date-abs nil) (i start-year (1+ i))) ((> i start-year )) ; (format t "~% i: ~D start-year: ~D end-year: ~D~%" i start-year end-year) (setq p-date (calendar-date-string (calendar-gregorian-from-absolute (setq y-date-abs (hebrew-calendar-yahrzeit h-date (extract-calendar-year (calendar-hebrew-from-absolute (calendar-absolute-from-gregorian (list 1 1 i))))))))) (format t "~A which is observed until sunset on ~A~%" (calendar-hebrew-date-string (calendar-gregorian-from-absolute y-date-abs)) p-date)))) ;(trace (calendar-date-string :step-if t)) ;(trace calendar-absolute-from-hebrew) ;(setq dd (list 1 9 5735)) ;(setq dyr 5760) ;(hebrew-calendar-yahrzeit dd dyr) ;(setq month 1) ;(setq day 1) ;(setq year 1990) ;(list-yahrzeit-dates (list 10 17 1974) 1995 2000) ;(calendar-gregorian-from-absolute 720913) ;(defun test-do (a b) ; (do (( i a (1+ i))) ; ((>= i b) nil) ; (print i))) (load 'solar.cl) (load 'lunar.cl) (load 'cal-dst.cl) ;(trace (solar-adj-time-for-dst :step-if t)) ;(trace (solar-sunset :step-if t)) ;(trace (solar-sunrise-sunset :step-if t)) ;(trace (diary-sabbath-candles :step-if t))