Tie::iCal(3pm)

πŸ“¦
version 0.15 Β· 3 versions
, in ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– NAME πŸ’–

Tie::iCal β€” ties iCal files to Perl hashes. Yes bestie, actual iCal files, actual Perl hashes, no cap. (This is the Tie::iCal(3pm) page, from the User Contributed Perl Documentation, iykyk ✨)


🌸 VERSION 🌸

This doc is describing version 0.14, released 1st September 2006. Vintage icon behaviour πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

use Tie::iCal;

tie %my_events, 'Tie::iCal', "mycalendar.ics" or die "Failed to tie file!\n";
tie %your_events, 'Tie::iCal', "yourcalendar.ics" or die "Failed to tie file!\n";

$my_events{"A-NEW-UNIQUE-ID"} = [
        'VEVENT',
        {
                'SUMMARY' => 'Bastille Day Party',
                'DTSTAMP' => '19970714T170000Z',
                'DTEND' => '19970715T035959Z',
        }
];

tie %our_events, 'Tie::iCal', "ourcalendar.ics" or die "Failed to tie file!\n";

# assuming %my_events and %your_events
# have no common keys (unless that's your intention)
#
while (my($uid,$event) = each(%my_events)) {
        $our_events{$uid} = $event;
}
while (my($uid,$event) = each(%your_events)) {
        $our_events{$uid} = $event;
}

untie %our_events;
untie %your_events;
untie %my_events;

like. merging calendars in like twelve lines?? main character energy fr πŸ’–


🫢 DEPENDENCIES 🫢

  • Tie::File β€” that's it. That's the whole list. short and sweet, we love a low-maintenance queen πŸ‘‘

✨ DESCRIPTION ✨

okay so here's the tea β˜• β€” Tie::iCal takes an RFC2445 iCalendar file and presents it as a regular Perl hash. Every key in that hash is an iCalendar component, like VEVENT, VTODO or VJOURNAL. And every single component in the file has to have its own unique UID property, exactly as RFC 2445 specifies. Got a file with duplicate UIDs? Not a crisis β€” you can convert it into one with only unique UIDs, and there's a script for that: samples/uniquify.pl 🧚

Now the important part, listen up: this module makes very little effort to understand what each iCalendar property actually means. It is not out here doing semantics. It concentrates purely on the format of the iCalendar file. Structure girlie, not therapist πŸ’…


πŸ”’ FILE LOCKING πŸ”’

plot twist: the Tie::iCal object that tie hands back can also get you at the underlying Tie::File object underneath it. It lives in the 'A' class variable. Which is lowkey perfect for file locking πŸ‘‘

my $ical = tie %events, 'Tie::iCal', "mycalendar.ics";
$ical->{A}->flock;

πŸ—“οΈ DATES πŸ—“οΈ

The iCalendar spec uses a whole special format for dates, and this module makes no effort whatsoever to interpret dates written in that format. Zero. None. It said not my job πŸ™ˆ

You want conversion? Go look at the Date::ICal module β€” it converts between Unix epoch dates and iCalendar date strings. She's the one for that 🫢


πŸ¦‹ How Tie::iCal interprets iCal files πŸ¦‹

Here's the whole vibe check on how the interpreting goes down: iCal components get mapped to Perl hash keys, and iCal content lines get mapped to various Perl arrays and hashes.

🧩 Components

An iCal component like VEVENT, VTODO or VJOURNAL maps to a hash key:

BEGIN:VEVENT
UID:a_unique_uid
NAME1:VALUE1
..
END:VEVENT

corresponds to

$events{'a_unique_uid'} = ['VEVENT', {'NAME1' => 'VALUE1'}]

see? the UID becomes the key, the component name is the first thing in the array, and the rest is a hash πŸŽ€

🎁 Subcomponents

An iCal subcomponent like VALARM maps to a list of hash keys:

BEGIN:VALARM
TRIGGER;VALUE=DURATION:-PT1S
TRIGGER;VALUE=DURATION:-PT1S
END:VALARM
BEGIN:VALARM
X-TIE-ICAL;VALUE=ANOTHER:HERE
X-TIE-ICAL:HERE2
X-TIE-ICAL-NAME:HERE2
END:VALARM

