Merge pull request #2189 from webmin/dev/icalendar-event-parser

Add support to parse calendar events files #2160
This commit is contained in:
Jamie Cameron
2024-06-03 16:05:49 -07:00
committed by GitHub

View File

@@ -1286,5 +1286,81 @@ if (!glob("\Q$rv\E.*")) {
return $rv;
}
# parse_calendar_file(calendar-file)
# Parses an iCalendar file and returns a list of events
sub parse_calendar_file
{
my ($calendar_file) = @_;
my (@events, %event);
eval "use DateTime; use DateTime::TimeZone;";
return \@events if ($@);
my $adjust_time_with_timezone = sub {
my ($time, $tzid) = @_;
my $dt = DateTime->new(
year => substr($time, 0, 4),
month => substr($time, 4, 2),
day => substr($time, 6, 2),
hour => substr($time, 9, 2),
minute => substr($time, 11, 2),
second => substr($time, 13, 2),
time_zone => $tzid);
my $local_dt = $dt->clone->set_time_zone('local');
return {
formatted => $local_dt->strftime('%Y-%m-%d %H:%M:%S'),
timestamp => $local_dt->epoch
};
};
my $ics_file_lines = &read_file_lines($calendar_file, 1);
foreach (@$ics_file_lines) {
if (/^BEGIN:VEVENT/) {
# Start a new event
%event = ();
}
elsif (/^END:VEVENT/) {
# Convert times using the timezone
if ($event{'dtstart'} && $event{'tzid'}) {
my $adjusted_start = $adjust_time_with_timezone->($event{'dtstart'}, $event{'tzid'});
$event{'dtstart_local_timestamp'} = $adjusted_start->{'timestamp'};
$event{'dtstart_local_date'} = &make_date($event{'dtstart_local_timestamp'});
}
if ($event{'dtend'} && $event{'tzid'}) {
my $adjusted_end = $adjust_time_with_timezone->($event{'dtend'}, $event{'tzid'});
$event{'dtend_local_timestamp'} = $adjusted_end->{'timestamp'};
$event{'dtend_local_date'} = &make_date($event{'dtend_local_timestamp'});
}
# Local timezone
$event{'tzid_local'} = DateTime::TimeZone->new(name => 'local')->name;
# Add the event to the list
push(@events, { %event });
}
# Parse fields
elsif (/^SUMMARY:(.*)$/) {
$event{'summary'} = $1;
}
elsif (/^DTSTART;TZID=(.*?):(.*)$/) {
$event{'tzid'} = $1;
$event{'dtstart'} = $2;
}
elsif (/^DTEND;TZID=(.*?):(.*)$/) {
$event{'tzid'} = $1;
$event{'dtend'} = $2;
}
elsif (/^DESCRIPTION:(.*)$/) {
$event{'description'} = $1;
}
elsif (/^LOCATION:(.*)$/) {
$event{'location'} = $1;
}
elsif (/^ATTENDEE.*:(.*)$/) {
push @{$event{'attendees'}}, $1;
}
elsif (/^ORGANIZER;CN=(.*?):mailto:(.*)$/) {
$event{'organizer_name'} = $1;
$event{'organizer_email'} = $2;
}
}
return \@events;
}
1;