summaryrefslogtreecommitdiff
path: root/localtxt2ics
blob: 284775ab53a8e48d5b73189dd5f11cc345165746 (plain)
  1. #!/usr/bin/perl
  2. # Copyright © 2016 Jonas Smedegaard <dr@jones.dk>
  3. #
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 3, or (at your option)
  7. # any later version.
  8. #
  9. # Description: Create iCalendar file from multiline news chunks
  10. #
  11. # Depends: libdata-ical-perl libdatetime-timezone-perl libdatetime-format-ical-perl
  12. use strict;
  13. use warnings;
  14. use Data::ICal;
  15. use Data::ICal::Entry::Event;
  16. use DateTime::TimeZone;
  17. use DateTime::Format::ICal;
  18. my $data;
  19. my $calendar = Data::ICal->new( rfc_strict => 1, auto_uid => 1 );
  20. my $tz = DateTime::TimeZone->new( name => 'local' );
  21. # warn about resolved timezone
  22. printf STDERR "using timezone %s - set environment variable TZ to override\n",
  23. $tz->name;
  24. # slurp input
  25. my @lines;
  26. while (<>) {
  27. chomp;
  28. $data .= "$_\n";
  29. }
  30. # parse data and serialize as iCalendar events
  31. # * Events are newline-newline delimited
  32. # * First line contains date, location, time(s)
  33. # * String before date (e.g. weekday) is ignored
  34. # * Date is formatted as DD.MM.YYYY
  35. # * Times are formatted as either HH or HH:MM
  36. # * Times are space-hyphen-space delimited
  37. # * End time (and delimiter) is optional
  38. # * string after date (e.g. hour keyword) is ignored
  39. # * Second line is summary
  40. # * Third and subsequent lines are description
  41. while (
  42. $data =~ m{
  43. (\d{1,2})[./](\d{1,2})[./](\d{4}),\h* # date
  44. ([^\n]+?),?\h* # location
  45. (\d{1,2})(?::(\d{2}))? # start time
  46. (?:\h+-\h+(\d{1,2})(?::(\d{2}))?)? # end time
  47. (?:\h+Uhr)?\h*\n
  48. ([^\n]+)\h*\n # description
  49. ([^\n]+(?:\n[^\n]+)*)\h*\n(?:\n|\z) # description
  50. }gx
  51. ) {
  52. my ( $dtstart, $dtend );
  53. $dtstart = DateTime->new(
  54. year => $3,
  55. month => $2,
  56. day => $1,
  57. hour => $5,
  58. minute => $6 || '00',
  59. time_zone => $tz,
  60. );
  61. # Data::ICal does not support named timezones
  62. $dtstart->set_time_zone( $dtstart->offset() );
  63. if ( defined($7) ) {
  64. $dtend = DateTime->new(
  65. year => $3,
  66. month => $2,
  67. day => $1,
  68. hour => $7,
  69. minute => $8 || '00',
  70. time_zone => $tz,
  71. );
  72. # Data::ICal does not support named timezones
  73. $dtend->set_time_zone( $dtend->offset() );
  74. }
  75. my $location = $4;
  76. my $summary = $9;
  77. my $description = $10;
  78. my $vevent = Data::ICal::Entry::Event->new();
  79. $vevent->add_properties(
  80. dtstart => DateTime::Format::ICal->format_datetime($dtstart),
  81. location => $location,
  82. summary => $summary,
  83. description => $description,
  84. );
  85. $vevent->add_property(
  86. dtend => DateTime::Format::ICal->format_datetime($dtend) )
  87. if ($dtend);
  88. $calendar->add_entry($vevent);
  89. }
  90. print $calendar->as_string;