#!/usr/bin/perl # Copyright © 2016 Jonas Smedegaard # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # # Description: Create iCalendar file from multiline news chunks # # Depends: libdata-ical-perl libdatetime-timezone-perl libdatetime-format-ical-perl use strict; use warnings; use Data::ICal; use Data::ICal::Entry::Event; use DateTime::TimeZone; use DateTime::Format::ICal; my $data; my $calendar = Data::ICal->new( rfc_strict => 1, auto_uid => 1 ); my $tz = DateTime::TimeZone->new( name => 'local' ); # warn about resolved timezone printf STDERR "using timezone %s - set environment variable TZ to override\n", $tz->name; # slurp input my @lines; while (<>) { chomp; $data .= "$_\n"; } # parse data and serialize as iCalendar events # * Events are newline-newline delimited # * First line contains date, location, time(s) # * String before date (e.g. weekday) is ignored # * Date is formatted as DD.MM.YYYY # * Times are formatted as either HH or HH:MM # * Times are space-hyphen-space delimited # * End time (and delimiter) is optional # * string after date (e.g. hour keyword) is ignored # * Second line is summary # * Third and subsequent lines are description while ( $data =~ m{ (\d{1,2})[./](\d{1,2})[./](\d{4}),\h* # date ([^\n]+?),?\h* # location (\d{1,2})(?::(\d{2}))? # start time (?:\h+-\h+(\d{1,2})(?::(\d{2}))?)? # end time (?:\h+Uhr)?\h*\n ([^\n]+)\h*\n # description ([^\n]+(?:\n[^\n]+)*)\h*\n(?:\n|\z) # description }gx ) { my ( $dtstart, $dtend ); $dtstart = DateTime->new( year => $3, month => $2, day => $1, hour => $5, minute => $6 || '00', time_zone => $tz, ); # Data::ICal does not support named timezones $dtstart->set_time_zone( $dtstart->offset() ); if ( defined($7) ) { $dtend = DateTime->new( year => $3, month => $2, day => $1, hour => $7, minute => $8 || '00', time_zone => $tz, ); # Data::ICal does not support named timezones $dtend->set_time_zone( $dtend->offset() ); } my $location = $4; my $summary = $9; my $description = $10; my $vevent = Data::ICal::Entry::Event->new(); $vevent->add_properties( dtstart => DateTime::Format::ICal->format_datetime($dtstart), location => $location, summary => $summary, description => $description, ); $vevent->add_property( dtend => DateTime::Format::ICal->format_datetime($dtend) ) if ($dtend); $calendar->add_entry($vevent); } print $calendar->as_string;