Mercurial > emacs
comparison lisp/calendar/icalendar.el @ 95273:4d3975347028
Ulf Jasper <ulf.jasper at web.de>
(icalendar-version): Increase to "0.19".
(icalendar--date-style): New function.
(icalendar--datetime-to-diary-date): Doc fix. Use icalendar--date-style.
(icalendar--datestring-to-isodate): Doc fix. Handle iso date style.
(icalendar--convert-yearly-to-ical):
(icalendar--convert-recurring-to-diary): Handle iso date style,
use icalendar-date-style.
author | Glenn Morris <rgm@gnu.org> |
---|---|
date | Sat, 24 May 2008 02:26:06 +0000 |
parents | e49abd957e81 |
children | b39c4aef1848 |
comparison
equal
deleted
inserted
replaced
95272:b3a22f3768c6 | 95273:4d3975347028 |
---|---|
101 ;; + Which chars to (un)escape? | 101 ;; + Which chars to (un)escape? |
102 | 102 |
103 | 103 |
104 ;;; Code: | 104 ;;; Code: |
105 | 105 |
106 (defconst icalendar-version "0.18" | 106 (defconst icalendar-version "0.19" |
107 "Version number of icalendar.el.") | 107 "Version number of icalendar.el.") |
108 | 108 |
109 ;; ====================================================================== | 109 ;; ====================================================================== |
110 ;; Customizables | 110 ;; Customizables |
111 ;; ====================================================================== | 111 ;; ====================================================================== |
199 Some calendar browsers only propagate recurring events for | 199 Some calendar browsers only propagate recurring events for |
200 several years beyond the start time. Set this string to a year | 200 several years beyond the start time. Set this string to a year |
201 just before the start of your personal calendar." | 201 just before the start of your personal calendar." |
202 :type 'integer | 202 :type 'integer |
203 :group 'icalendar) | 203 :group 'icalendar) |
204 | |
205 | 204 |
206 (defcustom icalendar-export-hidden-diary-entries | 205 (defcustom icalendar-export-hidden-diary-entries |
207 t | 206 t |
208 "Determines whether hidden diary entries are exported. | 207 "Determines whether hidden diary entries are exported. |
209 If non-nil hidden diary entries (starting with `&') get exported, | 208 If non-nil hidden diary entries (starting with `&') get exported, |
666 (or separator " ") | 665 (or separator " ") |
667 (nth 3 datetime)) ;day | 666 (nth 3 datetime)) ;day |
668 ;; datetime == nil | 667 ;; datetime == nil |
669 nil)) | 668 nil)) |
670 | 669 |
670 (defun icalendar--date-style () | |
671 "Return current calendar date style. | |
672 Convenience function to handle transition from old | |
673 `european-calendar-style' to new `calendar-date-style'." | |
674 (if (boundp 'calendar-date-style) | |
675 calendar-date-style | |
676 (if (with-no-warnings european-calendar-style) | |
677 'european | |
678 'american))) | |
679 | |
671 (defun icalendar--datetime-to-diary-date (datetime &optional separator) | 680 (defun icalendar--datetime-to-diary-date (datetime &optional separator) |
672 "Convert the decoded DATETIME to diary format. | 681 "Convert the decoded DATETIME to diary format. |
673 Optional argument SEPARATOR gives the separator between month, | 682 Optional argument SEPARATOR gives the separator between month, |
674 day, and year. If nil a blank character is used as separator. | 683 day, and year. If nil a blank character is used as separator. |
675 Call icalendar--datetime-to-*-date according to the | 684 Call icalendar--datetime-to-*-date according to the current |
676 value of `calendar-date-style' (or the older `european-calendar-style')." | 685 calendar date style." |
677 (funcall (intern-soft (format "icalendar--datetime-to-%s-date" | 686 (funcall (intern-soft (format "icalendar--datetime-to-%s-date" |
678 (if (boundp 'calendar-date-style) | 687 (icalendar--date-style))) |
679 calendar-date-style | |
680 (if (with-no-warnings european-calendar-style) | |
681 'european | |
682 'american)))) | |
683 datetime separator)) | 688 datetime separator)) |
684 | 689 |
685 (defun icalendar--datetime-to-colontime (datetime) | 690 (defun icalendar--datetime-to-colontime (datetime) |
686 "Extract the time part of a decoded DATETIME into 24-hour format. | 691 "Extract the time part of a decoded DATETIME into 24-hour format. |
687 Note that this silently ignores seconds." | 692 Note that this silently ignores seconds." |
744 | 749 |
745 (defun icalendar--datestring-to-isodate (datestring &optional day-shift) | 750 (defun icalendar--datestring-to-isodate (datestring &optional day-shift) |
746 "Convert diary-style DATESTRING to iso-style date. | 751 "Convert diary-style DATESTRING to iso-style date. |
747 If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days | 752 If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days |
748 -- DAY-SHIFT must be either nil or an integer. This function | 753 -- DAY-SHIFT must be either nil or an integer. This function |
749 takes care of european-style." | 754 tries to figure the date style from DATESTRING itself. If that |
755 is not possible it uses the current calendar date style." | |
750 (let ((day -1) month year) | 756 (let ((day -1) month year) |
751 (save-match-data | 757 (save-match-data |
752 (cond ( ;; numeric date | 758 (cond ( ;; iso-style numeric date |
759 (string-match (concat "\\s-*" | |
760 "\\([0-9]\\{4\\}\\)[ \t/]\\s-*" | |
761 "0?\\([1-9][0-9]?\\)[ \t/]\\s-*" | |
762 "0?\\([1-9][0-9]?\\)") | |
763 datestring) | |
764 (setq year (read (substring datestring (match-beginning 1) | |
765 (match-end 1)))) | |
766 (setq month (read (substring datestring (match-beginning 2) | |
767 (match-end 2)))) | |
768 (setq day (read (substring datestring (match-beginning 3) | |
769 (match-end 3))))) | |
770 ( ;; non-iso numeric date -- must rely on configured | |
771 ;; calendar style | |
753 (string-match (concat "\\s-*" | 772 (string-match (concat "\\s-*" |
754 "0?\\([1-9][0-9]?\\)[ \t/]\\s-*" | 773 "0?\\([1-9][0-9]?\\)[ \t/]\\s-*" |
755 "0?\\([1-9][0-9]?\\),?[ \t/]\\s-*" | 774 "0?\\([1-9][0-9]?\\),?[ \t/]\\s-*" |
756 "\\([0-9]\\{4\\}\\)") | 775 "\\([0-9]\\{4\\}\\)") |
757 datestring) | 776 datestring) |
759 (match-end 1)))) | 778 (match-end 1)))) |
760 (setq month (read (substring datestring (match-beginning 2) | 779 (setq month (read (substring datestring (match-beginning 2) |
761 (match-end 2)))) | 780 (match-end 2)))) |
762 (setq year (read (substring datestring (match-beginning 3) | 781 (setq year (read (substring datestring (match-beginning 3) |
763 (match-end 3)))) | 782 (match-end 3)))) |
764 (unless european-calendar-style | 783 (if (eq (icalendar--date-style) 'american) |
765 (let ((x month)) | 784 (let ((x month)) |
766 (setq month day) | 785 (setq month day) |
767 (setq day x)))) | 786 (setq day x)))) |
768 ( ;; date contains month names -- european-style | 787 ( ;; date contains month names -- iso style |
788 (string-match (concat "\\s-*" | |
789 "\\([0-9]\\{4\\}\\)[ \t/]\\s-*" | |
790 "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" | |
791 "0?\\([123]?[0-9]\\)") | |
792 datestring) | |
793 (setq year (read (substring datestring (match-beginning 1) | |
794 (match-end 1)))) | |
795 (setq month (icalendar--get-month-number | |
796 (substring datestring (match-beginning 2) | |
797 (match-end 2)))) | |
798 (setq day (read (substring datestring (match-beginning 3) | |
799 (match-end 3))))) | |
800 ( ;; date contains month names -- european style | |
769 (string-match (concat "\\s-*" | 801 (string-match (concat "\\s-*" |
770 "0?\\([123]?[0-9]\\)[ \t/]\\s-*" | 802 "0?\\([123]?[0-9]\\)[ \t/]\\s-*" |
771 "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" | 803 "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" |
772 "\\([0-9]\\{4\\}\\)") | 804 "\\([0-9]\\{4\\}\\)") |
773 datestring) | 805 datestring) |
776 (setq month (icalendar--get-month-number | 808 (setq month (icalendar--get-month-number |
777 (substring datestring (match-beginning 2) | 809 (substring datestring (match-beginning 2) |
778 (match-end 2)))) | 810 (match-end 2)))) |
779 (setq year (read (substring datestring (match-beginning 3) | 811 (setq year (read (substring datestring (match-beginning 3) |
780 (match-end 3))))) | 812 (match-end 3))))) |
781 ( ;; date contains month names -- non-european-style | 813 ( ;; date contains month names -- american style |
782 (string-match (concat "\\s-*" | 814 (string-match (concat "\\s-*" |
783 "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" | 815 "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" |
784 "0?\\([123]?[0-9]\\),?[ \t/]\\s-*" | 816 "0?\\([123]?[0-9]\\),?[ \t/]\\s-*" |
785 "\\([0-9]\\{4\\}\\)") | 817 "\\([0-9]\\{4\\}\\)") |
786 datestring) | 818 datestring) |
796 (if (> day 0) | 828 (if (> day 0) |
797 (let ((mdy (calendar-gregorian-from-absolute | 829 (let ((mdy (calendar-gregorian-from-absolute |
798 (+ (calendar-absolute-from-gregorian (list month day | 830 (+ (calendar-absolute-from-gregorian (list month day |
799 year)) | 831 year)) |
800 (or day-shift 0))))) | 832 (or day-shift 0))))) |
833 (icalendar--dmsg (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))) | |
801 (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))) | 834 (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))) |
802 nil))) | 835 nil))) |
803 | 836 |
804 (defun icalendar--diarytime-to-isotime (timestring ampmstring) | 837 (defun icalendar--diarytime-to-isotime (timestring ampmstring) |
805 "Convert a time like 9:30pm to an iso-conform string like T213000. | 838 "Convert a time like 9:30pm to an iso-conform string like T213000. |
1065 ;; subroutines for icalendar-export-region | 1098 ;; subroutines for icalendar-export-region |
1066 (defun icalendar--convert-ordinary-to-ical (nonmarker entry-main) | 1099 (defun icalendar--convert-ordinary-to-ical (nonmarker entry-main) |
1067 "Convert \"ordinary\" diary entry to icalendar format. | 1100 "Convert \"ordinary\" diary entry to icalendar format. |
1068 NONMARKER is a regular expression matching the start of non-marking | 1101 NONMARKER is a regular expression matching the start of non-marking |
1069 entries. ENTRY-MAIN is the first line of the diary entry." | 1102 entries. ENTRY-MAIN is the first line of the diary entry." |
1070 (if (string-match (concat nonmarker | 1103 (if (string-match |
1071 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-*" | 1104 (concat nonmarker |
1072 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" | 1105 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-*" ; date |
1073 "\\(" | 1106 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" ; start time |
1074 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" | 1107 "\\(" |
1075 "\\)?" | 1108 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" ; end time |
1076 "\\s-*\\(.*?\\) ?$") | 1109 "\\)?" |
1077 entry-main) | 1110 "\\s-*\\(.*?\\) ?$") |
1111 entry-main) | |
1078 (let* ((datetime (substring entry-main (match-beginning 1) | 1112 (let* ((datetime (substring entry-main (match-beginning 1) |
1079 (match-end 1))) | 1113 (match-end 1))) |
1080 (startisostring (icalendar--datestring-to-isodate | 1114 (startisostring (icalendar--datestring-to-isodate |
1081 datetime)) | 1115 datetime)) |
1082 (endisostring (icalendar--datestring-to-isodate | 1116 (endisostring (icalendar--datestring-to-isodate |
1227 "\nDTEND;" | 1261 "\nDTEND;" |
1228 (if endtimestring | 1262 (if endtimestring |
1229 "VALUE=DATE-TIME:" | 1263 "VALUE=DATE-TIME:" |
1230 "VALUE=DATE:") | 1264 "VALUE=DATE:") |
1231 (funcall 'format "%04d%02d%02d" | 1265 (funcall 'format "%04d%02d%02d" |
1232 ;; end is non-inclusive! | 1266 ;; end is non-inclusive! |
1233 icalendar-recurring-start-year 1 | 1267 icalendar-recurring-start-year 1 |
1234 (+ (icalendar-first-weekday-of-year | 1268 (+ (icalendar-first-weekday-of-year |
1235 day icalendar-recurring-start-year) | 1269 day icalendar-recurring-start-year) |
1236 (if endtimestring 0 1))) | 1270 (if endtimestring 0 1))) |
1237 (or endtimestring "") | 1271 (or endtimestring "") |
1244 (defun icalendar--convert-yearly-to-ical (nonmarker entry-main) | 1278 (defun icalendar--convert-yearly-to-ical (nonmarker entry-main) |
1245 "Convert yearly diary entry to icalendar format. | 1279 "Convert yearly diary entry to icalendar format. |
1246 NONMARKER is a regular expression matching the start of non-marking | 1280 NONMARKER is a regular expression matching the start of non-marking |
1247 entries. ENTRY-MAIN is the first line of the diary entry." | 1281 entries. ENTRY-MAIN is the first line of the diary entry." |
1248 (if (string-match (concat nonmarker | 1282 (if (string-match (concat nonmarker |
1249 (if european-calendar-style | 1283 (if (eq (icalendar--date-style) 'european) |
1250 "0?\\([1-9]+[0-9]?\\)\\s-+\\([a-z]+\\)\\s-+" | 1284 "0?\\([1-9]+[0-9]?\\)\\s-+\\([a-z]+\\)\\s-+" |
1251 "\\([a-z]+\\)\\s-+0?\\([1-9]+[0-9]?\\)\\s-+") | 1285 "\\([a-z]+\\)\\s-+0?\\([1-9]+[0-9]?\\)\\s-+") |
1252 "\\*?\\s-*" | 1286 "\\*?\\s-*" |
1253 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" | 1287 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" |
1254 "\\(" | 1288 "\\(" |
1255 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" | 1289 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" |
1256 "\\)?" | 1290 "\\)?" |
1257 "\\s-*\\([^0-9]+.*?\\) ?$" ; must not match years | 1291 "\\s-*\\([^0-9]+.*?\\) ?$" ; must not match years |
1258 ) | 1292 ) |
1259 entry-main) | 1293 entry-main) |
1260 (let* ((daypos (if european-calendar-style 1 2)) | 1294 (let* ((daypos (if (eq (icalendar--date-style) 'european) 1 2)) |
1261 (monpos (if european-calendar-style 2 1)) | 1295 (monpos (if (eq (icalendar--date-style) 'european) 2 1)) |
1262 (day (read (substring entry-main | 1296 (day (read (substring entry-main |
1263 (match-beginning daypos) | 1297 (match-beginning daypos) |
1264 (match-end daypos)))) | 1298 (match-end daypos)))) |
1265 (month (icalendar--get-month-number | 1299 (month (icalendar--get-month-number |
1266 (substring entry-main | 1300 (substring entry-main |
2001 (if end-t "-" "") (or end-t ""))))))) | 2035 (if end-t "-" "") (or end-t ""))))))) |
2002 ;; yearly | 2036 ;; yearly |
2003 ((string-equal frequency "YEARLY") | 2037 ((string-equal frequency "YEARLY") |
2004 (icalendar--dmsg "yearly") | 2038 (icalendar--dmsg "yearly") |
2005 (if until | 2039 (if until |
2006 (setq result (format | 2040 (let ((day (nth 3 dtstart-dec)) |
2007 (concat "%%%%(and (diary-date %s %s t) " | 2041 (month (nth 4 dtstart-dec))) |
2008 "(diary-block %s %s)) %s%s%s") | 2042 (setq result (concat "%%(and (diary-date " |
2009 (if european-calendar-style (nth 3 dtstart-dec) | 2043 (cond ((eq (icalendar--date-style) 'iso) |
2010 (nth 4 dtstart-dec)) | 2044 (format "t %d %d" month day)) |
2011 (if european-calendar-style (nth 4 dtstart-dec) | 2045 ((eq (icalendar--date-style) 'european) |
2012 (nth 3 dtstart-dec)) | 2046 (format "%d %d t" day month)) |
2013 dtstart-conv | 2047 ((eq (icalendar--date-style) 'american) |
2014 until-conv | 2048 (format "%d %d t" month day))) |
2015 (or start-t "") | 2049 ") (diary-block " |
2016 (if end-t "-" "") (or end-t ""))) | 2050 dtstart-conv |
2051 " " | |
2052 until-conv | |
2053 ")) " | |
2054 (or start-t "") | |
2055 (if end-t "-" "") | |
2056 (or end-t "")))) | |
2017 (setq result (format | 2057 (setq result (format |
2018 "%%%%(and (diary-anniversary %s)) %s%s%s" | 2058 "%%%%(and (diary-anniversary %s)) %s%s%s" |
2019 dtstart-conv | 2059 dtstart-conv |
2020 (or start-t "") | 2060 (or start-t "") |
2021 (if end-t "-" "") (or end-t ""))))) | 2061 (if end-t "-" "") (or end-t ""))))) |
2022 ;; monthly | 2062 ;; monthly |
2023 ((string-equal frequency "MONTHLY") | 2063 ((string-equal frequency "MONTHLY") |
2024 (icalendar--dmsg "monthly") | 2064 (icalendar--dmsg "monthly") |
2025 (setq result | 2065 (setq result |
2026 (format | 2066 (format |
2027 "%%%%(and (diary-date %s %s %s) (diary-block %s %s)) %s%s%s" | 2067 "%%%%(and (diary-date %s) (diary-block %s %s)) %s%s%s" |
2028 (if european-calendar-style (nth 3 dtstart-dec) "t") | 2068 (let ((day (nth 3 dtstart-dec))) |
2029 (if european-calendar-style "t" (nth 3 dtstart-dec)) | 2069 (cond ((eq (icalendar--date-style) 'iso) |
2030 "t" | 2070 (format "t t %d" day)) |
2071 ((eq (icalendar--date-style) 'european) | |
2072 (format "%d t t" day)) | |
2073 ((eq (icalendar--date-style) 'american) | |
2074 (format "t %d t" day)))) | |
2031 dtstart-conv | 2075 dtstart-conv |
2032 (if until | 2076 (if until |
2033 until-conv | 2077 until-conv |
2034 "1 1 9999") ;; FIXME: should be unlimited | 2078 (if (eq (icalendar--date-style) 'iso) "9999 1 1" "1 1 9999")) ;; FIXME: should be unlimited |
2035 (or start-t "") | 2079 (or start-t "") |
2036 (if end-t "-" "") (or end-t "")))) | 2080 (if end-t "-" "") (or end-t "")))) |
2037 ;; daily | 2081 ;; daily |
2038 ((and (string-equal frequency "DAILY")) | 2082 ((and (string-equal frequency "DAILY")) |
2039 (if until | 2083 (if until |