aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2004-11-02 01:05:27 +0000
committerGlenn Morris2004-11-02 01:05:27 +0000
commit81d565943da7e109fdbc27540608b31a6f1d0ebc (patch)
treec5934c73d7b8b5d015e26550e6eb3fac4da491d8
parent3467488ee7d0b3eb3b4c34da94eee2243636bc5b (diff)
downloademacs-81d565943da7e109fdbc27540608b31a6f1d0ebc.tar.gz
emacs-81d565943da7e109fdbc27540608b31a6f1d0ebc.zip
From Ulf Jasper <ulf.jasper@web.de>:
(icalendar-version): Increase to 0.08. (icalendar--split-value): Change name of work buffer. (icalendar--get-weekday-abbrev): Return nil on error. (icalendar--date-to-isodate): New function. (icalendar-convert-diary-to-ical) (icalendar-extract-ical-from-buffer): Use only two args for make-obsolete (XEmacs compatibility). (icalendar-export-file, icalendar-import-file): Blank at end of prompt. (icalendar-export-region): Doc fix. If error, return non-nil and write errors to buffer ` *icalendar-errors*'. Use correct weekday for weekly recurring events. Check whether date has been parsed for ordinary events. Make weekly events start in the year 2000. DTEND is non-inclusive, shift end date by one day if necessary (not for entries that have date and time). Rename local let variables: oops -> found-error, datestring -> startdatestring.
-rw-r--r--lisp/calendar/icalendar.el724
1 files changed, 383 insertions, 341 deletions
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 5f581e1d74a..dc3bf016053 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -31,16 +31,7 @@
31 31
32;;; History: 32;;; History:
33 33
34;; 0.07: Renamed commands! 34;; 0.07 onwards: see lisp/ChangeLog
35;; icalendar-extract-ical-from-buffer -> icalendar-import-buffer
36;; icalendar-convert-diary-to-ical -> icalendar-export-file
37;; Naming scheme: icalendar-.* = user command; icalendar--.* =
38;; internal.
39;; Added icalendar-export-region.
40;; The import and export commands do not clear their target file,
41;; but append their results to the target file.
42;; I18n-problems fixed -- use calendar-(month|day)-name-array.
43;; Fixed problems with export of multi-line diary entries.
44 35
45;; 0.06: Bugfixes regarding icalendar-import-format-*. 36;; 0.06: Bugfixes regarding icalendar-import-format-*.
46;; Fix in icalendar-convert-diary-to-ical -- thanks to Philipp 37;; Fix in icalendar-convert-diary-to-ical -- thanks to Philipp
@@ -99,7 +90,7 @@
99 90
100;;; Code: 91;;; Code:
101 92
102(defconst icalendar-version 0.07 93(defconst icalendar-version 0.08
103 "Version number of icalendar.el.") 94 "Version number of icalendar.el.")
104 95
105;; ====================================================================== 96;; ======================================================================
@@ -333,7 +324,7 @@ children."
333 param-name param-value) 324 param-name param-value)
334 (when value-string 325 (when value-string
335 (save-current-buffer 326 (save-current-buffer
336 (set-buffer (get-buffer-create " *ical-temp*")) 327 (set-buffer (get-buffer-create " *icalendar-work*"))
337 (set-buffer-modified-p nil) 328 (set-buffer-modified-p nil)
338 (erase-buffer) 329 (erase-buffer)
339 (insert value-string) 330 (insert value-string)
@@ -529,7 +520,17 @@ Note that this silently ignores seconds."
529 (setq num (1+ num)))) 520 (setq num (1+ num))))
530 calendar-day-name-array)) 521 calendar-day-name-array))
531 ;; Error: 522 ;; Error:
532 "??")) 523 nil))
524
525(defun icalendar--date-to-isodate (date &optional day-shift)
526 "Convert DATE to iso-style date.
527DATE must be a list of the form (month day year).
528If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days."
529 (let ((mdy (calendar-gregorian-from-absolute
530 (+ (calendar-absolute-from-gregorian date)
531 (or day-shift 0)))))
532 (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))))
533
533 534
534(defun icalendar--datestring-to-isodate (datestring &optional day-shift) 535(defun icalendar--datestring-to-isodate (datestring &optional day-shift)
535 "Convert diary-style DATESTRING to iso-style date. 536 "Convert diary-style DATESTRING to iso-style date.
@@ -587,7 +588,7 @@ takes care of european-style."
587 (if (> day 0) 588 (if (> day 0)
588 (let ((mdy (calendar-gregorian-from-absolute 589 (let ((mdy (calendar-gregorian-from-absolute
589 (+ (calendar-absolute-from-gregorian (list month day 590 (+ (calendar-absolute-from-gregorian (list month day
590 year)) 591 year))
591 (or day-shift 0))))) 592 (or day-shift 0)))))
592 (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))) 593 (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy)))
593 nil))) 594 nil)))
@@ -625,22 +626,24 @@ would be \"pm\"."
625 "Export diary file to iCalendar format. 626 "Export diary file to iCalendar format.
626All diary entries in the file DIARY-FILENAME are converted to iCalendar 627All diary entries in the file DIARY-FILENAME are converted to iCalendar
627format. The result is appended to the file ICAL-FILENAME." 628format. The result is appended to the file ICAL-FILENAME."
628 (interactive "FExport diary data from file: 629 (interactive "FExport diary data from file:
629Finto iCalendar file: ") 630Finto iCalendar file: ")
630 (save-current-buffer 631 (save-current-buffer
631 (set-buffer (find-file diary-filename)) 632 (set-buffer (find-file diary-filename))
632 (icalendar-export-region (point-min) (point-max) ical-filename))) 633 (icalendar-export-region (point-min) (point-max) ical-filename)))
633 634
634(defalias 'icalendar-convert-diary-to-ical 'icalendar-export-file) 635(defalias 'icalendar-convert-diary-to-ical 'icalendar-export-file)
635(make-obsolete 'icalendar-convert-diary-to-ical 'icalendar-export-file 636(make-obsolete 'icalendar-convert-diary-to-ical 'icalendar-export-file)
636 "icalendar 0.07")
637 637
638;; User function 638;; User function
639(defun icalendar-export-region (min max ical-filename) 639(defun icalendar-export-region (min max ical-filename)
640 "Export region in diary file to iCalendar format. 640 "Export region in diary file to iCalendar format.
641All diary entries in the region from MIN to MAX in the current buffer are 641All diary entries in the region from MIN to MAX in the current buffer are
642converted to iCalendar format. The result is appended to the file 642converted to iCalendar format. The result is appended to the file
643ICAL-FILENAME." 643ICAL-FILENAME.
644
645Returns non-nil if an error occurred. In this case an error message is
646written to the buffer ` *icalendar-errors*'."
644 (interactive "r 647 (interactive "r
645FExport diary data into iCalendar file: ") 648FExport diary data into iCalendar file: ")
646 (let ((result "") 649 (let ((result "")
@@ -649,9 +652,14 @@ FExport diary data into iCalendar file: ")
649 (entry-rest "") 652 (entry-rest "")
650 (header "") 653 (header "")
651 (contents) 654 (contents)
652 (oops nil) 655 (found-error nil)
653 (nonmarker (concat "^" (regexp-quote diary-nonmarking-symbol) 656 (nonmarker (concat "^" (regexp-quote diary-nonmarking-symbol)
654 "?"))) 657 "?")))
658 ;; prepare buffer with error messages
659 (save-current-buffer
660 (set-buffer (get-buffer-create " *icalendar-errors*"))
661 (erase-buffer))
662 ;; here we go
655 (save-excursion 663 (save-excursion
656 (goto-char min) 664 (goto-char min)
657 (while (re-search-forward 665 (while (re-search-forward
@@ -664,330 +672,366 @@ FExport diary data into iCalendar file: ")
664 (car (current-time)) 672 (car (current-time))
665 (cadr (current-time)) 673 (cadr (current-time))
666 (car (cddr (current-time))))) 674 (car (cddr (current-time)))))
667 (setq oops nil) 675 (condition-case error-val
668 (cond 676 (progn
669 ;; anniversaries 677 (cond
670 ((string-match 678 ;; anniversaries
671 (concat nonmarker 679 ((string-match
672 "%%(diary-anniversary \\([^)]+\\))\\s-*\\(.*\\)") 680 (concat nonmarker
673 entry-main) 681 "%%(diary-anniversary \\([^)]+\\))\\s-*\\(.*\\)")
674 (icalendar--dmsg "diary-anniversary %s" entry-main) 682 entry-main)
675 (let* ((datetime (substring entry-main (match-beginning 1) 683 (icalendar--dmsg "diary-anniversary %s" entry-main)
676 (match-end 1))) 684 (let* ((datetime (substring entry-main (match-beginning 1)
677 (summary (icalendar--convert-string-for-export 685 (match-end 1)))
678 (substring entry-main (match-beginning 2) 686 (summary (icalendar--convert-string-for-export
679 (match-end 2)))) 687 (substring entry-main (match-beginning 2)
680 (startisostring (icalendar--datestring-to-isodate 688 (match-end 2))))
681 datetime)) 689 (startisostring (icalendar--datestring-to-isodate
682 (endisostring (icalendar--datestring-to-isodate 690 datetime))
683 datetime 1))) 691 (endisostring (icalendar--datestring-to-isodate
684 (setq contents 692 datetime 1)))
685 (concat "\nDTSTART;VALUE=DATE:" startisostring 693 (setq contents
686 "\nDTEND;VALUE=DATE:" endisostring 694 (concat "\nDTSTART;VALUE=DATE:" startisostring
687 "\nSUMMARY:" summary 695 "\nDTEND;VALUE=DATE:" endisostring
688 "\nRRULE:FREQ=YEARLY;INTERVAL=1" 696 "\nSUMMARY:" summary
689 ;; the following is redundant, 697 "\nRRULE:FREQ=YEARLY;INTERVAL=1"
690 ;; but korganizer seems to expect this... ;( 698 ;; the following is redundant,
691 ;; and evolution doesn't understand it... :( 699 ;; but korganizer seems to expect this... ;(
692 ;; so... who is wrong?! 700 ;; and evolution doesn't understand it... :(
693 ";BYMONTH=" (substring startisostring 4 6) 701 ;; so... who is wrong?!
694 ";BYMONTHDAY=" (substring startisostring 6 8) 702 ";BYMONTH=" (substring startisostring 4 6)
695 ))) 703 ";BYMONTHDAY=" (substring startisostring 6 8)
696 (unless (string= entry-rest "") 704 )))
697 (setq contents (concat contents "\nDESCRIPTION:" 705 (unless (string= entry-rest "")
698 (icalendar--convert-string-for-export 706 (setq contents (concat contents "\nDESCRIPTION:"
699 entry-rest))))) 707 (icalendar--convert-string-for-export
700 ;; cyclic events 708 entry-rest)))))
701 ;; %%(diary-cyclic ) 709 ;; cyclic events
702 ((string-match 710 ;; %%(diary-cyclic )
703 (concat nonmarker 711 ((string-match
704 "%%(diary-cyclic \\([^ ]+\\) +" 712 (concat nonmarker
705 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") 713 "%%(diary-cyclic \\([^ ]+\\) +"
706 entry-main) 714 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)")
707 (icalendar--dmsg "diary-cyclic %s" entry-main) 715 entry-main)
708 (let* ((frequency (substring entry-main (match-beginning 1) 716 (icalendar--dmsg "diary-cyclic %s" entry-main)
709 (match-end 1))) 717 (let* ((frequency (substring entry-main (match-beginning 1)
710 (datetime (substring entry-main (match-beginning 2) 718 (match-end 1)))
711 (match-end 2))) 719 (datetime (substring entry-main (match-beginning 2)
712 (summary (icalendar--convert-string-for-export 720 (match-end 2)))
713 (substring entry-main (match-beginning 3) 721 (summary (icalendar--convert-string-for-export
714 (match-end 3)))) 722 (substring entry-main (match-beginning 3)
715 (startisostring (icalendar--datestring-to-isodate 723 (match-end 3))))
716 datetime)) 724 (startisostring (icalendar--datestring-to-isodate
717 (endisostring (icalendar--datestring-to-isodate 725 datetime))
718 datetime 1))) 726 (endisostring (icalendar--datestring-to-isodate
719 (setq contents 727 datetime 1)))
720 (concat "\nDTSTART;VALUE=DATE:" startisostring 728 (setq contents
721 "\nDTEND;VALUE=DATE:" endisostring 729 (concat "\nDTSTART;VALUE=DATE:" startisostring
722 "\nSUMMARY:" summary 730 "\nDTEND;VALUE=DATE:" endisostring
723 "\nRRULE:FREQ=DAILY;INTERVAL=" frequency 731 "\nSUMMARY:" summary
724 ;; strange: korganizer does not expect 732 "\nRRULE:FREQ=DAILY;INTERVAL=" frequency
725 ;; BYSOMETHING here... 733 ;; strange: korganizer does not expect
726 ))) 734 ;; BYSOMETHING here...
727 (unless (string= entry-rest "") 735 )))
728 (setq contents (concat contents "\nDESCRIPTION:" 736 (unless (string= entry-rest "")
729 (icalendar--convert-string-for-export 737 (setq contents (concat contents "\nDESCRIPTION:"
730 entry-rest))))) 738 (icalendar--convert-string-for-export
731 ;; diary-date -- FIXME 739 entry-rest)))))
732 ((string-match 740 ;; diary-date -- FIXME
733 (concat nonmarker 741 ((string-match
734 "%%(diary-date \\([^)]+\\))\\s-*\\(.*\\)") 742 (concat nonmarker
735 entry-main) 743 "%%(diary-date \\([^)]+\\))\\s-*\\(.*\\)")
736 (icalendar--dmsg "diary-date %s" entry-main) 744 entry-main)
737 (setq oops t)) 745 (icalendar--dmsg "diary-date %s" entry-main)
738 ;; float events -- FIXME 746 (error "`diary-date' is not supported yet"))
739 ((string-match 747 ;; float events -- FIXME
740 (concat nonmarker 748 ((string-match
741 "%%(diary-float \\([^)]+\\))\\s-*\\(.*\\)") 749 (concat nonmarker
742 entry-main) 750 "%%(diary-float \\([^)]+\\))\\s-*\\(.*\\)")
743 (icalendar--dmsg "diary-float %s" entry-main) 751 entry-main)
744 (setq oops t)) 752 (icalendar--dmsg "diary-float %s" entry-main)
745 ;; block events 753 (error "`diary-float' is not supported yet"))
746 ((string-match 754 ;; block events
747 (concat nonmarker 755 ((string-match
748 "%%(diary-block \\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\) +" 756 (concat nonmarker
749 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") 757 "%%(diary-block \\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\) +"
750 entry-main) 758 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)")
751 (icalendar--dmsg "diary-block %s" entry-main) 759 entry-main)
752 (let* ((startstring (substring entry-main (match-beginning 1) 760 (icalendar--dmsg "diary-block %s" entry-main)
753 (match-end 1))) 761 (let* ((startstring (substring entry-main (match-beginning 1)
754 (endstring (substring entry-main (match-beginning 2) 762 (match-end 1)))
755 (match-end 2))) 763 (endstring (substring entry-main (match-beginning 2)
756 (summary (icalendar--convert-string-for-export 764 (match-end 2)))
757 (substring entry-main (match-beginning 3) 765 (summary (icalendar--convert-string-for-export
758 (match-end 3)))) 766 (substring entry-main (match-beginning 3)
759 (startisostring (icalendar--datestring-to-isodate 767 (match-end 3))))
760 startstring)) 768 (startisostring (icalendar--datestring-to-isodate
761 (endisostring (icalendar--datestring-to-isodate 769 startstring))
762 endstring 1))) 770 (endisostring (icalendar--datestring-to-isodate
763 (setq contents 771 endstring 1)))
764 (concat "\nDTSTART;VALUE=DATE:" startisostring 772 (setq contents
765 "\nDTEND;VALUE=DATE:" endisostring 773 (concat "\nDTSTART;VALUE=DATE:" startisostring
766 "\nSUMMARY:" summary 774 "\nDTEND;VALUE=DATE:" endisostring
767 )) 775 "\nSUMMARY:" summary
768 (unless (string= entry-rest "") 776 ))
769 (setq contents (concat contents "\nDESCRIPTION:" 777 (unless (string= entry-rest "")
770 (icalendar--convert-string-for-export 778 (setq contents (concat contents "\nDESCRIPTION:"
771 entry-rest)))))) 779 (icalendar--convert-string-for-export
772 ;; other sexp diary entries -- FIXME 780 entry-rest))))))
773 ((string-match 781 ;; other sexp diary entries -- FIXME
774 (concat nonmarker 782 ((string-match
775 "%%(\\([^)]+\\))\\s-*\\(.*\\)") 783 (concat nonmarker
776 entry-main) 784 "%%(\\([^)]+\\))\\s-*\\(.*\\)")
777 (icalendar--dmsg "diary-sexp %s" entry-main) 785 entry-main)
778 (setq oops t)) 786 (icalendar--dmsg "diary-sexp %s" entry-main)
779 ;; weekly by day 787 (error "sexp-entries are not supported yet"))
780 ;; Monday 8:30 Team meeting 788 ;; weekly by day
781 ((and (string-match 789 ;; Monday 8:30 Team meeting
782 (concat nonmarker 790 ((and (string-match
783 "\\([a-z]+\\)\\s-+" 791 (concat nonmarker
784 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" 792 "\\([a-z]+\\)\\s-+"
785 "\\(-0?" 793 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
786 "\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" 794 "\\(-0?"
787 "\\)?" 795 "\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
788 "\\s-*\\(.*\\)$") 796 "\\)?"
789 entry-main) 797 "\\s-*\\(.*\\)$")
790 (icalendar--get-weekday-abbrev 798 entry-main)
791 (substring entry-main (match-beginning 1) (match-end 1)))) 799 (icalendar--get-weekday-abbrev
792 (icalendar--dmsg "weekly %s" entry-main) 800 (substring entry-main (match-beginning 1) (match-end 1))))
793 (let* ((day (icalendar--get-weekday-abbrev 801 (icalendar--dmsg "weekly %s" entry-main)
794 (substring entry-main (match-beginning 1) 802 (let* ((day (icalendar--get-weekday-abbrev
795 (match-end 1)))) 803 (substring entry-main (match-beginning 1)
796 (starttimestring (icalendar--diarytime-to-isotime 804 (match-end 1))))
797 (if (match-beginning 3) 805 (starttimestring (icalendar--diarytime-to-isotime
798 (substring entry-main 806 (if (match-beginning 3)
799 (match-beginning 3) 807 (substring entry-main
800 (match-end 3)) 808 (match-beginning 3)
801 nil) 809 (match-end 3))
802 (if (match-beginning 4) 810 nil)
803 (substring entry-main 811 (if (match-beginning 4)
804 (match-beginning 4) 812 (substring entry-main
805 (match-end 4)) 813 (match-beginning 4)
806 nil))) 814 (match-end 4))
807 (endtimestring (icalendar--diarytime-to-isotime 815 nil)))
808 (if (match-beginning 6) 816 (endtimestring (icalendar--diarytime-to-isotime
809 (substring entry-main 817 (if (match-beginning 6)
810 (match-beginning 6) 818 (substring entry-main
811 (match-end 6)) 819 (match-beginning 6)
812 nil) 820 (match-end 6))
813 (if (match-beginning 7) 821 nil)
814 (substring entry-main 822 (if (match-beginning 7)
815 (match-beginning 7) 823 (substring entry-main
816 (match-end 7)) 824 (match-beginning 7)
817 nil))) 825 (match-end 7))
818 (summary (icalendar--convert-string-for-export 826 nil)))
819 (substring entry-main (match-beginning 8) 827 (summary (icalendar--convert-string-for-export
820 (match-end 8))))) 828 (substring entry-main (match-beginning 8)
821 (when starttimestring 829 (match-end 8)))))
822 (unless endtimestring 830 (when starttimestring
823 (let ((time (read (icalendar--rris "^T0?" "" 831 (unless endtimestring
824 starttimestring)))) 832 (let ((time (read (icalendar--rris "^T0?" ""
825 (setq endtimestring (format "T%06d" (+ 10000 time)))))) 833 starttimestring))))
826 (setq contents 834 (setq endtimestring (format "T%06d" (+ 10000 time))))))
827 (concat "\nDTSTART" 835 (setq contents
828 (if starttimestring "" ";VALUE=DATE") 836 (concat "\nDTSTART;"
829 ":19000101" ;; FIXME? Probability that this 837 (if starttimestring
830 ;; is the right day is 1/7 838 "VALUE=DATE-TIME:"
831 (or starttimestring "") 839 "VALUE=DATE:")
832 "\nDTEND" 840 ;; find the correct week day,
833 (if endtimestring "" ";VALUE=DATE") 841 ;; 1st january 2000 was a saturday
834 ":19000101" ;; FIXME? 842 (format
835 (or endtimestring "") 843 "200001%02d"
836 "\nSUMMARY:" summary 844 (+ (icalendar--get-weekday-number day) 2))
837 "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=" day 845 (or starttimestring "")
838 ))) 846 "\nDTEND;"
839 (unless (string= entry-rest "") 847 (if endtimestring
840 (setq contents (concat contents "\nDESCRIPTION:" 848 "VALUE=DATE-TIME:"
841 (icalendar--convert-string-for-export 849 "VALUE=DATE:")
842 entry-rest))))) 850 (format
843 ;; yearly by day 851 "200001%02d"
844 ;; 1 May Tag der Arbeit 852 ;; end is non-inclusive!
845 ((string-match 853 (+ (icalendar--get-weekday-number day)
846 (concat nonmarker 854 (if endtimestring 2 3)))
847 (if european-calendar-style 855 (or endtimestring "")
848 "0?\\([1-9]+[0-9]?\\)\\s-+\\([a-z]+\\)\\s-+" 856 "\nSUMMARY:" summary
849 "\\([a-z]+\\)\\s-+0?\\([1-9]+[0-9]?\\)\\s-+") 857 "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=" day
850 "\\*?\\s-*" 858 )))
851 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" 859 (unless (string= entry-rest "")
852 "\\(" 860 (setq contents (concat contents "\nDESCRIPTION:"
853 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" 861 (icalendar--convert-string-for-export
854 "\\)?" 862 entry-rest)))))
855 "\\s-*\\([^0-9]+.*\\)$" ; must not match years 863 ;; yearly by day
856 ) 864 ;; 1 May Tag der Arbeit
857 entry-main) 865 ((string-match
858 (icalendar--dmsg "yearly %s" entry-main) 866 (concat nonmarker
859 (let* ((daypos (if european-calendar-style 1 2)) 867 (if european-calendar-style
860 (monpos (if european-calendar-style 2 1)) 868 "0?\\([1-9]+[0-9]?\\)\\s-+\\([a-z]+\\)\\s-+"
861 (day (read (substring entry-main (match-beginning daypos) 869 "\\([a-z]+\\)\\s-+0?\\([1-9]+[0-9]?\\)\\s-+")
862 (match-end daypos)))) 870 "\\*?\\s-*"
863 (month (icalendar--get-month-number 871 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
864 (substring entry-main (match-beginning monpos) 872 "\\("
865 (match-end monpos)))) 873 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
866 (starttimestring (icalendar--diarytime-to-isotime 874 "\\)?"
867 (if (match-beginning 4) 875 "\\s-*\\([^0-9]+.*\\)$" ; must not match years
868 (substring entry-main 876 )
869 (match-beginning 4) 877 entry-main)
870 (match-end 4)) 878 (icalendar--dmsg "yearly %s" entry-main)
871 nil) 879 (let* ((daypos (if european-calendar-style 1 2))
872 (if (match-beginning 5) 880 (monpos (if european-calendar-style 2 1))
873 (substring entry-main 881 (day (read (substring entry-main (match-beginning daypos)
874 (match-beginning 5) 882 (match-end daypos))))
875 (match-end 5)) 883 (month (icalendar--get-month-number
876 nil))) 884 (substring entry-main (match-beginning monpos)
877 (endtimestring (icalendar--diarytime-to-isotime 885 (match-end monpos))))
878 (if (match-beginning 7) 886 (starttimestring (icalendar--diarytime-to-isotime
879 (substring entry-main 887 (if (match-beginning 4)
880 (match-beginning 7) 888 (substring entry-main
881 (match-end 7)) 889 (match-beginning 4)
882 nil) 890 (match-end 4))
883 (if (match-beginning 8) 891 nil)
884 (substring entry-main 892 (if (match-beginning 5)
885 (match-beginning 8) 893 (substring entry-main
886 (match-end 8)) 894 (match-beginning 5)
887 nil))) 895 (match-end 5))
888 (summary (icalendar--convert-string-for-export 896 nil)))
889 (substring entry-main (match-beginning 9) 897 (endtimestring (icalendar--diarytime-to-isotime
890 (match-end 9))))) 898 (if (match-beginning 7)
891 (when starttimestring 899 (substring entry-main
892 (unless endtimestring 900 (match-beginning 7)
893 (let ((time (read (icalendar--rris "^T0?" "" 901 (match-end 7))
894 starttimestring)))) 902 nil)
895 (setq endtimestring (format "T%06d" (+ 10000 time)))))) 903 (if (match-beginning 8)
896 (setq contents 904 (substring entry-main
897 (concat "\nDTSTART" 905 (match-beginning 8)
898 (if starttimestring "" ";VALUE=DATE") 906 (match-end 8))
899 (format ":1900%02d%02d" month day) 907 nil)))
900 (or starttimestring "") 908 (summary (icalendar--convert-string-for-export
901 "\nDTEND" 909 (substring entry-main (match-beginning 9)
902 (if endtimestring "" ";VALUE=DATE") 910 (match-end 9)))))
903 (format ":1900%02d%02d" month day) 911 (when starttimestring
904 (or endtimestring "") 912 (unless endtimestring
905 "\nSUMMARY:" summary 913 (let ((time (read (icalendar--rris "^T0?" ""
906 "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=" 914 starttimestring))))
907 (format "%2d" month) 915 (setq endtimestring (format "T%06d" (+ 10000 time))))))
908 ";BYMONTHDAY=" 916 (setq contents
909 (format "%2d" day) 917 (concat "\nDTSTART;"
910 ))) 918 (if starttimestring "VALUE=DATE-TIME:"
911 (unless (string= entry-rest "") 919 "VALUE=DATE:")
912 (setq contents (concat contents "\nDESCRIPTION:" 920 (format "1900%02d%02d" month day)
913 (icalendar--convert-string-for-export 921 (or starttimestring "")
914 entry-rest))))) 922 "\nDTEND;"
915 ;; "ordinary" events, start and end time given 923 (if endtimestring "VALUE=DATE-TIME:"
916 ;; 1 Feb 2003 Hs Hochzeitsfeier, Dreieich 924 "VALUE=DATE:")
917 ((string-match 925 ;; end is not included! shift by one day
918 (concat nonmarker 926 (icalendar--date-to-isodate
919 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-+" 927 (list month day 1900) (if endtimestring 0 1))
920 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" 928 (or endtimestring "")
921 "\\(" 929 "\nSUMMARY:"
922 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" 930 summary
923 "\\)?" 931 "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH="
924 "\\s-*\\(.*\\)") 932 (format "%2d" month)
925 entry-main) 933 ";BYMONTHDAY="
926 (icalendar--dmsg "ordinary %s" entry-main) 934 (format "%2d" day)
927 (let* ((datestring (icalendar--datestring-to-isodate 935 )))
928 (substring entry-main (match-beginning 1) 936 (unless (string= entry-rest "")
929 (match-end 1)))) 937 (setq contents (concat contents "\nDESCRIPTION:"
930 (starttimestring (icalendar--diarytime-to-isotime 938 (icalendar--convert-string-for-export
931 (if (match-beginning 3) 939 entry-rest)))))
932 (substring entry-main 940 ;; "ordinary" events, start and end time given
933 (match-beginning 3) 941 ;; 1 Feb 2003 Hs Hochzeitsfeier, Dreieich
934 (match-end 3)) 942 ((string-match
935 nil) 943 (concat nonmarker
936 (if (match-beginning 4) 944 "\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-+"
937 (substring entry-main 945 "\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?"
938 (match-beginning 4) 946 "\\("
939 (match-end 4)) 947 "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
940 nil))) 948 "\\)?"
941 (endtimestring (icalendar--diarytime-to-isotime 949 "\\s-*\\(.*\\)")
942 (if (match-beginning 6) 950 entry-main)
943 (substring entry-main 951 (icalendar--dmsg "ordinary %s" entry-main)
944 (match-beginning 6) 952 (let* ((startdatestring (icalendar--datestring-to-isodate
945 (match-end 6)) 953 (substring entry-main
946 nil) 954 (match-beginning 1)
947 (if (match-beginning 7) 955 (match-end 1))))
948 (substring entry-main 956 (starttimestring (icalendar--diarytime-to-isotime
949 (match-beginning 7) 957 (if (match-beginning 3)
950 (match-end 7)) 958 (substring entry-main
951 nil))) 959 (match-beginning 3)
952 (summary (icalendar--convert-string-for-export 960 (match-end 3))
953 (substring entry-main (match-beginning 8) 961 nil)
954 (match-end 8))))) 962 (if (match-beginning 4)
955 (when starttimestring 963 (substring entry-main
956 (unless endtimestring 964 (match-beginning 4)
957 (let ((time (read (icalendar--rris "^T0?" "" 965 (match-end 4))
958 starttimestring)))) 966 nil)))
959 (setq endtimestring (format "T%06d" (+ 10000 time)))))) 967 (endtimestring (icalendar--diarytime-to-isotime
960 (setq contents (format 968 (if (match-beginning 6)
961 "\nDTSTART%s:%s%s\nDTEND%s:%s%s\nSUMMARY:%s" 969 (substring entry-main
962 (if starttimestring "" ";VALUE=DATE") 970 (match-beginning 6)
963 datestring 971 (match-end 6))
964 (or starttimestring "") 972 nil)
965 (if endtimestring "" 973 (if (match-beginning 7)
966 ";VALUE=DATE") 974 (substring entry-main
967 datestring 975 (match-beginning 7)
968 (or endtimestring "") 976 (match-end 7))
969 summary)) 977 nil)))
970 (unless (string= entry-rest "") 978 (summary (icalendar--convert-string-for-export
971 (setq contents (concat contents "\nDESCRIPTION:" 979 (substring entry-main (match-beginning 8)
972 (icalendar--convert-string-for-export 980 (match-end 8)))))
973 entry-rest)))))) 981 (unless startdatestring
974 ;; everything else 982 (error "Could not parse date"))
975 (t 983 (when starttimestring
976 ;; Oops! what's that? 984 (unless endtimestring
977 (setq oops t))) 985 (let ((time (read (icalendar--rris "^T0?" ""
978 (if oops 986 starttimestring))))
979 (message "Cannot export entry on line %d" 987 (setq endtimestring (format "T%06d" (+ 10000 time))))))
980 (count-lines (point-min) (point))) 988 (setq contents (concat
981 (setq result (concat result header contents "\nEND:VEVENT")))) 989 "\nDTSTART;"
990 (if starttimestring "VALUE=DATE-TIME:"
991 "VALUE=DATE:")
992 startdatestring
993 (or starttimestring "")
994 "\nDTEND;"
995 (if endtimestring "VALUE=DATE-TIME:"
996 "VALUE=DATE:")
997 (icalendar--datestring-to-isodate
998 (substring entry-main
999 (match-beginning 1)
1000 (match-end 1))
1001 (if endtimestring 0 1))
1002 (or endtimestring "")
1003 "\nSUMMARY:"
1004 summary))
1005 ;; could not parse the date
1006 (unless (string= entry-rest "")
1007 (setq contents (concat contents "\nDESCRIPTION:"
1008 (icalendar--convert-string-for-export
1009 entry-rest))))))
1010 ;; everything else
1011 (t
1012 ;; Oops! what's that?
1013 (error "Could not parse entry")))
1014 (setq result (concat result header contents "\nEND:VEVENT")))
1015 ;; handle errors
1016 (error
1017 (setq found-error t)
1018 (save-current-buffer
1019 (set-buffer (get-buffer-create " *icalendar-errors*"))
1020 (insert (format "Error in line %d -- %s: `%s'\n"
1021 (count-lines (point-min) (point))
1022 (cadr error-val)
1023 entry-main))))))
1024
982 ;; we're done, insert everything into the file 1025 ;; we're done, insert everything into the file
983 (let ((coding-system-for-write 'utf8)) 1026 (let ((coding-system-for-write 'utf8))
984 (set-buffer (find-file ical-filename)) 1027 (set-buffer (find-file ical-filename))
985 (goto-char (point-max)) 1028 (goto-char (point-max))
986 (insert "BEGIN:VCALENDAR") 1029 (insert "BEGIN:VCALENDAR")
987 (insert "\nPRODID:-//Emacs//NONSGML icalendar.el//EN") 1030 (insert "\nPRODID:-//Emacs//NONSGML icalendar.el//EN")
988 (insert "\nVERSION:2.0") 1031 (insert "\nVERSION:2.0")
989 (insert result) 1032 (insert result)
990 (insert "\nEND:VCALENDAR\n"))))) 1033 (insert "\nEND:VCALENDAR\n")))
1034 found-error))
991 1035
992;; ====================================================================== 1036;; ======================================================================
993;; Import -- convert icalendar to emacs-diary 1037;; Import -- convert icalendar to emacs-diary
@@ -1001,7 +1045,7 @@ Argument ICAL-FILENAME output iCalendar file.
1001Argument DIARY-FILENAME input `diary-file'. 1045Argument DIARY-FILENAME input `diary-file'.
1002Optional argument NON-MARKING determines whether events are created as 1046Optional argument NON-MARKING determines whether events are created as
1003non-marking or not." 1047non-marking or not."
1004 (interactive "fImport iCalendar data from file: 1048 (interactive "fImport iCalendar data from file:
1005Finto diary file: 1049Finto diary file:
1006p") 1050p")
1007 ;; clean up the diary file 1051 ;; clean up the diary file
@@ -1062,9 +1106,7 @@ reading, parsing, or converting iCalendar data!"
1062 "Current buffer does not contain icalendar contents!")))) 1106 "Current buffer does not contain icalendar contents!"))))
1063 1107
1064(defalias 'icalendar-extract-ical-from-buffer 'icalendar-import-buffer) 1108(defalias 'icalendar-extract-ical-from-buffer 'icalendar-import-buffer)
1065 1109(make-obsolete 'icalendar-extract-ical-from-buffer 'icalendar-import-buffer)
1066(make-obsolete 'icalendar-extract-ical-from-buffer 'icalendar-import-buffer
1067 "icalendar 0.07")
1068 1110
1069;; ====================================================================== 1111;; ======================================================================
1070;; private area 1112;; private area
@@ -1184,7 +1226,7 @@ written into the buffer ` *icalendar-errors*'."
1184 (setq diary-string 1226 (setq diary-string
1185 (format "%s %s%s%s" 1227 (format "%s %s%s%s"
1186 (aref calendar-day-name-array 1228 (aref calendar-day-name-array
1187 weekday) 1229 weekday)
1188 start-t (if end-t "-" "") 1230 start-t (if end-t "-" "")
1189 (or end-t ""))) 1231 (or end-t "")))
1190 ;; FIXME!!!! 1232 ;; FIXME!!!!