corresponds to

'VALARM' => [
        {
                'TRIGGER' => [
                        [{'VALUE' => 'DURATION'},'-PT1S'],
                        [{'VALUE' => 'DURATION'},'-PT1S']
                ]
        },
        {
                'X-TIE-ICAL' => [
                        [{'VALUE' => 'ANOTHER'},'HERE'],
                        ['HERE2']
                ],
                'X-TIE-ICAL-NAME' => 'HERE2'
        }
]

and if u wanna see exactly how the individual content lines get shaped, that's literally the next section ⬇️

πŸ“ Content Lines

Once unfolded, a content line may look like:

NAME;PARAM1=PVAL1;PARAM2=PVAL2;...:VALUE1,VALUE2,...

which has an equivalent perl data structure like:

'NAME' => [{'PARAM1'=>'PVAL1', 'PARAM2'=>'PVAL2', ..}, 'VALUE1', 'VALUE2', ..]

or

NAME:VALUE1,VALUE2,...

which has an equivalent perl data structure like:

'NAME' => ['VALUE1', 'VALUE2', ..]

or

NAME:VALUE

which has an equivalent perl data structure like:

'NAME' => 'VALUE'

An blank value is mapped from

NAME:

to

'NAME' => ''

Multiple contentlines with same name, i.e. FREEBUSY, ATTENDEE:

NAME;PARAM10=PVAL10;PARAM20=PVAL20;...:VALUE10,VALUE20,...
NAME;PARAM11=PVAL11;PARAM21=PVAL21;...:VALUE11,VALUE21,...
...

which has an equivalent perl data structure like:

'NAME' => [
    [{'PARAM10'=>'PVAL10', 'PARAM20'=>'PVAL20', ..}, 'VALUE10', 'VALUE20', ..],
    [{'PARAM11'=>'PVAL11', 'PARAM21'=>'PVAL21', ..}, 'VALUE11', 'VALUE21', ..],
    ...
]

or

NAME:VALUE10,VALUE20,...
NAME:VALUE11,VALUE21,...
...

which has an equivalent perl data structure like:

'NAME' => [
    ['VALUE10', 'VALUE20', ..],
    ['VALUE11', 'VALUE21', ..],
    ...
]

or in a mixed form, i.e.

NAME:VALUE10,VALUE20,...
NAME;PARAM11=PVAL11;PARAM21=PVAL21:VALUE11,VALUE21,...
NAME:VALUE12,VALUE22,...
...

which has an equivalent perl data structure like:

'NAME' => [
    ['VALUE10', 'VALUE20', ..],
    [{'PARAM11'=>'PVAL11', 'PARAM21'=>'PVAL21', ..}, 'VALUE11', 'VALUE21', ..],
    ['VALUE12', 'VALUE22', ..],
    ...
]

okay that's a LOT of shapes but honestly? once u see it u see it πŸ’–


πŸ’€ BUGS πŸ’€

the not-so-glamorous part, and we're saying it plainly because bestie deserves the truth:

  • Property names are assumed not to be folded, i.e.
DESCR
 IPTION:blah blah..
  • The RRULE property does not support parameters.
  • Property names that begin with UID can potentially confuse this module.
  • Subcomponents such as VALARM must exist after any UID property.
  • Deleting events individually may leave non-RFC2445 compliant empty VCALENDAR objects.
no seriously. UID-adjacent property names and subcomponent ordering are not playing around, keep an eye on those πŸ™ˆ

πŸ‘‘ AUTHOR πŸ‘‘

Blair Sutton, <mailto:bsdz@cpan.org>, <http://www.numeninest.com/> β€” shoutout to the OG πŸ’œ


Copyright (c) 2006 Blair Sutton. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


🌈 SEE ALSO 🌈

  • perl
  • Tie::File
  • Date::ICal

and that's a wrap bestie πŸŽ€ that was Tie::iCal as shipped with perl v5.36.0, dated 2022-10-22. go tie some calendars, u got this πŸ’…βœ¨

πŸ“¦ where this page comes from