- #!/usr/bin/perl
- # Copyright © 2016 Jonas Smedegaard <dr@jones.dk>
- #
- # 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;
|