| 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 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
(defvar date) |
|---|
| 40 |
|
|---|
| 41 |
(require 'calendar) |
|---|
| 42 |
|
|---|
| 43 |
(defun calendar-absolute-from-iso (date) |
|---|
| 44 |
"The number of days elapsed between the Gregorian date 12/31/1 BC and DATE. |
|---|
| 45 |
The `ISO year' corresponds approximately to the Gregorian year, but |
|---|
| 46 |
weeks start on Monday and end on Sunday. The first week of the ISO year is |
|---|
| 47 |
the first such week in which at least 4 days are in a year. The ISO |
|---|
| 48 |
commercial DATE has the form (week day year) in which week is in the range |
|---|
| 49 |
1..52 and day is in the range 0..6 (1 = Monday, 2 = Tuesday, ..., 0 = |
|---|
| 50 |
Sunday). The Gregorian date Sunday, December 31, 1 BC is imaginary." |
|---|
| 51 |
(let* ((week (extract-calendar-month date)) |
|---|
| 52 |
(day (extract-calendar-day date)) |
|---|
| 53 |
(year (extract-calendar-year date))) |
|---|
| 54 |
(+ (calendar-dayname-on-or-before |
|---|
| 55 |
1 (+ 3 (calendar-absolute-from-gregorian (list 1 1 year)))) |
|---|
| 56 |
(* 7 (1- week)) |
|---|
| 57 |
(if (= day 0) 6 (1- day))))) |
|---|
| 58 |
|
|---|
| 59 |
(defun calendar-iso-from-absolute (date) |
|---|
| 60 |
"Compute the `ISO commercial date' corresponding to the absolute DATE. |
|---|
| 61 |
The ISO year corresponds approximately to the Gregorian year, but weeks |
|---|
| 62 |
start on Monday and end on Sunday. The first week of the ISO year is the |
|---|
| 63 |
first such week in which at least 4 days are in a year. The ISO commercial |
|---|
| 64 |
date has the form (week day year) in which week is in the range 1..52 and |
|---|
| 65 |
day is in the range 0..6 (1 = Monday, 2 = Tuesday, ..., 0 = Sunday). The |
|---|
| 66 |
absolute date is the number of days elapsed since the (imaginary) Gregorian |
|---|
| 67 |
date Sunday, December 31, 1 BC." |
|---|
| 68 |
(let* ((approx (extract-calendar-year |
|---|
| 69 |
(calendar-gregorian-from-absolute (- date 3)))) |
|---|
| 70 |
(year (+ approx |
|---|
| 71 |
(calendar-sum y approx |
|---|
| 72 |
(>= date (calendar-absolute-from-iso (list 1 1 (1+ y)))) |
|---|
| 73 |
1)))) |
|---|
| 74 |
(list |
|---|
| 75 |
(1+ (/ (- date (calendar-absolute-from-iso (list 1 1 year))) 7)) |
|---|
| 76 |
(% date 7) |
|---|
| 77 |
year))) |
|---|
| 78 |
|
|---|
| 79 |
(defun calendar-iso-date-string (&optional date) |
|---|
| 80 |
"String of ISO date of Gregorian DATE. |
|---|
| 81 |
Defaults to today's date if DATE is not given." |
|---|
| 82 |
(let* ((d (calendar-absolute-from-gregorian |
|---|
| 83 |
(or date (calendar-current-date)))) |
|---|
| 84 |
(day (% d 7)) |
|---|
| 85 |
(iso-date (calendar-iso-from-absolute d))) |
|---|
| 86 |
(format "Day %s of week %d of %d" |
|---|
| 87 |
(if (zerop day) 7 day) |
|---|
| 88 |
(extract-calendar-month iso-date) |
|---|
| 89 |
(extract-calendar-year iso-date)))) |
|---|
| 90 |
|
|---|
| 91 |
(defun calendar-print-iso-date () |
|---|
| 92 |
"Show equivalent ISO date for the date under the cursor." |
|---|
| 93 |
(interactive) |
|---|
| 94 |
(message "ISO date: %s" |
|---|
| 95 |
(calendar-iso-date-string (calendar-cursor-to-date t)))) |
|---|
| 96 |
|
|---|
| 97 |
(defun calendar-iso-read-args (&optional dayflag) |
|---|
| 98 |
"Interactively read the arguments for an iso date command." |
|---|
| 99 |
(let* ((today (calendar-current-date)) |
|---|
| 100 |
(year (calendar-read |
|---|
| 101 |
"ISO calendar year (>0): " |
|---|
| 102 |
'(lambda (x) (> x 0)) |
|---|
| 103 |
(int-to-string (extract-calendar-year today)))) |
|---|
| 104 |
(no-weeks (extract-calendar-month |
|---|
| 105 |
(calendar-iso-from-absolute |
|---|
| 106 |
(1- |
|---|
| 107 |
(calendar-dayname-on-or-before |
|---|
| 108 |
1 (calendar-absolute-from-gregorian |
|---|
| 109 |
(list 1 4 (1+ year)))))))) |
|---|
| 110 |
(week (calendar-read |
|---|
| 111 |
(format "ISO calendar week (1-%d): " no-weeks) |
|---|
| 112 |
'(lambda (x) (and (> x 0) (<= x no-weeks))))) |
|---|
| 113 |
(day (if dayflag (calendar-read |
|---|
| 114 |
"ISO day (1-7): " |
|---|
| 115 |
'(lambda (x) (and (<= 1 x) (<= x 7)))) |
|---|
| 116 |
1))) |
|---|
| 117 |
(list (list week day year)))) |
|---|
| 118 |
|
|---|
| 119 |
(defun calendar-goto-iso-date (date &optional noecho) |
|---|
| 120 |
"Move cursor to ISO DATE; echo ISO date unless NOECHO is t." |
|---|
| 121 |
(interactive (calendar-iso-read-args t)) |
|---|
| 122 |
(calendar-goto-date (calendar-gregorian-from-absolute |
|---|
| 123 |
(calendar-absolute-from-iso date))) |
|---|
| 124 |
(or noecho (calendar-print-iso-date))) |
|---|
| 125 |
|
|---|
| 126 |
(defun calendar-goto-iso-week (date &optional noecho) |
|---|
| 127 |
"Move cursor to ISO DATE; echo ISO date unless NOECHO is t. |
|---|
| 128 |
Interactively, goes to the first day of the specified week." |
|---|
| 129 |
(interactive (calendar-iso-read-args)) |
|---|
| 130 |
(calendar-goto-date (calendar-gregorian-from-absolute |
|---|
| 131 |
(calendar-absolute-from-iso date))) |
|---|
| 132 |
(or noecho (calendar-print-iso-date))) |
|---|
| 133 |
|
|---|
| 134 |
(defun diary-iso-date () |
|---|
| 135 |
"ISO calendar equivalent of date diary entry." |
|---|
| 136 |
(format "ISO date: %s" (calendar-iso-date-string date))) |
|---|
| 137 |
|
|---|
| 138 |
(provide 'cal-iso) |
|---|
| 139 |
|
|---|
| 140 |
|
|---|
| 141 |
|
|---|
| 142 |
|
|---|