#!/usr/bin/perl -w

use Time::Local;
use File::Copy;
use strict 'vars';

# Define how old events must be before they are considered stale
my $MONTH = 2592000;

# Todays date for comparison and archive filename
my $now = time();
my($day,$month,$year) = (localtime($now))[3..5];
if ($day < 10) { $day = "0$day"; }
if (++$month < 10) { $month = "0$month"; }
$year += 1900;

# Open directory and process each .ics file
opendir(DIR, '.') or die "can't open directory: $!";
while (defined(my $file = readdir(DIR))) {
	# Skip old archived calendars
	next if $file =~ /^\d{4}(-\d{2}){2}_.+\.ics$/;

	my $buffer = '';
	my @lines = ();
	my $line = '';

	# Archive existing calendar
	copy($file, "$year-$month-$day" . "_$file");

	# Read calendar into buffer
	open(CALENDAR, "< $file") or die "Couldn't open file: $!\n";
	while(defined($line = <CALENDAR>)) {
		$buffer .= $line;
	}

	close(CALENDAR);

	# Put calendar into array and trim each line
	@lines = split(/\n(?!\s)/, $buffer);
	@lines = map { s/^\s+//g; $_ } @lines;
	@lines = map { s/\s+$//g; $_ } @lines;

	# Reset buffer variable
	$buffer = '';

	# Process the array
	for (my $i=0,my $r=$#lines+1; $i<$r; $i++) {
		$line = $lines[$i];

		# Look for the start of events
		if ($line !~ m/BEGIN:VEVENT/) {
			# Write to buffer
			$buffer .= "$line\n";
		} else {
			my $skip = 0;
			my $stale = FALSE;
			my $event = '';

			# Gather event details
			while(defined($line = $lines[++$i]) && ($line !~ /END:VEVENT/)) {
				my($key,$val) = split(':', $line);

				# Trim whitespace from start of value
				$val =~ s/^\s+//g;

				# Look for the start date and check if older than a month
				if (($key =~ /^DTSTART/) && defined($val)) {
					if ($val =~ /^\d+$/) {
						# DTSTART;VALUE=DATE:20050324
						$val = timelocal(0, 0, 0, substr($val, 6, 2), substr($val, 4, 2)-1, substr($val, 0, 4)-1900);
					} else {
						# DTSTART:20050513T083000Z
						$val = timelocal(substr($val, 13, 2), substr($val, 11, 2), substr($val, 9, 2), substr($val, 6, 2), substr($val, 4, 2)-1, substr($val, 0, 4)-1900);
					}

					$stale = TRUE if (($now - $val) > $MONTH);
				}

				$event .= "$line\n";

				# Check for repeating events without end dates
				#	TODO: check UNTIL and/or COUNT end date have expired
				if ($line =~ /RRULE/) {
					$skip = (($line =~ /COUNT/) || ($line =~ /UNTIL/)) ? 1:2;
				}
			}

			# Skip old events and write cromulent ones to the buffer
			next if (($stale eq TRUE) && ($skip < 2));
			$buffer .= "BEGIN:VEVENT\n" . $event . "END:VEVENT\n";
		}
	}

	# Write the buffer to the original filename
	open(CALENDAR, "> $file") or die "Couldn't open file: $!\n";
	print CALENDAR $buffer;
	close(CALENDAR);
}

# Close directory and quit
closedir(DIR);
exit;

Creative Commons License
This work is licenced under a Creative Commons Licence.