make_meeting
#!/usr/bin/perl
#===============================================================================
#
# FILE: make_meeting
#
# USAGE: ./make_meeting
#
# DESCRIPTION: Makes a recurrent iCalendar meeting to be loaded into
# a calendar. This is apparently necessary when the 'RRULE'
# recurrence description is not adequate.
#
# OPTIONS: None
# REQUIREMENTS: Needs modules Data::ICal and Date::Calc
# BUGS: ---
# NOTES: Distributed with the HPR episode "iCalendar Hacking"
# AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
# LICENCE: Copyright (c) year 2012, Dave Morriss
# VERSION: 1.0
# CREATED: 13/10/2012 15:34:01
# REVISION: 16/11/2012 16:04:37
#
#===============================================================================
# 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 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
use 5.010;
use strict;
use warnings;
use Data::ICal;
use Data::ICal::Entry::Event;
use Date::Calc qw{
Today Day_of_Year Add_Delta_YMD Nth_Weekday_of_Month_Year
};
#
# Date and time values
#
my @today = Today();
my @startdate;
my @rdate;
my $monday = 1; # Day of week number 1-7, Monday-Sunday
my @starttime = ( 19, 00, 00 );
my @endtime = ( 21, 00, 00 );
#
# Format of an ISO UTC datetime
#
my $fmt = "%02d%02d%02dT%02d%02d%02dZ";
#
# Constants for the event
#
my $calname = 'Hacker Public Radio';
my $timezone = 'Europe/London';
my $location = 'mumble.openspeak.cc port: 64747';
my $summary = 'HPR Community News';
my $description = <<ENDDESC;
This is a test, building an iCalendar file and loading it into Thunderbird.
-----------------------------------------
Mumble settings
Server Name: Anything you like
Server Address: mumble.openspeak.cc
Port: 64747
Name: Your name or alias is fine
Don't have mumble, setup instructions can be found on our wiki -
http://linuxbasix.com/tiki-index.php?page=Linux+Basix+Mumble
ENDDESC
#
# Compute the next meeting date from now
#
@startdate = make_date( \@today, $monday, 1, -2 );
#
# Create the calendar object
#
my $calendar = Data::ICal->new();
#
# Some calendar properties
#
$calendar->add_properties(
'X-WR-CALNAME' => $calname,
'X-WR-TIMEZONE' => $timezone,
);
#
# Create the event object
#
my $vevent = Data::ICal::Entry::Event->new();
#
# Add some event properties
#
$vevent->add_properties(
summary => $summary,
location => $location,
description => $description,
dtstart => sprintf( $fmt, @startdate, @starttime ),
dtend => sprintf( $fmt, @startdate, @endtime ),
);
#
# Add 12 recurring dates. (Note that this generates 12 RDATE entries rather
# than 1 entry with multiple dates; this is because this module doesn't seem
# to have the ability to generated the concatenated entry. The two modes of
# expressing the repeated dates seem to be equivalent.)
#
for my $i ( 1 .. 12 ) {
@today = Add_Delta_YMD( @today, 0, 1, 0 );
@rdate = make_date( \@today, $monday, 1, -2 );
$vevent->add_property( rdate =>
[ sprintf( $fmt, @rdate, @starttime ), { value => 'DATE-TIME' } ],
);
}
#
# Add the event into the calendar
#
$calendar->add_entry($vevent);
#
# Print the result
#
print $calendar->as_string;
exit;
#=== FUNCTION ================================================================
# NAME: make_date
# PURPOSE: Make the event date for recurrence
# PARAMETERS: $refdate
# An arrayref to the reference date array (usually
# today's date)
# $dow Day of week for the event date (1-7, 1=Monday)
# $n The nth day of the week in the given month required
# for the event date
# $offset Number of days to offset the computed date
# RETURNS: The resulting date as a list for Date::Calc
# DESCRIPTION: We want to compute a simple date with an offset, such as
# "the Saturday before the first Monday of the month". We do
# this my computing a pre-offset date (first Monday of month)
# then apply the offset (Saturday before).
# THROWS: No exceptions
# COMMENTS: TODO Needs more testing to be considered truly universal
# SEE ALSO:
#===============================================================================
sub make_date {
my ( $refdate, $dow, $n, $offset ) = @_;
#
# Compute the required date: the nth day of week in this year and month
#
my @date = Nth_Weekday_of_Month_Year( @$refdate[ 0, 1 ], $dow, $n );
#
# If the computed date is before the base date advance a month
#
if ( Day_of_Year(@date) <= Day_of_Year(@$refdate) ) {
#
# Add a month and recompute
#
@date = Add_Delta_YMD( @date, 0, 1, 0 );
@date = Nth_Weekday_of_Month_Year( @date[ 0, 1 ], $dow, $n );
}
#
# Apply the day offset
#
@date = Add_Delta_YMD( @date, 0, 0, $offset );
#
# Return a list
#
return (@date);
}
# vim: syntax=perl:ts=8:sw=4:et:ai:tw=78:fo=tcrqn21:fdm=marker