]> pere.pagekite.me Git - homepage.git/blob - linux/plan2icalendar
Generated.
[homepage.git] / linux / plan2icalendar
1 #!/usr/bin/perl -w
2 #
3 # Author: Petter Reinholdtsen <pere@hungry.com>
4 # Date: 2002-01-10
5 #
6 # Convert plan calender data to/from icalender format.
7 #
8 # plan, <URL:http://www.bitrot.de/>
9 # icalendar, RFC 2445, <URL:http://www.faqs.org/rfcs/rfc2445.html">iCalendar>
10 #
11 # Depend on debian package libdate-ical-perl
12
13 use warnings;
14 use strict;
15
16 use Getopt::Std;
17 use Date::Parse;
18 use Date::Format;
19 use Date::ICal;
20
21 my @events;
22 my %opts;
23 unless (getopts('dif:o:', \%opts)) {
24 usage();
25 exit 1;
26 }
27
28 my $debug = $opts{d} || 0;
29 my $input = $opts{f};
30 my $output = $opts{o};
31
32 if ($opts{i}) { # Import
33 read_icalendar($input || "test.ical");
34 write_planfile($output || $ENV{HOME}."/.plan.dir/fromical");
35 } else { # Default is to export
36 read_planfile($input || $ENV{HOME}."/.plan.dir/dayplan");
37 write_icalendar($output || "-");
38 }
39 exit 0;
40
41 sub usage {
42 print <<EOF
43 Usage: $0 [-i] [-f infile] [-o outfile]
44
45 Imports or exports between plan and iCalendar.
46
47 -i import ical file
48 -f infile read input from 'infile'
49 -o outfile read output from 'outfile'
50 -d enable debug output
51 EOF
52 }
53 sub read_planfile {
54 my ($planfile) = @_;
55 open(PLAN, "<$planfile") || die "Unable to read $planfile";
56 my $planver = <PLAN>;
57 chomp $planver;
58 while (<PLAN>) {
59 chomp;
60 if (m%\d+/\d+/\d+\s%) {
61 my ($date, $start, $duration) = split(/\s+/);
62 my $info = <PLAN>;
63 chomp $info;
64 my ($dontknow, $msg) = $info =~ m/^(.)\t(.+)$/;
65 print STDERR "E: $date $start $duration $msg\n" if $debug;
66
67 my $timestamp = str2time("$date $start");
68 my $isostartstamp = time2str("%Y%m%dT%H%M%S", $timestamp);
69 my $icalstartstamp = Date::ICal->new( epoch => $timestamp );
70
71 my @f = split(/:/, $duration);
72 $timestamp += ($f[0]*60*60 + $f[1]*60 +$f[2]);
73 my $isoendstamp = time2str("%Y%m%dT%H%M%S", $timestamp);
74 my $icalendstamp = Date::ICal->new( epoch => $timestamp );
75
76 print STDERR "IE: $isostartstamp $isoendstamp\n" if $debug;
77 push(@events, {
78 summary => $msg,
79 dtstart => $icalstartstamp->ical,
80 dtend => $icalendstamp->ical,
81 });
82 }
83 }
84 close(PLAN);
85 }
86
87
88 # BEGIN:VCALENDAR
89 # PRODID
90 # :-//test environment//NONSGML plan2icalendar//EN
91 # VERSION
92 # :2.0
93 # BEGIN:VEVENT
94 # CREATED
95 # :20020110T153939
96 # UID
97 # :KOrganizer-141229514.660
98 # SEQUENCE
99 # :0
100 # LAST-MODIFIED
101 # :20020110T153939
102 # DTSTAMP
103 # :20020110T153952
104 # SUMMARY
105 # :SL-veiledning
106 # DTSTART
107 # :20020114T151500
108 # DTEND
109 # :20020114T160000
110 # END:VEVENT
111 # END:VCALENDAR
112 sub write_icalendar {
113 my $filename = shift;
114 open(PLAN, ">$filename") || die "Unable to write to $filename";
115 print PLAN <<EOF;
116 BEGIN:VCALENDAR
117 CALSCALE:GREGORIAN
118 PRODID:-//test environment//NONSGML plan2icalender//EN
119 VERSION:2.0
120 EOF
121 my $count = 0;
122 for my $event (@events) {
123 $event->{uid} = "plan2icalendar-$count" unless $event->{uid};
124 $event->{dtstamp} = "20020110T153952" unless $event->{dtstamp};
125 $event->{'last-modified'} = "20020110T153939" unless $event->{'last-modified'};
126 $event->{sequence} = $count unless $event->{sequence};
127 $event->{created} = "20020110T153939" unless $event->{created};
128 print PLAN <<EOF;
129 BEGIN:VEVENT
130 CREATED:$event->{created}
131 UID:$event->{uid}
132 SEQUENCE:$count
133 LAST-MODIFIED:$event->{'last-modified'}
134 DTSTAMP:$event->{dtstamp}
135 SUMMARY:$event->{summary}
136 DTSTART:$event->{dtstart}
137 DTEND:$event->{dtend}
138 END:VEVENT
139
140 EOF
141 $count++;
142 }
143 print PLAN "END:VCALENDAR\n";
144 close PLAN;
145 }
146
147 #
148 # Should probably leave this task to Net::ICal. But it is not
149 # available in debian/sarge, so I make a quick-n-dirty solution
150 # instead.
151 #
152 sub read_icalendar {
153 my $filename = shift;
154 open (ICALENDAR, "<$filename") or die "Unable to read from $filename";
155 my $oldval = $/;
156 $/ = "\r\n";
157 print STDERR "Loading $filename\n" if $debug;
158 while (<ICALENDAR>) {
159 chomp;
160 if (m/^BEGIN:VEVENT/) {
161 my %event;
162 while (<ICALENDAR>) {
163 chomp;
164 last if (m/END:VEVENT/);
165 $event{description} = $1 if (m/^DESCRIPTION\s*:\s*(.+)$/);
166 $event{created} = $1 if (m/^CREATED\s*:\s*(.+)$/);
167 $event{dtend} = $1 if (m/^DTEND\s*:\s*(.+)$/);
168 $event{dtstamp} = $1 if (m/^DTSTAMP\s*:\s*(.+)$/);
169 $event{dtstart} = $1 if (m/^DTSTART\s*:\s*(.+)$/);
170 $event{last-modified} = $1 if (m/^LAST-MODIFIED\s*:\s*(.+)$/);
171 $event{sequence} = $1 if (m/^SEQUENCE\s*:\s*(.+)$/);
172 $event{summary} = $1 if (m/^SUMMARY\s*:\s*(.+)$/);
173 $event{uid} = $1 if (m/^UID\s*:\s*(.+)$/);
174 }
175 push @events, \%event;
176 print STDERR "Event pushed\n" if $debug;
177 }
178 }
179 close (ICALENDAR);
180 $/ = $oldval;
181 }
182
183 # Simple version covering the chars I need.
184 sub utf8tolocalmap {
185 my $string = shift;
186 $string =~ s/ø/ø/g;
187 $string =~ s/æ/æ/g;
188 $string =~ s/Ã¥/å/g;
189 $string =~ s/Ã\85/Å/g;
190 $string =~ s/«/«/g;
191 $string =~ s/»/»/g;
192 return $string;
193 }
194
195 sub write_planfile {
196 my $filename = shift;
197 open(PLAN, ">$filename") or die "Unable to write to $filename";
198 for my $event (@events) {
199 # offset = 0 -- assume all timestamps in local time zone
200 my $ical = Date::ICal->new( ical => $event->{dtstart}, offset => 0 );
201 my $date = join("/", $ical->month, $ical->day, $ical->year);
202 my $start = join(":", $ical->hour, $ical->min, $ical->sec);
203
204 my $icalstop = Date::ICal->new( ical => $event->{dtend}, offset => 0 );
205 my $icalduration = $icalstop - $ical;
206 my $duration = join(":",
207 $icalduration->hours || "0",
208 $icalduration->minutes || "0",
209 $icalduration->seconds || "0");
210
211 my $code = "N";
212 my $summary = utf8tolocalmap($event->{summary});
213 print PLAN "$date $start $duration 0:0:0 0:0:0 ---------- 0 0\n";
214 print PLAN "$code\t$summary\n";
215 }
216 }