Data-ICal-DateTime-0.82/0000755000175000017500000000000013146616577014156 5ustar flavioflavioData-ICal-DateTime-0.82/t/0000755000175000017500000000000013146616577014421 5ustar flavioflavioData-ICal-DateTime-0.82/t/01.parse.t0000644000175000017500000000417713145634223016133 0ustar flavioflaviouse strict; use Test::More tests => 27; use Data::ICal::DateTime; use DateTime; use DateTime::Set; use DateTime::TimeZone; # check the import stuff ok(Data::ICal->can('events'),"Events"); for (qw(start end duration summary description url recurrence explode is_in _normalise)) { ok(Data::ICal::Entry::Event->can($_),"Can $_"); } my $cal; ok($cal = Data::ICal->new( filename => 't/ics/test.ics'), "parse test ics"); my $date1 = DateTime->new( year => 2005, month => 6, day => 27 ); my $date2 = DateTime->new( year => 2005, month => 10, day => 27 ); my $set = DateTime::Span->from_datetimes( start => $date1, end => $date2 ); # $set->set_time_zone('Europe/London'); my @events; @events = $cal->events; is (@events, 128, "128 total events"); my ($orig_norm, $orig_recur); for (@events) { if ( $_->summary eq 'Potential Alternative London.pm social meet' ) { $orig_norm = $_; } elsif ( $_->summary eq 'London.pm tech meet') { $orig_recur = $_; } } @events = grep { $_->is_in($set) } @events; is(@events, 10, "10 eligible events"); @events = $cal->events($set); is(@events, 15, "15 events if you explode just recurring events"); my ($munged_norm, $munged_recur); for (@events) { if ( $_->summary eq 'Potential Alternative London.pm social meet' ) { $munged_norm = $_; } elsif ( $_->summary eq 'London.pm tech meet') { $munged_recur = $_; } } @events = $cal->events($set,'day'); is(@events, 36, "36 events if you explode multi day events to multiple single day events"); ok($orig_norm, "Found normal event"); ok($orig_recur, "Found recurring event"); ok($munged_norm, "Found munged normal event"); ok($munged_recur, "Found munged recurring event"); ok($orig_norm->duration,"Got a duration in the normal one"); ok(!$orig_norm->end,"Not got an end in the normal one"); ok(!$munged_norm->duration,"Not got a duration in the munged one"); ok($munged_norm->end,"Got an end in the munged one"); ok($orig_recur->recurrence,"Got a recurrence in the normal one"); ok(!$munged_recur->recurrence,"Not got a recurrence in the munged one"); ok($munged_recur->end,"Got an end in the munged one"); Data-ICal-DateTime-0.82/t/complex-dtstart.t0000644000175000017500000000075013145634223017725 0ustar flavioflaviouse strict; use Test::More tests => 2; use DateTime; use Data::ICal; use Data::ICal::DateTime; my $d = Data::ICal->new( filename => 't/ics/test.ics' ); my $st = DateTime->new( year => 2014, month => 1, day => 2, hour => 12, minute => 34, second => 56, time_zone => 'America/Chicago', ); my ($e) = $d->events; $e->start($st); my $dtstart = $e->property('dtstart')->[0]; is($dtstart->value, '20140102T123456'); is($dtstart->parameters->{TZID}, 'America/Chicago'); Data-ICal-DateTime-0.82/t/05.palm_floating.t0000644000175000017500000000244513145634223017635 0ustar flavioflaviouse strict; use Test::More tests => 13; use Data::ICal::DateTime; use Data::ICal::Entry::Event; use DateTime; use DateTime::Set; use DateTime::TimeZone; my $cal; ok($cal = Data::ICal->new( filename => 't/ics/palm.ics'), "parse palm ics"); my $date1 = DateTime->new( year => 2005, month => 10, day => 3 ); my $date2 = $date1->clone->add( days => 1 )->subtract( nanoseconds => 1 ); my $span = DateTime::Span->from_datetimes( start => $date1->clone->subtract(days => 2), end => $date1->clone->add(days => 2) ); my @events = $cal->events($span); use Data::Dumper; is(scalar(@events),1,"1 event"); my $ev = shift @events; my $s = $ev->start; my $e = $ev->end; is("$s", "$date1", "Start is the same as date1"); is ($e, undef, "End if undef"); is($ev->floating, 1, "Event is floating"); is($ev->floating(0), 0, "Set floating to 0"); $s = $ev->start; $e = $ev->end; is("$s", "$date1", "Start is still the same as date1"); is("$e", "$date2", "End is now the same as date2"); is($ev->floating, 0, "Event isn't floating"); is($ev->floating(1), 1, "Set floating to 1"); $s = $ev->start; $e = $ev->end; is("$s", "$date1", "Start is still the same as date1. Again."); is ($e, undef, "End if undef. Again."); is($ev->floating, 1, "Event is floating. Again."); Data-ICal-DateTime-0.82/t/01.parse_recurring.t0000644000175000017500000000156613145634223020212 0ustar flavioflaviouse strict; use Test::More tests => 18; use Data::ICal::DateTime; use DateTime; use DateTime::Set; use DateTime::TimeZone; my $cal; ok($cal = Data::ICal->new( filename => 't/ics/recur.ics'), "parse recur ics") or diag( $cal->error_message ); my $date1 = DateTime->new( year => 2005, month => 6, day => 20 ); my $date2 = DateTime->new( year => 2005, month => 6, day => 26, hour => 11, minute => 59 ); my $set = DateTime::Span->from_datetimes( start => $date1, end => $date2 ); my @events = $cal->events; is (@events, 1, "1 total event"); @events = $cal->events($set); is (@events, 7, "7 recurring events"); my $day = 20; for my $event (@events) { is($event->start->iso8601, "2005-06-${day}T11:00:00"); is($event->start->time_zone_long_name, 'Europe/London'); $day++; } @events = $cal->events($set,'minute'); is (@events, 7*60, "420 split recurring events"); Data-ICal-DateTime-0.82/t/04.all_day.t0000644000175000017500000000374113145634223016425 0ustar flavioflaviouse strict; use Test::More tests => 24; use Data::ICal::DateTime; use Data::ICal::Entry::Event; use DateTime; use DateTime::Set; use DateTime::TimeZone; my $cal; ok($cal = Data::ICal->new( filename => 't/ics/all_day.ics'), "parse all_day ics"); my $date1 = DateTime->new( year => 2005, month => 8, day => 1, hour => 23, minute => 59, second => 59 ); my $date2 = DateTime->new( year => 2005, month => 10, day => 27, hour => 23, minute => 59, second => 59); my @events = $cal->events; is (@events, 2, "2 total events"); my ($e1, $e2) = @events; is ($e1->summary,"Event 1"); is ($e2->summary,"Event 2"); is("".$e1->end, "".$date1, "E1's end is the correct date"); is("".$e2->end, "".$date1, "E2's end is the correct date"); is($e1->all_day,0, "E1 is not all day"); is($e2->all_day,1, "E2 is all day"); $e1->end($date2); $e2->end($date2); is("".$e1->end, "".$date2, "E1's end is the correct new date"); is("".$e2->end, "".$date2, "E2's end is the correct new date"); is($e1->all_day, 0, "E1 is not all day"); is($e2->all_day, 1, "E2 is all day"); $e2->all_day(0); is($e2->all_day, 0, "E2 is not all day"); is("".$e2->end, "".$date2, "E2's end is the correct new date"); $e2->all_day(1); is($e2->all_day, 1, "E2 is now all day again "); is("".$e2->end, "".$date2, "E2's end is the correct new date"); $e1->end($date1); $e2->end($date1); my @e1 = $e1->split_up('hour'); my @e2 = $e2->split_up('hour'); is(@e1, 14, "e1 14 exploded"); is(@e2, 14, "e2 14 exploded"); is($e1[0]->all_day, 0, "e1 exploded is not all day"); is($e2[0]->all_day, 0, "e2 exploded is all day"); is($e1[0]->original->all_day, 0, "e1 exploded wasn't originally all day"); is($e2[0]->original->all_day, 1, "e2 exploded was originally all day"); # test setting all day without end my $new = Data::ICal::Entry::Event->new(); my $new_date = $date1->clone->truncate( to => 'day' ); $new->start($new_date); $new->all_day(1); is ($new->all_day, 1, "New is all day"); is ("".$new->end, "".$date1, "New end is the same as start"); Data-ICal-DateTime-0.82/t/pod.t0000644000175000017500000000021413145634223015350 0ustar flavioflavio#!perl -T use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; all_pod_files_ok(); Data-ICal-DateTime-0.82/t/ics/0000755000175000017500000000000013146616577015177 5ustar flavioflavioData-ICal-DateTime-0.82/t/ics/meeting.ics0000644000175000017500000000136413145634223017316 0ustar flavioflavioBEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT DTSTART;TZID=Europe/London:20050804T183000 DTEND;TZID=Europe/London:20050804T230000 SUMMARY:London.pm social UID:6700873C-0409-11DA-A793-000A9599EB44 SEQUENCE:7 DTSTAMP:20050803T102748Z RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TH RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=TH;BYMONTHDAY=8 EXRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=TH;BYMONTHDAY=1 DESCRIPTION:We get drunk and talk crap END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050804T183000 DTEND;TZID=Europe/London:20050804T230000 SUMMARY:London.pm Heretics social UID:6700873C-0409-11DA-A793-000A9599EB44 SEQUENCE:7 DTSTAMP:20050803T102748Z RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=TH;BYMONTHDAY=1 DESCRIPTION: We get *really* drunk and talk crap END:VEVENT END:VCALENDAR Data-ICal-DateTime-0.82/t/ics/palm_recur.ics0000644000175000017500000000042113145634223020010 0ustar flavioflavioBEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT DESCRIPTION:Doesn't\nMatter DTSTAMP:20051003T080457Z DTSTART;VALUE=DATE:20051003 RRULE:FREQ=DAILY;BYHOUR=0;BYMINUTE=0 SUMMARY:Check 2341 assessment UID:palm-datebook-007f9a18-000076 END:VEVENT END:VCALENDAR Data-ICal-DateTime-0.82/t/ics/recur.ics0000644000175000017500000000041613145634223017003 0ustar flavioflavioBEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT DTSTART;TZID=Europe/London:20050615T110000 SUMMARY:Test event UID:2FB51E02-170F-11DA-B41B-000A9599EB44 SEQUENCE:2 DTSTAMP:20050827T152856Z RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20050818T225959Z DURATION:PT1H END:VEVENT END:VCALENDAR Data-ICal-DateTime-0.82/t/ics/all_day.ics0000644000175000017500000000033213145634223017265 0ustar flavioflavioBEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT SUMMARY:Event 1 DTSTART:20050801T103000 DTEND:20050801T235959 END:VEVENT BEGIN:VEVENT SUMMARY:Event 2 DTSTART:20050801T103000 DTEND;VALUE=DATE:20050802 END:VEVENT END:VCALENDAR Data-ICal-DateTime-0.82/t/ics/palm.ics0000644000175000017500000000035413145634223016615 0ustar flavioflavioBEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT DESCRIPTION:Doesn't\nMatter DTSTAMP:20051003T080457Z DTSTART;VALUE=DATE:20051003 SUMMARY:Check 2341 assessment UID:palm-datebook-007f9a18-000076 END:VEVENT END:VCALENDAR Data-ICal-DateTime-0.82/t/ics/test.ics0000644000175000017500000013160113145634223016643 0ustar flavioflavioBEGIN:VCALENDAR VERSION:2.0 X-WR-CALNAME:London.pm PRODID:-//Apple Computer\, Inc//iCal 2.0//EN X-WR-RELCALID:DEF1B3EE-62EF-4B86-BBDC-710AAC4B6867 X-WR-TIMEZONE:Europe/London CALSCALE:GREGORIAN METHOD:PUBLISH BEGIN:VTIMEZONE TZID:Europe/London LAST-MODIFIED:20050716T111510Z BEGIN:DAYLIGHT DTSTART:20030330T020000 TZOFFSETTO:+0100 TZOFFSETFROM:+0000 TZNAME:BST END:DAYLIGHT BEGIN:STANDARD DTSTART:20031026T020000 TZOFFSETTO:+0000 TZOFFSETFROM:+0100 TZNAME:GMT END:STANDARD BEGIN:DAYLIGHT DTSTART:20040328T020000 TZOFFSETTO:+0100 TZOFFSETFROM:+0000 TZNAME:BST END:DAYLIGHT BEGIN:STANDARD DTSTART:20041031T020000 TZOFFSETTO:+0000 TZOFFSETFROM:+0100 TZNAME:GMT END:STANDARD BEGIN:DAYLIGHT DTSTART:20050327T020000 TZOFFSETTO:+0100 TZOFFSETFROM:+0000 TZNAME:BST END:DAYLIGHT BEGIN:STANDARD DTSTART:20051030T020000 TZOFFSETTO:+0000 TZOFFSETFROM:+0100 TZNAME:GMT END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART;VALUE=DATE:20030709 DTEND;VALUE=DATE:20030710 SUMMARY:OSCon\, day 3 UID:B7685C95-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050226 DTEND;VALUE=DATE:20050228 SUMMARY:FOSDEM UID:03AC396F-6316-11D9-A8C0-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DTSTAMP:20050110T144347Z END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040315T170000 LOCATION:Smiths of Smithfield SUMMARY:London Java URL;VALUE=URI:http://web1.2020media.com/j/jez/javanicuscom/londonjava/ UID:E8E3F7D0-754C-11D8-AE04-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DURATION:PT6H END:VEVENT BEGIN:VEVENT LOCATION:The Clachan (Mayfair/SOHO near Regents Street) DTSTAMP:20040527T160401Z UID:F623FDE4-AFF6-11D8-8B00-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 URL;VALUE=URI:http://london.pm.org/meetings/locations/the_clachan.html DTSTART;TZID=Europe/London:20040603T180000 SUMMARY:London.pm Social Meet @ The Clachan DTEND;TZID=Europe/London:20040603T230000 DESCRIPTION:It's another social meet. This time at a *new* *pub* END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050209 DTEND;VALUE=DATE:20050212 SUMMARY:German Perl Workshop UID:E7CC599C-1522-11D9-8247-000393DA37B4-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030617 DTEND;VALUE=DATE:20030618 SUMMARY:YAPC::NA\, day 2 UID:48070B23-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040309T190000 STATUS:TENTATIVE SUMMARY:London SVG Users Group Meeting URL;VALUE=URI:http://london.pm.org/pipermail/london.pm/Week-of-Mon-20040 216/024834.html UID:6E7BB522-6136-11D8-A86D-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:11 DURATION:PT4H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030508T180000 SUMMARY:London.pm Meeting\, venue tbc UID:7DDA96AB-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:14 DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050505T180000 SUMMARY:London.pm Social @ The Windmill UID:08FE45EF-A5E7-11D9-9459-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 DTSTAMP:20050430T055559Z SEQUENCE:1 DESCRIPTION:This month's London.pm social will\, once again\, be at The Windmill in\nMayfair on Thursday the 5th of May at 6:30pm.\n\n http:/ /london.pm.org/meetings/locations/windmill.html\n http://www.windmill mayfair.co.uk/\n http://www.streetmap.co.uk/streetmap.dll?G2M?X=52900 1&Y=180921&A=Y&Z=1\n http://london.openguides.org/index.cgi?Windmill% 2C_W1S_2AT\n DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040429T180000 STATUS:TENTATIVE SUMMARY:UKUUG Perl night UID:58D46F46-7C23-11D8-BFFB-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 DESCRIPTION:TENTATIVE: Possible date for aselection of Perl talks (speak ers\, Dave Cross\, Mark Fowler\, Andy Wardley\, Simon Cozens) given to t he UK Unix User Group DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040805T180000 STATUS:CONFIRMED DTEND;TZID=Europe/London:20040805T230000 SUMMARY:Social Meet @ The Star UID:DF2C43AA-CBAA-11D8-975D-000393DA37B4-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 DTSTAMP:20040803T095111Z END:VEVENT BEGIN:VEVENT DURATION:P1D DTSTAMP:20040629T152410Z UID:5251010A-C9E0-11D8-8E69-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 STATUS:CONFIRMED DTSTART;VALUE=DATE:20040813 SUMMARY:YAPC::EU Slides Deadline DESCRIPTION:If you've been accepted to speak this year\, this is the dea dline for Papers/Slides for the proceedings\n\n(updated) END:VEVENT BEGIN:VEVENT LOCATION:Paris UID:BCAB74AC-74E0-11D8-AE04-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 URL;VALUE=URI:http://conferences.mongueurs.net/2004/ DTSTART;VALUE=DATE:20040606 SUMMARY:Les Journées Perl DTEND;VALUE=DATE:20040608 DESCRIPTION:Le dimanche 6 et le lundi 7 juin prochains\, se tiendra à Pa ris la première conférence Perl en français\, Les Journées Perl 2004.\n\ nTous les détails concernant cette conférence sont disponibles sur le si te http://conferences.mongueurs.net/2004/.\n\nLes Journées Perl sont l'o ccasion de se rencontrer et parler de Perl en français. Y seront réunis des gens qui ont mené des projets en Perl\, qui travaillent sur le langa ge lui-même\, qui utilisent ce langage tous les jours et qui veulent en apprendre plus.\n\nQuelques-uns des meilleurs auteurs et développeurs Pe rl francophones seront présents pour discuter de leur travail\, de leurs projets\, pour les mettre aux niveaux de tous\, débutants et confirmés. \n\nRejoignez-nous à Paris pendant ces deux jours pour parler et entendr e parler de Perl à la Cité des Sciences et de l'Industrie\, dans le 19èm e arrondissement de Paris.\n\n * Les pré-inscriptions seront possible s dès le 19 avril 2004\n * Les inscriptions seront ouvertes dès la fi n avril 2004\n\nFrais d'inscription à la conférence : environ 20 euro.\n \nUne liste de diffusion est ouverte pour discuter spécifiquement de cet te conférence et y poser toutes vos questions : http://conferences.mongu eurs.net/liste.html\n\nTous les détails concernant la conférence sont di sponibles sur le site http://conferences.mongueurs.net/2004/\n\nPlus d'i nformations sur ce que sera la conférence : http://conferences.mongueurs .net/2004/appel_participation.html\n\nPour soumettre une présentation : http://conferences.mongueurs.net/2004/appel_presentation.html\n\nNos spo nsors : http://conferences.mongueurs.net/sponsors.html END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030616 DTEND;VALUE=DATE:20030617 SUMMARY:YAPC::NA\, day 1 UID:41E5E412-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030611T200000 SUMMARY:Deadline for TT book review UID:7C3569D0-9785-11D7-820F-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20041206T180000 DTEND;TZID=Europe/London:20041206T180000 SUMMARY:Slide Deadline for LPW UID:C96D98B0-3957-11D9-A2FD-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DTSTAMP:20041118T114918Z DESCRIPTION:Speakers should have submitted thier slides to lpw by this p oint\n END:VEVENT BEGIN:VEVENT LOCATION:BUPA house DTSTAMP:20040902T163635Z UID:494491EC-C6B0-11D8-8E69-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 URL;VALUE=URI:http://london.pm.org/pipermail/london.pm-announce/2004-Sep tember/000111.html STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040909T190000 SUMMARY:London.pm Tech Meet DTEND;TZID=Europe/London:20040909T230000 DESCRIPTION:This month Alex will be talking about making music in Perl\, giving a live\ndemonstration (with big speakers and everything) of what he's been talking\nabout in his 'as seen on slashdot today' Perl.com ar ticle[1].\n\nSimon Cozens will be giving us a talk which is simply label led \"What I've\nbeen working on\"\, which will probably cover things li ke Where Was\, his new\n'search everything you've ever seen' and other e xciting things.\n\nTom Hukins will be doing his talk[2] on Running Web B usiness With Perl\,\nwhich he's practising for the upcoming YAPC::Europe .\n\nAnd I'll be talking to you briefly about a couple of modules I've b een\nplaying with\, and experiment with the Template Toolkit and AxKit a nd then\nbugging everyone about the Phalanx[2] project.\n\nSigning Up\n\ n We're collecting names of people that want to attend on our website.\ n\n http://london.pm.org/signup/\n\n No sign up\, no entry. Signup will close midnight spanning Tues\n 7th/Weds 8th. We won't use your n ame or email address for anything\n nasty\, honest guv'ner.\n\nDirectio ns to the Venue:\n\n http://www.streetmap.co.uk/streetmap.dll?G2M?X=530 262&Y=181615&A=Y&Z=1\n\n BUPA House is located on Bury Place. It's abo ut five minutes walk from\n either Tottenham Court Road or Holborn stat ion. A large eight floor\n building with big steps outside and the BUP A logo shown really large.\n Can't miss it.\n\n From Holborn Station:\ n\n Turn left out of the station and cross Kingsway and continue down\n High Holborn as it bears slightly to the right. Bury Place is on\n y our right.\n\n From Tottenham Court Road Station:\n\n Walk east out of the station down New Oxford Street so you're passing\n Centre point on your right. Keep going straight on as the road turns\n into Bloomsbur y Way. Bury place will be on your right.\n\nHope to see you there\, if not before (as tonight's the social.)\n\nMark.\n\n[1] http://www.perl.co m/pub/a/2004/08/31/livecode.html\n[2] http://belfast.yapc.org/wiki/index .cgi?RunningWebBusinessWithPerl\n[3] http://qa.perl.org/phalanx/\n END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040421 LOCATION:http://www.linuxuser.co.uk/expo DTEND;VALUE=DATE:20040423 SUMMARY:Linux Expo UID:A14C3B88-6DFE-11D8-8A32-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20041129T150000 SUMMARY:New Event UID:54720D5A-4604-11D9-897D-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DTSTAMP:20041204T145359Z DURATION:PT1H END:VEVENT BEGIN:VEVENT DURATION:PT5H DTSTAMP:20040504T120739Z UID:1C6ACFBA-92C1-11D8-AD10-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040504T180000 SUMMARY:Meeting wiht dha DESCRIPTION:At the founders arms\, near the tate modern END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040915 DTEND;VALUE=DATE:20040918 SUMMARY:YAPC::Europe UID:1EED7E92-5274-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20031204T180000 SUMMARY:London.pm social meeting\, venue tbc UID:F48595A9-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050831 LOCATION:Braga\, Portugal DTEND;VALUE=DATE:20050903 SUMMARY:YAPC::Europe 2005 UID:7E726022-5E59-11D9-8199-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:6 DTSTAMP:20050104T140451Z END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040205T190000 SUMMARY:Social Meet @ The Sun Tavern UID:B4815776-5575-11D8-A079-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 DESCRIPTION:http://london.pm.org/pipermail/london.pm-announce/2004-Janua ry/000083.html DURATION:PT4H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030522T180000 SUMMARY:London.pm Tech Meet UID:8C98AB84-6ACC-11D7-8EC3-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 DESCRIPTION:state 51 DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030602 DTEND;VALUE=DATE:20030603 SUMMARY:Perl Whirl\, day 2 UID:E8CF33F3-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040327 STATUS:CONFIRMED DTEND;VALUE=DATE:20040329 SUMMARY:YAPC::Taipei UID:90F1B68D-5273-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 END:VEVENT BEGIN:VEVENT DURATION:PT5H LOCATION:The CLACHAN\, 34 Kingly St.\,West End\, nr Oxford Cir UID:9AACB018-5A42-11D8-8AEE-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040212T180000 SUMMARY:Pub Recce - The CLACHAN DESCRIPTION:http://london.pm.org/pipermail/london.pm/Week-of-Mon-2004012 6/024365.html END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030605T180000 SUMMARY:London.pm Socail Meeting\, venue tbc UID:9598D4F8-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:7 DURATION:PT5H END:VEVENT BEGIN:VEVENT DURATION:PT5H LOCATION:De Hems - 11 Macclesfield Street Soho - Tel 020 74 UID:216800BE-6DFE-11D8-8A32-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 URL;VALUE=URI:http://www.streetmap.co.uk/newmap.srf?x=529778&y=180890&z= 1 DTSTART;TZID=Europe/London:20040311T180000 SUMMARY:Lonix DESCRIPTION:This month's meeting will be held upstairs in De Hems\, \na spacious Dutch bar in the heart of China Town\, Soho.\nA large range of beers from the continent are served\nalong with a selection of Dutch bar snacks. \n\nAs usual this month we will continue various linux \ndiscus sions and debates/punch-ups :) All are welcome\nto attend\, new\, old an d those inbetween. I'll have \na few Lonix shirts for sale which are sti ll \ncluttering up the basement. END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040531 DTEND;VALUE=DATE:20040601 SUMMARY:YAPC::EU Speaker Notification UID:00AA1D29-6C27-11D8-95B1-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 DESCRIPTION:If you've submitted a paper\, you'll be told if you're speak ing by this date END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040629 DTEND;VALUE=DATE:20040702 SUMMARY:German Perl Workshop UID:EABE791B-5273-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20031106T181500 SUMMARY:London.pm social meeting\, venue tbc UID:E5A209C8-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTAMP:20050411T164145Z UID:8AA4D86A-AAA8-11D9-B65D-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 URL;VALUE=URI:http://www.perl.it/workshop/ DTSTART;VALUE=DATE:20050623 SUMMARY:Italian Perl Workshop DTEND;VALUE=DATE:20050625 DESCRIPTION:http://www.perl.it/workshop/ END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030623T190000 SUMMARY:Tim O'Reilly speaking? UID:4D175B63-7C8F-11D7-B275-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 DURATION:PT1H END:VEVENT BEGIN:VEVENT LOCATION:Penderel's Oak\, High Holborn DTSTAMP:20040811T124137Z UID:05B252C6-EB92-11D8-8FFD-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 URL;VALUE=URI:http://london.pm.org/pipermail/london.pm/Week-of-Mon-20040 809/028550.html STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040812T190000 SUMMARY:Emergency Meet (XERN) DTEND;TZID=Europe/London:20040812T230000 DESCRIPTION:Hello\,\n\nSo here's hopefully the last emergency social bei ng announced for\nthese days.\n\nWhy? because XERN (@cpan) is in town.\n \nWhen: Thursday\, 12th August from 7pm\nWhere: Penderel's Oak\nHuh?: ht tp://london.openguides.org/index.cgi?Penderel's_Oak\,_WC1V_7HP\nMap: htt p://www.streetmap.co.uk/streetmap.dll?P2M?P=WC1V7HP&Z=1\n\nHope to see y ou there.\n\nCheers\,\nCLK END:VEVENT BEGIN:VEVENT DURATION:PT5H LOCATION:The Champion - 1 Wellington Terrace W2 4LW UID:287126C7-9155-11D8-AD10-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 URL;VALUE=URI:http://tinyurl.com/2nta9 DTSTART;TZID=Europe/London:20040421T180000 SUMMARY:Lonix DESCRIPTION:Nearest Tube: Nottinghill Gate. Bus 27 or 28 from Olympia. \nPhone: 020 8896 2600\n\nThis month we'll be going to the Champion in N ottinghill\nGate. Which is a stone's throw from Olympia where the\nLinux User and Developer show is happening this month\non the 20th and 21st ( next week). If you are going to\ncome along to the show you must registe r here to gain\nfree entrance.\n\nhttp://www.linuxuser.co.uk/expo\n\nWe' ll meet up at the end of the show (5.00pm) and go \ndown in a group (21s t). If you're going there on your\nown the nearest tube is Nottinghill G ate and it's a \nshort walk to the Champion. On exiting the station head \ntowards the Waterstones/Rhymans direction. You'll see \nthe Champion o n your left.\n\nThis pub has only just opened in the last week with \nne w management (if you knew the old pub \;) ) and we\nhave the entire down stairs and beer garden reserved\nfor us. A variety of fine ales and beer s are served\nas well as a huge selection of reasonably priced\nfood\, f rom sausage and mash to cray fish.\n END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030724 DTEND;VALUE=DATE:20030725 SUMMARY:YAPC::Europe day 2 UID:266FF32E-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050721T190000 SUMMARY:Potential Alternative London.pm social meet UID:D946FCFF-6759-4A02-9E76-12F7427DC845-E31211C1-6C87-42FD-9372-1902A4E 902D6 DTSTAMP:20050716T111414Z SEQUENCE:3 DURATION:P1DT4H END:VEVENT BEGIN:VEVENT DURATION:PT4H LOCATION:Morgan Stanley UID:D1538E40-5278-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040318T190000 SUMMARY:Tech Meet @ MS DESCRIPTION:We're in Morgan Stanly's Shakespeare Room in the Datacraft H ospitality Suite. Not the same room as last time. END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030515 DTEND;VALUE=DATE:20030516 SUMMARY:YAPC::Canada\, day 1 UID:6EB67C85-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040306 STATUS:CONFIRMED DTEND;VALUE=DATE:20040307 SUMMARY:BCS Programming Heat UID:45B28664-573D-11D8-A079-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:6 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030604 DTEND;VALUE=DATE:20030605 SUMMARY:Perl Whirl\, day 4 UID:F53F8BE3-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT LOCATION:Monash University in Melbourne UID:DEB7C76A-7D7B-11D8-BFFB-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 URL;VALUE=URI:http://yapc.dlist.com.au/ STATUS:CONFIRMED DTSTART;VALUE=DATE:20041201 SUMMARY:YAPC::AU DTEND;VALUE=DATE:20041204 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040719 DTEND;VALUE=DATE:20040721 SUMMARY:Italian Perl Workshop URL;VALUE=URI:http://www.perl.it/workshop/ UID:5D72868E-7460-11D8-A9B7-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040616 DTEND;VALUE=DATE:20040619 SUMMARY:YAPC::NA UID:03E457BA-5274-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040726 DTEND;VALUE=DATE:20040731 SUMMARY:OSCON UID:0DCE1F51-5274-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 END:VEVENT BEGIN:VEVENT DTSTAMP:20040828T111601Z UID:29DE970F-F8E3-11D8-AA35-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 URL;VALUE=URI:http://www.streetmap.co.uk/streetmap.dll?G2M?X=529001&Y=18 0921&A=Y&Z=1 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040902T180000 SUMMARY:Social at The Windmill DTEND;TZID=Europe/London:20040902T230000 DESCRIPTION:This is the announcement for the September Social Meet\, whi ch will take place at 7pm on Thursday the 2nd of September 2004 at the W indmill pub in Mayfair\, just south of Oxford Circus\, the same pub we h ad our April meeting in.\n\nhttp://www.streetmap.co.uk/streetmap.dll?G2M ?X=529001&Y=180921&A=Y&Z=1\n\nhttp://london.pm.org/meetings/locations/wi ndmill.html\n\nhttp://london.openguides.org/index.cgi?Windmill%2C_W1S_2A T\n\nDirections From Oxford Circus: Get out of the tube\, and head south down Regent Street Street. This is directly south from the circus\, aw ay from the church\, towards Piccadilly Circus. Take the forth exit on your right\, roughly opposite Hamleys\, down Conduit Street. Take the f irst left down Mill Street and the Pub is on the left side of the street . END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030710 DTEND;VALUE=DATE:20030711 SUMMARY:OSCon\, day 4 UID:BD108AAF-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20051017 DTEND;VALUE=DATE:20051021 SUMMARY:Euro OSCON Date? UID:4FFDB59E-AAA8-11D9-B65D-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DTSTAMP:20050411T164002Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030707 DTEND;VALUE=DATE:20030708 SUMMARY:OSCon\, day 1 UID:AACD7E94-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DURATION:PT1H DTSTAMP:20040903T161332Z UID:1E2BE254-FDC4-11D8-BB3D-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 STATUS:TENTATIVE DTSTART;TZID=Europe/London:20040927T180000 SUMMARY:Potential Emergancy Social Meet DESCRIPTION:mbm writes:\n\nSo\, at some point in the next few weeks\, I propose an emergency trip to the\nOakdale Arms\, Haringay. http://www.in dividualpubs.co.uk/oakdale/ All of you\nwill love it because you walk in and 8 hand pumps\, each with a different\nbeer will face you. It also h appens to be run by Steve Early\, who many of\nyou may or may not know a s the moderator of UKCrypto\, the old owner of the\nhouse at Green End R oad in Cambridge (hence greenend.org.uk) and other such\ndistinctions.\n END:VEVENT BEGIN:VEVENT LOCATION:The Anchor\, South Bank DTSTAMP:20040811T124220Z UID:3AAB3FCE-EB92-11D8-8FFD-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 URL;VALUE=URI:http://london.pm.org/pipermail/london.pm/Week-of-Mon-20040 809/028549.html STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040818T190000 SUMMARY:Emergency Meet (Jody and Jesse) DTEND;TZID=Europe/London:20040818T230000 DESCRIPTION:Leon wasn't kidding when he said there might be other emerge ncy meets \nnext week\, though I have\nprobably committed some horrible faux-pas by managing to turn two pub \noutings into one.\n\nJody Belka and I will both be in town\, but neither of us are able to \nmake it t o the Star on Saturday. Jody\n and I were independently plotting to dra g folks out to the pub\, but we \nmanaged to settle on Wednesday\nas a date that works for both of us.\n\nThe Anchor has been suggested me as a reasonable place to go\, \nespecially if it's reasonably nice out.\n\n \nWhen: Wedneday\, August 18th\, 7pm onward\nWhere: The Anchor\, Ban kside\, SE1\nWhere?: (http://london.pm.org/meetings/locations/theanchor .html)\nMap: \n http://www.streetmap.co.uk/newmap.srf? \nx=53244 7&y=180423&z=1&sv=SE1%209DN&st=PostCode&lu=N&tl=~&ar=y&bi=~\n\n\nBest\,\ n\nJesse\n\n END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20041211T100000 LOCATION:Imperial College Union\, Exhibition Road\, London SUMMARY:London Perl Workshop URL;VALUE=URI:http://london.pm.org/lpw/ UID:B94EF70F-0C6C-11D9-BDE1-000393DA37B4-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DURATION:PT8H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040408T190000 STATUS:CONFIRMED SUMMARY:London PM Meet - The Windmill UID:954ED510-790F-11D8-8061-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 DESCRIPTION:confirmed DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030601 DTEND;VALUE=DATE:20030602 SUMMARY:Perl Whirl\, day 1 UID:E1D96D37-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050106T190000 LOCATION:The Windmill DTEND;TZID=Europe/London:20050106T230000 SUMMARY:Social Meet UID:146B569D-5F38-11D9-B40C-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DTSTAMP:20050105T163801Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040327 STATUS:CONFIRMED DTEND;VALUE=DATE:20040329 SUMMARY:Nordic Perl Workshop UID:814BB078-5273-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040430 DTEND;VALUE=DATE:20040501 SUMMARY:YAPC::EU CFP Deadiline URL;VALUE=URI:http://belfast.yapc.org/cfp.html UID:E2386592-6C26-11D8-95B1-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030606 DTEND;VALUE=DATE:20030607 SUMMARY:Perl Whirl\, day 6 UID:02A5692C-5B94-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20041104T180000 STATUS:TENTATIVE SUMMARY:London.pm Social UID:FD7AD02C-0C6C-11D9-BDE1-000393DA37B4-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030511 DTEND;VALUE=DATE:20030512 SUMMARY:YAPC::Israel UID:5DFE0224-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DURATION:PT5H LOCATION: St Stephen's Tavern (Westminster\, Opposite The Ho UID:E577CB21-BA06-11D8-9276-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 URL;VALUE=URI:http://london.pm.org/lpma/2004-June/000096.html STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040708T180000 SUMMARY:London.pm Social Meet @ St Stephen's Tavern DESCRIPTION:It's another social meet. This time in another a *new* *pub * END:VEVENT BEGIN:VEVENT LOCATION:Brussels UID:8B6BAACE-5962-11D8-838E-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 STATUS:CONFIRMED DTSTART;VALUE=DATE:20040221 SUMMARY:FOSDEM DTEND;VALUE=DATE:20040223 DESCRIPTION:http://www.fosdem.org END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050609 DTEND;VALUE=DATE:20050611 SUMMARY:Austrian Perl Workshop UID:72FFF8F8-AAA8-11D9-B65D-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DTSTAMP:20050411T164057Z DESCRIPTION:http://conferences.mongueurs.net/apw2005/?language=en END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20050801 DTEND;VALUE=DATE:20050806 SUMMARY:OSCON UID:83557149-63C2-11D9-B456-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DTSTAMP:20050111T111835Z END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050407T180000 DTEND;TZID=Europe/London:20050407T230000 SUMMARY:London.pm Social @ The Star UID:EB9A6527-A5E6-11D9-9459-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 DTSTAMP:20050405T152535Z END:VEVENT BEGIN:VEVENT LOCATION:University of Toronto\, Toronto\, Canada DTSTAMP:20050210T170349Z UID:5D3DD57C-0E0F-11D9-A987-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 URL;VALUE=URI:http://yapc.org/America/ DTSTART;VALUE=DATE:20050627 SUMMARY:YAPC::NA DTEND;VALUE=DATE:20050630 END:VEVENT BEGIN:VEVENT LOCATION:Morgan Stanley\, Canda Water DTSTAMP:20040716T134949Z UID:6FC6588C-BA07-11D8-9276-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:8 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040722T190000 SUMMARY:London.pm Tech Meet DTEND;TZID=Europe/London:20040722T213000 DESCRIPTION:http://london.pm.org/pipermail/london.pm-announce/2004-July/ 000102.html END:VEVENT BEGIN:VEVENT LOCATION:Porter House Pub - 21-22 Maiden Lane\, WC2 E7NA DTSTAMP:20040719T202418Z UID:57F3DCD0-D9C1-11D8-B716-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 URL;VALUE=URI:http://www.lonix.org.uk/cgi-bin/Lonix?CODE=searchMeeting&C URRENT=YES STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040721T180000 SUMMARY:Lonix DTEND;TZID=Europe/London:20040721T230000 DESCRIPTION:Lonix is The London Linux User Group\n\nVenue: http://www.co ventgardenlife.com/places.asp?PlaceID=145\n\n END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040816 DTEND;VALUE=DATE:20040823 SUMMARY:Linuxbierwanderung UID:E3698780-615A-11D8-A86D-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 URL;VALUE=URI:http://london.pm.org/pipermail/london.pm-announce/2004-Jan uary/000082.html SEQUENCE:3 DESCRIPTION:Linux\, Beer\, and Walking END:VEVENT BEGIN:VEVENT DURATION:PT4H LOCATION:The Porter House\, Covent Gdn DTSTAMP:20050105T163838Z UID:1FD6BDFB-5F38-11D9-B40C-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DTSTART;TZID=Europe/London:20050112T190000 SUMMARY:Lonix DESCRIPTION:\n\nTo kick start the year and enjoy the sales\,\nwe'll be m eeting in the Porter House pub. This is\nlocated in Covent Garden and is an excellent venue\nboasting at least one beer from each country along\ nwith a variety of wines\, Belgium beers\nand micro breweries from many continents. We are in\nthe corporate hospitality suite up the stairs tow ards\nthe back. Again we'll be having a set of games\, including \na lin ux pub quiz\, prizes\, forfeits and other activities.\nOff course seriou s linux discussion will be carried \nout throughout the night.\n\nFrom C ovent Garden Station\, walk into the main square\nand take a right\, wal k out of the square and take\nthe next left. Keep walking straight until you \nsee Maiden Lane on your left. (down a small \nroad). Porter House is on your right next\nto the Spanish Tapas place\, La Tasca.\n\nIf thi s sounds all too much we'll be going for\na curry around the corner at 9 .00pm at the\nStrand Tandoori restaurant\, 45 Bedford Place.\nhttp://tin yurl.com/5s62n. We're having a set\nmenu here (12 pounds a head for 4 co urses)\nwhich is both vegetarian and non veg.\n\nRemember there is also a Lonix Mailling List\nthat you can sign up to. Simply log into \nthe Lo nix web site to subscribe to one of the\ngroups!\n\nThere are a few Loni x Polo Shirts left. Email \nin advance if you're interested.\n\nHope to see you next week\,\n END:VEVENT BEGIN:VEVENT LOCATION:Imperial College Union (Biet Quad) DTSTAMP:20040528T165717Z UID:EB571330-B0C7-11D8-8858-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 URL;VALUE=URI:http://www.xcom2002.com/nc04/ DTSTART;TZID=Europe/London:20040606T110000 SUMMARY:Notcon DTEND;TZID=Europe/London:20040606T190000 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20031215T110000 SUMMARY:Joint London Soclal Meetup UID:58BE51EC-11D3-11D8-BB30-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030904T180000 SUMMARY:London.pm Social Meeting\, Venue tbc UID:CB6E5BCE-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040328 DTEND;VALUE=DATE:20040329 SUMMARY:Austrian Perl Workshop CFP deadline URL;VALUE=URI:http://vienna.pm.org/en_workshop.html UID:E80736D8-74E1-11D8-AE04-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040220T183000 STATUS:CONFIRMED SUMMARY:BCS Deadline UID:57256134-573D-11D8-A079-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 DESCRIPTION:This is the last day you can enter the BCS programming compe tion that's taking place on the 6th DURATION:PT0S END:VEVENT BEGIN:VEVENT DURATION:PT2H LOCATION:Pillars of Hercules\, Greek Street\, Soho\, London UID:AD8ADB1C-790F-11D8-8061-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:7 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040320T160000 SUMMARY:LPM Rugby DESCRIPTION:Small gathering to watch the England (and welsh) match END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040327 STATUS:CONFIRMED DTEND;VALUE=DATE:20040328 SUMMARY:YAPC::NA CFP deadline UID:F24FB0BE-5C77-11D8-B46A-0030654B4FB2-E31211C1-6C87-42FD-9372-1902A4E 902D6 URL;VALUE=URI:http://yapc.org/America/cfp.shtml SEQUENCE:1 END:VEVENT BEGIN:VEVENT DURATION:P2D DTSTAMP:20050411T164233Z UID:AD5CB28C-AAA8-11D9-B65D-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 URL;VALUE=URI:http://conferences.mongueurs.net/fpw2005/ DTSTART;VALUE=DATE:20050609 SUMMARY:French Perl Workshop DESCRIPTION:http://conferences.mongueurs.net/fpw2005/ END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030618 DTEND;VALUE=DATE:20030619 SUMMARY:YAPC::NA UID:4CC40656-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030711 DTEND;VALUE=DATE:20030712 SUMMARY:OSCon\, day 5 UID:C2798296-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030403T180000 SUMMARY:London.pm Social\, venue tbc proabably the windmill UID:1CD79EAE-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:18 DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030725 DTEND;VALUE=DATE:20030726 SUMMARY:YAPC::Europe day 3 UID:34DC1B72-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20041007T180000 SUMMARY:Social at The Star UID:754915CC-1523-11D9-8247-000393DA37B4-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030607 DTEND;VALUE=DATE:20030608 SUMMARY:Perl Whirl\, day 7 UID:08011BD3-5B94-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030603 DTEND;VALUE=DATE:20030604 SUMMARY:Perl Whirl\, day 3 UID:EF636995-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT LOCATION:G08 at the Euston Centre of Westminster University DTSTAMP:20040716T134628Z UID:58A7D6E0-D72E-11D8-B716-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:7 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040717T143000 SUMMARY:Gllug Meet DTEND;TZID=Europe/London:20040717T170000 DESCRIPTION:http://www.gllug.org.uk/meeting-20040717.html\n\nDrinks in t he pub after the meeting (see URL) END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030414T190000 SUMMARY:London.pm Mini-Tech Meet UID:4CA880B6-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:13 DURATION:PT4H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040401T190000 SUMMARY:London PM new heretics meet UID:A0A8C372-790F-11D8-8061-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DURATION:PT4H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040520 DTEND;VALUE=DATE:20040523 SUMMARY:Austrian Perl Workshop URL;VALUE=URI:http://vienna.pm.org/en_workshop.html UID:A29338D8-74E1-11D8-AE04-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040324T180000 SUMMARY:New HDD going into penderel UID:D921F672-7BFD-11D8-BFFB-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DURATION:PT1H END:VEVENT BEGIN:VEVENT DURATION:PT4H LOCATION:The Star of Belgravia\, London UID:F8094813-5575-11D8-A079-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040304T190000 SUMMARY:Social Meet @ The Star DESCRIPTION:http://london.pm.org/pipermail/london.pm-announce/2004-Janua ry/000083.html END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030516 DTEND;VALUE=DATE:20030517 SUMMARY:YAPC::Canada\, day 2 UID:78695B10-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030614T104500 SUMMARY:Offical London.pm Flight to Miami UID:4AA8136E-6F86-11D7-80D6-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:6 DURATION:PT13H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030807T180000 SUMMARY:London.pm Social Meeting\, Venue tbc UID:BDCDC274-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 DURATION:PT1H END:VEVENT BEGIN:VEVENT DURATION:PT4H LOCATION:The Angel Pub\, Nr Old Street DTSTAMP:20040506T102348Z UID:3F146204-92C1-11D8-AD10-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040527T190000 SUMMARY:Tech Meet DESCRIPTION:Not on the 20th due to the Austrian Perl workshop and becaus e there are three perl meets at the start of the month. END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030708 DTEND;VALUE=DATE:20030709 SUMMARY:OSCon\, day 2 UID:B14B8906-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040226 STATUS:CONFIRMED DTEND;VALUE=DATE:20040227 SUMMARY:YAPC::Israel UID:17F2C75C-5273-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040419 DTEND;VALUE=DATE:20040420 SUMMARY:Les Journées Perl appel participation deadline URL;VALUE=URI:http://conferences.mongueurs.net/2004/appel_participation. html UID:2D91A96B-74E1-11D8-AE04-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20031002T174500 SUMMARY:London.pm Social Meeting\, Venue tbc UID:DA675BE6-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT DURATION:PT1H LOCATION:City University\, London UID:F599CD4A-5275-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040219T190000 SUMMARY:Tim O'Reilly Speaking DESCRIPTION:http://www.ukcfug.org/index.cfm?objectid=34A5AE57-0AA2-93EF- B8EE09920B923A51\n\nEntry free\, but you'll have to register beforehand END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030703T180000 SUMMARY:London.pm Social Meeting\, Venue tbc UID:AFA80E86-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT LOCATION:The Star\, Belgravia DTSTAMP:20040811T124311Z UID:58641B6C-EB92-11D8-8FFD-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 URL;VALUE=URI:http://london.pm.org/pipermail/london.pm/Week-of-Mon-20040 809/028541.html STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040814T190000 SUMMARY:Emergency Meet (Tanja) DTEND;TZID=Europe/London:20040814T230000 DESCRIPTION:Hello\,\n\nI'm going to break from tradition and organise an emergency meet on\nSaturday evening. Tanja\, a valued member of Amsterd am.pm\, will be\nvisiting\, and it will be her 25th birthday. She wouldn 't object to\npresents or balloons.\n\nWhen: Saturday\, 14th August from 7pm\nWhere: Star Tavern\nHuh?: http://london.openguides.org/index.cgi?S tar_Tavern\,_SW1X_8HT\nMap: http://www.streetmap.co.uk/streetmap.dll?G2M ?X=528107&Y=179347&A=Y&Z=1\n\nI hear there may be other emergency meets this week\, hic.\n\nAnyway\, see you there! Leon END:VEVENT BEGIN:VEVENT LOCATION:St Stephen's Tavern DTSTAMP:20050228T121108Z UID:ADAC4ED3-8981-11D9-87E8-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 URL;VALUE=URI:http://london.pm.org/pipermail/london.pm-announce/2005-Feb ruary/000127.html DTSTART;TZID=Europe/London:20050303T183000 SUMMARY:March London.pm Social DTEND;TZID=Europe/London:20050303T230000 DESCRIPTION:http://london.pm.org/pipermail/london.pm-announce/2005-Febru ary/000127.html END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050707T190000 DTEND;TZID=Europe/London:20050708T230000 SUMMARY:CANCELLED: London.pm social meet UID:729EFFEE-08B5-4CB7-AF93-F1EFA9A4A270-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:8 DTSTAMP:20050707T121323Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030723 DTEND;VALUE=DATE:20030724 SUMMARY:YAPC::Europe\, day 1 UID:1E4E04B2-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040305 STATUS:CONFIRMED DTEND;VALUE=DATE:20040306 SUMMARY:Dutch Perl Workshop UID:3E87BD46-5273-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 END:VEVENT BEGIN:VEVENT LOCATION:The Star\, Belgravia DTSTAMP:20040506T102258Z UID:2F287D89-92C1-11D8-AD10-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 URL;VALUE=URI:http://london.pm.org/lpma/2004-April/000091.html STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040506T190000 SUMMARY:Social Meet DTEND;TZID=Europe/London:20040506T230000 DESCRIPTION:http://london.pm.org/lpma/2004-April/000091.html END:VEVENT BEGIN:VEVENT DURATION:PT0S LOCATION:FOSDEM\, Brussels UID:A3218526-5962-11D8-838E-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:5 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040222T150000 SUMMARY:Dave Cross Speaking DESCRIPTION:The Perl session by Dave Cross . Dave is the co-author of th e newly\npubllished -The Perl Template Toolkit http://www.oreilly.com/ca talog/perltt/ END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20041010 DTEND;VALUE=DATE:20041016 SUMMARY:Perl Whirl UID:38041992-5274-11D8-8085-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 DESCRIPTION:Nerds AFLOAT! END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050602T180000 SUMMARY:London.pm Social @ Venue TBC UID:0F616746-A5E7-11D9-9459-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 DTSTAMP:20050405T152619Z SEQUENCE:1 DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20051003 DTEND;VALUE=DATE:20051012 SUMMARY:Perl Whirl UID:1DA1036C-6316-11D9-A8C0-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 DESCRIPTION:Nerds AFLOAT! SEQUENCE:3 DTSTAMP:20050110T144429Z END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20041202T190000 LOCATION:The Angel @ Old Street DTEND;TZID=Europe/London:20041202T230000 SUMMARY:London.pm Social UID:E9843E62-420A-11D9-9150-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 DTSTAMP:20041129T133135Z END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030501T180000 SUMMARY:London.pm Heretics Meeting UID:690C1B41-5B92-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:11 DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040415 DTEND;VALUE=DATE:20040416 SUMMARY:Italian Perl Workshop CFP Deadline URL;VALUE=URI:http://www.perl.it/workshop/cfp.html UID:848D01EE-7460-11D8-A9B7-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20041026 LOCATION:Santa Clara\, CA\, United States DTEND;VALUE=DATE:20041031 SUMMARY:O'Reilly Mac OS X Conf UID:A9C6154E-6C27-11D8-95B1-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20030605 DTEND;VALUE=DATE:20030606 SUMMARY:Perl Whirl\, day 5 UID:FAD8501A-5B93-11D7-BD0B-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20030520T174500 SUMMARY:YAPC::NA Paper Deadline UID:4FC651CA-800A-11D7-B275-000393CB5CEC-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:1 DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040805 DTEND;VALUE=DATE:20040809 SUMMARY:UKUUG Technical Conf UID:87F595FD-DA68-11D8-B716-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 URL;VALUE=URI:http://www.ukuug.org/events/linux2004/ SEQUENCE:3 DTSTAMP:20040720T161943Z END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20040209 DTEND;VALUE=DATE:20040210 SUMMARY:OSCON CFP deadline UID:4E06F71A-573A-11D8-A079-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:2 DESCRIPTION:http://conferences.oreillynet.com/cs/os2004/create/e_sess END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040410T180000 LOCATION:The Winsor Castle\, Notting Hill SUMMARY:Emerg. Social UID:F3478B8D-87D8-11D8-A370-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:6 DESCRIPTION:Abigale is in town\, so we're meeting up with him. DURATION:PT5H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20040421T181500 SUMMARY:BCS: Should we Open IT? URL;VALUE=URI:http://www.nlondon.bcs.org/ UID:2B5EB297-8233-11D8-A370-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:6 DESCRIPTION:This is a BCS Meeting\, though it's open to all.\n\nSpeaking :\n\n * DAVE CROSS\n * MIKE ROBINSON\n * RICHARD STEEL\n DURATION:PT3H45M END:VEVENT BEGIN:VEVENT LOCATION:London: Business Design Centre\, Upper Street\, Islington UID:1B561080-5963-11D8-838E-000393AF6250-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:4 STATUS:CONFIRMED DTSTART;VALUE=DATE:20040223 SUMMARY:Devweek DTEND;VALUE=DATE:20040228 DESCRIPTION:http://www.devweek.com/new/ END:VEVENT BEGIN:VEVENT DURATION:PT5H LOCATION:Museum Tavern\, by the Brittish Museum DTSTAMP:20040629T083515Z UID:24BE666A-BA07-11D8-9276-000A95D05D54-E31211C1-6C87-42FD-9372-1902A4E 902D6 SEQUENCE:3 STATUS:CONFIRMED DTSTART;TZID=Europe/London:20040701T180000 SUMMARY:London.pm New Heretics Meet DESCRIPTION:Heretics meets are not 'offical' or organised by London.pm. They're a breakaway bunch of splitters.\n\nDave Cantrell (Deputy Chief Heretic and Official Trouble Maker) said:\n\nJuly starts on a Thursday\, so by long and ancient tradition we need to go to the pub and drink bee r. This month's Heretics' Meet will be at the Museum Tavern\, on the ju nction of Museum St and Great Russell St.\n\nNearest tubes are Tottenham Court Rd\, Holborn\, and Russell Sq.\n\nmap: http://www.streetmap.co.uk /streetmap.dll?G2M?X=530129&Y=181578&A=Y&Z=1\n END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050801T090000 DTEND;TZID=Europe/London:20050801T130000 SUMMARY:Mailman Day Reminder UID:DF51C24D-0408-11DA-A793-000A9599EB44 SEQUENCE:7 DTSTAMP:20050803T102342Z RRULE:FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=1 END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050804T183000 DTEND;TZID=Europe/London:20050804T230000 SUMMARY:London.pm social UID:6700873C-0409-11DA-A793-000A9599EB44 SEQUENCE:7 DTSTAMP:20050803T102748Z RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TH DESCRIPTION:We get drunk and talk crap END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050818T180000 DTEND;TZID=Europe/London:20050818T210000 SUMMARY:London.pm tech meet UID:670088B6-0409-11DA-A793-000A9599EB44 SEQUENCE:4 DTSTAMP:20050803T102833Z DESCRIPTION:We don't get drunk but still talk crap RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=3TH END:VEVENT END:VCALENDAR Data-ICal-DateTime-0.82/t/ics/recurrence-id.ics0000644000175000017500000000072613145634223020416 0ustar flavioflavioBEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT DTSTART;TZID=Europe/London:20050815T110000 SUMMARY:Test event UID:2FB51E02-170F-11DA-B41B-000A9599EB44 SEQUENCE:2 DTSTAMP:20050827T152856Z RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20050818T225959Z DURATION:PT1H END:VEVENT BEGIN:VEVENT DTSTART;TZID=Europe/London:20050816T110000 SUMMARY:This is on a Tuesday UID:2FB51E02-170F-11DA-B41B-000A9599EB44 RECURRENCE-ID;TZID=Europe/London:20050816T110000 DURATION:PT1H END:VEVENT END:VCALENDAR Data-ICal-DateTime-0.82/t/05.palm_floating_recur.t0000644000175000017500000000242513145634223021033 0ustar flavioflaviouse strict; use Test::More tests => 13; use Data::ICal::DateTime; use Data::ICal::Entry::Event; use DateTime; use DateTime::Set; use DateTime::TimeZone; my $cal; ok($cal = Data::ICal->new( filename => 't/ics/palm_recur.ics'), "parse palm recur ics"); my $date1 = DateTime->new( year => 2005, month => 10, day => 4 ); my $date2 = $date1->clone->add( days => 1 )->subtract( nanoseconds => 1 ); my $span = DateTime::Span->from_datetimes( start => $date1, end => $date2 ); my @events = $cal->events($span); use Data::Dumper; print Dumper(@events); is(scalar(@events),1,"1 event"); my $ev = shift @events; my $s = $ev->start; my $e = $ev->end; is("$s", "$date1", "Start is the same as date1"); is ($e, undef, "End if undef"); is($ev->floating, 1, "Event is floating"); is($ev->floating(0), 0, "Set floating to 0"); $s = $ev->start; $e = $ev->end; is("$s", "$date1", "Start is still the same as date1"); is("$e", "$date2", "End is now the same as date2"); is($ev->floating, 0, "Event isn't floating"); is($ev->floating(1), 1, "Set floating to 1"); $s = $ev->start; $e = $ev->end; is("$s", "$date1", "Start is still the same as date1. Again."); is ($e, undef, "End if undef. Again."); is($ev->floating, 1, "Event is floating. Again."); Data-ICal-DateTime-0.82/t/02.complicated.t0000644000175000017500000000162613145634223017302 0ustar flavioflaviouse strict; use Test::More tests => 7; use Data::ICal::DateTime; use DateTime; use DateTime::Set; use DateTime::TimeZone; my $cal; ok($cal = Data::ICal->new( filename => 't/ics/meeting.ics'), "parse meetings ics"); my $date1 = DateTime->new( year => 2005, month => 8, day => 1 ); my $date2 = DateTime->new( year => 2005, month => 10, day => 27 ); my $span = DateTime::Span->from_datetimes( start => $date1, end => $date2 ); # $set->set_time_zone('Europe/London'); my @events; @events = $cal->events; is (@events, 2, "2 total events"); @events = sort { $a->start->epoch <=> $b->start->epoch }$cal->events($span); is (@events, 4, "4 exploded events"); is($events[0]->summary, "London.pm social", "Got social"); is($events[1]->summary, "London.pm Heretics social", "Got Heretics social"); is($events[2]->summary, "London.pm social", "Got social"); is($events[3]->summary, "London.pm social", "Got social"); Data-ICal-DateTime-0.82/t/pod-coverage.t0000644000175000017500000000025413145634223017145 0ustar flavioflavio#!perl -T use Test::More; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; all_pod_coverage_ok(); Data-ICal-DateTime-0.82/t/03.recurrence-id.t0000644000175000017500000000166613145634223017552 0ustar flavioflaviouse strict; use Test::More tests => 8; use Data::ICal::DateTime; use DateTime; use DateTime::Set; use DateTime::TimeZone; my $cal; ok($cal = Data::ICal->new( filename => 't/ics/recurrence-id.ics'), "parse recurrence-id ics"); my $date1 = DateTime->new( year => 2005, month => 8, day => 1 ); my $date2 = DateTime->new( year => 2005, month => 10, day => 27 ); my $span = DateTime::Span->from_datetimes( start => $date1, end => $date2 ); # $set->set_time_zone('Europe/London'); my @events; @events = $cal->events; is (@events, 2, "2 total events"); @events = sort { $a->start->epoch <=> $b->start->epoch }$cal->events($span); is (@events, 4, "4 exploded events"); is($events[0]->summary, "Test event", "Test Event"); is($events[1]->summary, "This is on a Tuesday", "Got note"); is($events[2]->summary, "Test event", "Test Event"); is($events[3]->summary, "Test event", "Test Event"); is($events[0]->uid, $events[1]->uid, "UIDs the same"); Data-ICal-DateTime-0.82/t/00.load.t0000644000175000017500000000054213145634223015727 0ustar flavioflaviouse Test::More tests => 11; BEGIN { use_ok( 'Data::ICal::DateTime' ); } diag( "Testing Data::ICal::DateTime $Data::ICal::DateTime::VERSION" ); # check the import stuff ok(Data::ICal->can('events'),"Events"); for (qw(start end duration summary description recurrence explode is_in _normalise)) { ok(Data::ICal::Entry::Event->can($_),"Can $_"); } Data-ICal-DateTime-0.82/MANIFEST0000644000175000017500000000122713145634223015274 0ustar flavioflavioChanges examples/ics2rss inc/Module/Install.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm lib/Data/ICal/DateTime.pm Makefile.PL MANIFEST This list of files MANIFEST.SKIP META.yml t/00.load.t t/01.parse.t t/01.parse_recurring.t t/02.complicated.t t/03.recurrence-id.t t/04.all_day.t t/05.palm_floating.t t/05.palm_floating_recur.t t/complex-dtstart.t t/ics/all_day.ics t/ics/meeting.ics t/ics/palm.ics t/ics/palm_recur.ics t/ics/recur.ics t/ics/recurrence-id.ics t/ics/test.ics t/pod-coverage.t t/pod.t Data-ICal-DateTime-0.82/MANIFEST.SKIP0000644000175000017500000000013313145634223016034 0ustar flavioflaviotry .tar.gz MYMETA\. ^Makefile$ Makefile.old .svn blib .cache benchmark ^ics\/ .git \.bak$ Data-ICal-DateTime-0.82/inc/0000755000175000017500000000000013146616577014727 5ustar flavioflavioData-ICal-DateTime-0.82/inc/Module/0000755000175000017500000000000013146616577016154 5ustar flavioflavioData-ICal-DateTime-0.82/inc/Module/Install/0000755000175000017500000000000013146616577017562 5ustar flavioflavioData-ICal-DateTime-0.82/inc/Module/Install/Win32.pm0000644000175000017500000000340313145634223021005 0ustar flavioflavio#line 1 package Module::Install::Win32; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.14'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # determine if the user needs nmake, and download it if needed sub check_nmake { my $self = shift; $self->load('can_run'); $self->load('get_file'); require Config; return unless ( $^O eq 'MSWin32' and $Config::Config{make} and $Config::Config{make} =~ /^nmake\b/i and ! $self->can_run('nmake') ); print "The required 'nmake' executable not found, fetching it...\n"; require File::Basename; my $rv = $self->get_file( url => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe', ftp_url => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe', local_dir => File::Basename::dirname($^X), size => 51928, run => 'Nmake15.exe /o > nul', check_for => 'Nmake.exe', remove => 1, ); die <<'END_MESSAGE' unless $rv; ------------------------------------------------------------------------------- Since you are using Microsoft Windows, you will need the 'nmake' utility before installation. It's available at: http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe or ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe Please download the file manually, save it to a directory in %PATH% (e.g. C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to that directory, and run "Nmake15.exe" from there; that will create the 'nmake.exe' file needed by this module. You may then resume the installation process described in README. ------------------------------------------------------------------------------- END_MESSAGE } 1; Data-ICal-DateTime-0.82/inc/Module/Install/Base.pm0000644000175000017500000000214713145634223020761 0ustar flavioflavio#line 1 package Module::Install::Base; use strict 'vars'; use vars qw{$VERSION}; BEGIN { $VERSION = '1.14'; } # Suspend handler for "redefined" warnings BEGIN { my $w = $SIG{__WARN__}; $SIG{__WARN__} = sub { $w }; } #line 42 sub new { my $class = shift; unless ( defined &{"${class}::call"} ) { *{"${class}::call"} = sub { shift->_top->call(@_) }; } unless ( defined &{"${class}::load"} ) { *{"${class}::load"} = sub { shift->_top->load(@_) }; } bless { @_ }, $class; } #line 61 sub AUTOLOAD { local $@; my $func = eval { shift->_top->autoload } or return; goto &$func; } #line 75 sub _top { $_[0]->{_top}; } #line 90 sub admin { $_[0]->_top->{admin} or Module::Install::Base::FakeAdmin->new; } #line 106 sub is_admin { ! $_[0]->admin->isa('Module::Install::Base::FakeAdmin'); } sub DESTROY {} package Module::Install::Base::FakeAdmin; use vars qw{$VERSION}; BEGIN { $VERSION = $Module::Install::Base::VERSION; } my $fake; sub new { $fake ||= bless(\@_, $_[0]); } sub AUTOLOAD {} sub DESTROY {} # Restore warning handler BEGIN { $SIG{__WARN__} = $SIG{__WARN__}->(); } 1; #line 159 Data-ICal-DateTime-0.82/inc/Module/Install/Fetch.pm0000644000175000017500000000462713145634223021145 0ustar flavioflavio#line 1 package Module::Install::Fetch; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.14'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub get_file { my ($self, %args) = @_; my ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) { $args{url} = $args{ftp_url} or (warn("LWP support unavailable!\n"), return); ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; } $|++; print "Fetching '$file' from $host... "; unless (eval { require Socket; Socket::inet_aton($host) }) { warn "'$host' resolve failed!\n"; return; } return unless $scheme eq 'ftp' or $scheme eq 'http'; require Cwd; my $dir = Cwd::getcwd(); chdir $args{local_dir} or return if exists $args{local_dir}; if (eval { require LWP::Simple; 1 }) { LWP::Simple::mirror($args{url}, $file); } elsif (eval { require Net::FTP; 1 }) { eval { # use Net::FTP to get past firewall my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); $ftp->login("anonymous", 'anonymous@example.com'); $ftp->cwd($path); $ftp->binary; $ftp->get($file) or (warn("$!\n"), return); $ftp->quit; } } elsif (my $ftp = $self->can_run('ftp')) { eval { # no Net::FTP, fallback to ftp.exe require FileHandle; my $fh = FileHandle->new; local $SIG{CHLD} = 'IGNORE'; unless ($fh->open("|$ftp -n")) { warn "Couldn't open ftp: $!\n"; chdir $dir; return; } my @dialog = split(/\n/, <<"END_FTP"); open $host user anonymous anonymous\@example.com cd $path binary get $file $file quit END_FTP foreach (@dialog) { $fh->print("$_\n") } $fh->close; } } else { warn "No working 'ftp' program available!\n"; chdir $dir; return; } unless (-f $file) { warn "Fetching failed: $@\n"; chdir $dir; return; } return if exists $args{size} and -s $file != $args{size}; system($args{run}) if exists $args{run}; unlink($file) if $args{remove}; print(((!exists $args{check_for} or -e $args{check_for}) ? "done!" : "failed! ($!)"), "\n"); chdir $dir; return !$?; } 1; Data-ICal-DateTime-0.82/inc/Module/Install/Makefile.pm0000644000175000017500000002743713145634223021635 0ustar flavioflavio#line 1 package Module::Install::Makefile; use strict 'vars'; use ExtUtils::MakeMaker (); use Module::Install::Base (); use Fcntl qw/:flock :seek/; use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.14'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } sub Makefile { $_[0] } my %seen = (); sub prompt { shift; # Infinite loop protection my @c = caller(); if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) { die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])"; } # In automated testing or non-interactive session, always use defaults if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) { local $ENV{PERL_MM_USE_DEFAULT} = 1; goto &ExtUtils::MakeMaker::prompt; } else { goto &ExtUtils::MakeMaker::prompt; } } # Store a cleaned up version of the MakeMaker version, # since we need to behave differently in a variety of # ways based on the MM version. my $makemaker = eval $ExtUtils::MakeMaker::VERSION; # If we are passed a param, do a "newer than" comparison. # Otherwise, just return the MakeMaker version. sub makemaker { ( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0 } # Ripped from ExtUtils::MakeMaker 6.56, and slightly modified # as we only need to know here whether the attribute is an array # or a hash or something else (which may or may not be appendable). my %makemaker_argtype = ( C => 'ARRAY', CONFIG => 'ARRAY', # CONFIGURE => 'CODE', # ignore DIR => 'ARRAY', DL_FUNCS => 'HASH', DL_VARS => 'ARRAY', EXCLUDE_EXT => 'ARRAY', EXE_FILES => 'ARRAY', FUNCLIST => 'ARRAY', H => 'ARRAY', IMPORTS => 'HASH', INCLUDE_EXT => 'ARRAY', LIBS => 'ARRAY', # ignore '' MAN1PODS => 'HASH', MAN3PODS => 'HASH', META_ADD => 'HASH', META_MERGE => 'HASH', PL_FILES => 'HASH', PM => 'HASH', PMLIBDIRS => 'ARRAY', PMLIBPARENTDIRS => 'ARRAY', PREREQ_PM => 'HASH', CONFIGURE_REQUIRES => 'HASH', SKIP => 'ARRAY', TYPEMAPS => 'ARRAY', XS => 'HASH', # VERSION => ['version',''], # ignore # _KEEP_AFTER_FLUSH => '', clean => 'HASH', depend => 'HASH', dist => 'HASH', dynamic_lib=> 'HASH', linkext => 'HASH', macro => 'HASH', postamble => 'HASH', realclean => 'HASH', test => 'HASH', tool_autosplit => 'HASH', # special cases where you can use makemaker_append CCFLAGS => 'APPENDABLE', DEFINE => 'APPENDABLE', INC => 'APPENDABLE', LDDLFLAGS => 'APPENDABLE', LDFROM => 'APPENDABLE', ); sub makemaker_args { my ($self, %new_args) = @_; my $args = ( $self->{makemaker_args} ||= {} ); foreach my $key (keys %new_args) { if ($makemaker_argtype{$key}) { if ($makemaker_argtype{$key} eq 'ARRAY') { $args->{$key} = [] unless defined $args->{$key}; unless (ref $args->{$key} eq 'ARRAY') { $args->{$key} = [$args->{$key}] } push @{$args->{$key}}, ref $new_args{$key} eq 'ARRAY' ? @{$new_args{$key}} : $new_args{$key}; } elsif ($makemaker_argtype{$key} eq 'HASH') { $args->{$key} = {} unless defined $args->{$key}; foreach my $skey (keys %{ $new_args{$key} }) { $args->{$key}{$skey} = $new_args{$key}{$skey}; } } elsif ($makemaker_argtype{$key} eq 'APPENDABLE') { $self->makemaker_append($key => $new_args{$key}); } } else { if (defined $args->{$key}) { warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n}; } $args->{$key} = $new_args{$key}; } } return $args; } # For mm args that take multiple space-separated args, # append an argument to the current list. sub makemaker_append { my $self = shift; my $name = shift; my $args = $self->makemaker_args; $args->{$name} = defined $args->{$name} ? join( ' ', $args->{$name}, @_ ) : join( ' ', @_ ); } sub build_subdirs { my $self = shift; my $subdirs = $self->makemaker_args->{DIR} ||= []; for my $subdir (@_) { push @$subdirs, $subdir; } } sub clean_files { my $self = shift; my $clean = $self->makemaker_args->{clean} ||= {}; %$clean = ( %$clean, FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_), ); } sub realclean_files { my $self = shift; my $realclean = $self->makemaker_args->{realclean} ||= {}; %$realclean = ( %$realclean, FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_), ); } sub libs { my $self = shift; my $libs = ref $_[0] ? shift : [ shift ]; $self->makemaker_args( LIBS => $libs ); } sub inc { my $self = shift; $self->makemaker_args( INC => shift ); } sub _wanted_t { } sub tests_recursive { my $self = shift; my $dir = shift || 't'; unless ( -d $dir ) { die "tests_recursive dir '$dir' does not exist"; } my %tests = map { $_ => 1 } split / /, ($self->tests || ''); require File::Find; File::Find::find( sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 }, $dir ); $self->tests( join ' ', sort keys %tests ); } sub write { my $self = shift; die "&Makefile->write() takes no arguments\n" if @_; # Check the current Perl version my $perl_version = $self->perl_version; if ( $perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; } # Make sure we have a new enough MakeMaker require ExtUtils::MakeMaker; if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) { # This previous attempted to inherit the version of # ExtUtils::MakeMaker in use by the module author, but this # was found to be untenable as some authors build releases # using future dev versions of EU:MM that nobody else has. # Instead, #toolchain suggests we use 6.59 which is the most # stable version on CPAN at time of writing and is, to quote # ribasushi, "not terminally fucked, > and tested enough". # TODO: We will now need to maintain this over time to push # the version up as new versions are released. $self->build_requires( 'ExtUtils::MakeMaker' => 6.59 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.59 ); } else { # Allow legacy-compatibility with 5.005 by depending on the # most recent EU:MM that supported 5.005. $self->build_requires( 'ExtUtils::MakeMaker' => 6.36 ); $self->configure_requires( 'ExtUtils::MakeMaker' => 6.36 ); } # Generate the MakeMaker params my $args = $self->makemaker_args; $args->{DISTNAME} = $self->name; $args->{NAME} = $self->module_name || $self->name; $args->{NAME} =~ s/-/::/g; $args->{VERSION} = $self->version or die <<'EOT'; ERROR: Can't determine distribution version. Please specify it explicitly via 'version' in Makefile.PL, or set a valid $VERSION in a module, and provide its file path via 'version_from' (or 'all_from' if you prefer) in Makefile.PL. EOT if ( $self->tests ) { my @tests = split ' ', $self->tests; my %seen; $args->{test} = { TESTS => (join ' ', grep {!$seen{$_}++} @tests), }; } elsif ( $Module::Install::ExtraTests::use_extratests ) { # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness. # So, just ignore our xt tests here. } elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) { $args->{test} = { TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ), }; } if ( $] >= 5.005 ) { $args->{ABSTRACT} = $self->abstract; $args->{AUTHOR} = join ', ', @{$self->author || []}; } if ( $self->makemaker(6.10) ) { $args->{NO_META} = 1; #$args->{NO_MYMETA} = 1; } if ( $self->makemaker(6.17) and $self->sign ) { $args->{SIGN} = 1; } unless ( $self->is_admin ) { delete $args->{SIGN}; } if ( $self->makemaker(6.31) and $self->license ) { $args->{LICENSE} = $self->license; } my $prereq = ($args->{PREREQ_PM} ||= {}); %$prereq = ( %$prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->requires) ); # Remove any reference to perl, PREREQ_PM doesn't support it delete $args->{PREREQ_PM}->{perl}; # Merge both kinds of requires into BUILD_REQUIRES my $build_prereq = ($args->{BUILD_REQUIRES} ||= {}); %$build_prereq = ( %$build_prereq, map { @$_ } # flatten [module => version] map { @$_ } grep $_, ($self->configure_requires, $self->build_requires) ); # Remove any reference to perl, BUILD_REQUIRES doesn't support it delete $args->{BUILD_REQUIRES}->{perl}; # Delete bundled dists from prereq_pm, add it to Makefile DIR my $subdirs = ($args->{DIR} || []); if ($self->bundles) { my %processed; foreach my $bundle (@{ $self->bundles }) { my ($mod_name, $dist_dir) = @$bundle; delete $prereq->{$mod_name}; $dist_dir = File::Basename::basename($dist_dir); # dir for building this module if (not exists $processed{$dist_dir}) { if (-d $dist_dir) { # List as sub-directory to be processed by make push @$subdirs, $dist_dir; } # Else do nothing: the module is already present on the system $processed{$dist_dir} = undef; } } } unless ( $self->makemaker('6.55_03') ) { %$prereq = (%$prereq,%$build_prereq); delete $args->{BUILD_REQUIRES}; } if ( my $perl_version = $self->perl_version ) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, " . "but we need version >= $perl_version"; if ( $self->makemaker(6.48) ) { $args->{MIN_PERL_VERSION} = $perl_version; } } if ($self->installdirs) { warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS}; $args->{INSTALLDIRS} = $self->installdirs; } my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_} ) } keys %$args; my $user_preop = delete $args{dist}->{PREOP}; if ( my $preop = $self->admin->preop($user_preop) ) { foreach my $key ( keys %$preop ) { $args{dist}->{$key} = $preop->{$key}; } } my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile'); } sub fix_up_makefile { my $self = shift; my $makefile_name = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; my $preamble = $self->preamble ? "# Preamble by $top_class $top_version\n" . $self->preamble : ''; my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); local *MAKEFILE; open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; eval { flock MAKEFILE, LOCK_EX }; my $makefile = do { local $/; }; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; # Module::Install will never be used to build the Core Perl # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m; #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m; # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well. $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g; # XXX - This is currently unused; not sure if it breaks other MM-users # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg; seek MAKEFILE, 0, SEEK_SET; truncate MAKEFILE, 0; print MAKEFILE "$preamble$makefile$postamble" or die $!; close MAKEFILE or die $!; 1; } sub preamble { my ($self, $text) = @_; $self->{preamble} = $text . $self->{preamble} if defined $text; $self->{preamble}; } sub postamble { my ($self, $text) = @_; $self->{postamble} ||= $self->admin->postamble; $self->{postamble} .= $text if defined $text; $self->{postamble} } 1; __END__ #line 544 Data-ICal-DateTime-0.82/inc/Module/Install/Metadata.pm0000644000175000017500000004330213145634223021625 0ustar flavioflavio#line 1 package Module::Install::Metadata; use strict 'vars'; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.14'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } my @boolean_keys = qw{ sign }; my @scalar_keys = qw{ name module_name abstract version distribution_type tests installdirs }; my @tuple_keys = qw{ configure_requires build_requires requires recommends bundles resources }; my @resource_keys = qw{ homepage bugtracker repository }; my @array_keys = qw{ keywords author }; *authors = \&author; sub Meta { shift } sub Meta_BooleanKeys { @boolean_keys } sub Meta_ScalarKeys { @scalar_keys } sub Meta_TupleKeys { @tuple_keys } sub Meta_ResourceKeys { @resource_keys } sub Meta_ArrayKeys { @array_keys } foreach my $key ( @boolean_keys ) { *$key = sub { my $self = shift; if ( defined wantarray and not @_ ) { return $self->{values}->{$key}; } $self->{values}->{$key} = ( @_ ? $_[0] : 1 ); return $self; }; } foreach my $key ( @scalar_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} = shift; return $self; }; } foreach my $key ( @array_keys ) { *$key = sub { my $self = shift; return $self->{values}->{$key} if defined wantarray and !@_; $self->{values}->{$key} ||= []; push @{$self->{values}->{$key}}, @_; return $self; }; } foreach my $key ( @resource_keys ) { *$key = sub { my $self = shift; unless ( @_ ) { return () unless $self->{values}->{resources}; return map { $_->[1] } grep { $_->[0] eq $key } @{ $self->{values}->{resources} }; } return $self->{values}->{resources}->{$key} unless @_; my $uri = shift or die( "Did not provide a value to $key()" ); $self->resources( $key => $uri ); return 1; }; } foreach my $key ( grep { $_ ne "resources" } @tuple_keys) { *$key = sub { my $self = shift; return $self->{values}->{$key} unless @_; my @added; while ( @_ ) { my $module = shift or last; my $version = shift || 0; push @added, [ $module, $version ]; } push @{ $self->{values}->{$key} }, @added; return map {@$_} @added; }; } # Resource handling my %lc_resource = map { $_ => 1 } qw{ homepage license bugtracker repository }; sub resources { my $self = shift; while ( @_ ) { my $name = shift or last; my $value = shift or next; if ( $name eq lc $name and ! $lc_resource{$name} ) { die("Unsupported reserved lowercase resource '$name'"); } $self->{values}->{resources} ||= []; push @{ $self->{values}->{resources} }, [ $name, $value ]; } $self->{values}->{resources}; } # Aliases for build_requires that will have alternative # meanings in some future version of META.yml. sub test_requires { shift->build_requires(@_) } sub install_requires { shift->build_requires(@_) } # Aliases for installdirs options sub install_as_core { $_[0]->installdirs('perl') } sub install_as_cpan { $_[0]->installdirs('site') } sub install_as_site { $_[0]->installdirs('site') } sub install_as_vendor { $_[0]->installdirs('vendor') } sub dynamic_config { my $self = shift; my $value = @_ ? shift : 1; if ( $self->{values}->{dynamic_config} ) { # Once dynamic we never change to static, for safety return 0; } $self->{values}->{dynamic_config} = $value ? 1 : 0; return 1; } # Convenience command sub static_config { shift->dynamic_config(0); } sub perl_version { my $self = shift; return $self->{values}->{perl_version} unless @_; my $version = shift or die( "Did not provide a value to perl_version()" ); # Normalize the version $version = $self->_perl_version($version); # We don't support the really old versions unless ( $version >= 5.005 ) { die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n"; } $self->{values}->{perl_version} = $version; } sub all_from { my ( $self, $file ) = @_; unless ( defined($file) ) { my $name = $self->name or die( "all_from called with no args without setting name() first" ); $file = join('/', 'lib', split(/-/, $name)) . '.pm'; $file =~ s{.*/}{} unless -e $file; unless ( -e $file ) { die("all_from cannot find $file from $name"); } } unless ( -f $file ) { die("The path '$file' does not exist, or is not a file"); } $self->{values}{all_from} = $file; # Some methods pull from POD instead of code. # If there is a matching .pod, use that instead my $pod = $file; $pod =~ s/\.pm$/.pod/i; $pod = $file unless -e $pod; # Pull the different values $self->name_from($file) unless $self->name; $self->version_from($file) unless $self->version; $self->perl_version_from($file) unless $self->perl_version; $self->author_from($pod) unless @{$self->author || []}; $self->license_from($pod) unless $self->license; $self->abstract_from($pod) unless $self->abstract; return 1; } sub provides { my $self = shift; my $provides = ( $self->{values}->{provides} ||= {} ); %$provides = (%$provides, @_) if @_; return $provides; } sub auto_provides { my $self = shift; return $self unless $self->is_admin; unless (-e 'MANIFEST') { warn "Cannot deduce auto_provides without a MANIFEST, skipping\n"; return $self; } # Avoid spurious warnings as we are not checking manifest here. local $SIG{__WARN__} = sub {1}; require ExtUtils::Manifest; local *ExtUtils::Manifest::manicheck = sub { return }; require Module::Build; my $build = Module::Build->new( dist_name => $self->name, dist_version => $self->version, license => $self->license, ); $self->provides( %{ $build->find_dist_packages || {} } ); } sub feature { my $self = shift; my $name = shift; my $features = ( $self->{values}->{features} ||= [] ); my $mods; if ( @_ == 1 and ref( $_[0] ) ) { # The user used ->feature like ->features by passing in the second # argument as a reference. Accomodate for that. $mods = $_[0]; } else { $mods = \@_; } my $count = 0; push @$features, ( $name => [ map { ref($_) ? ( ref($_) eq 'HASH' ) ? %$_ : @$_ : $_ } @$mods ] ); return @$features; } sub features { my $self = shift; while ( my ( $name, $mods ) = splice( @_, 0, 2 ) ) { $self->feature( $name, @$mods ); } return $self->{values}->{features} ? @{ $self->{values}->{features} } : (); } sub no_index { my $self = shift; my $type = shift; push @{ $self->{values}->{no_index}->{$type} }, @_ if $type; return $self->{values}->{no_index}; } sub read { my $self = shift; $self->include_deps( 'YAML::Tiny', 0 ); require YAML::Tiny; my $data = YAML::Tiny::LoadFile('META.yml'); # Call methods explicitly in case user has already set some values. while ( my ( $key, $value ) = each %$data ) { next unless $self->can($key); if ( ref $value eq 'HASH' ) { while ( my ( $module, $version ) = each %$value ) { $self->can($key)->($self, $module => $version ); } } else { $self->can($key)->($self, $value); } } return $self; } sub write { my $self = shift; return $self unless $self->is_admin; $self->admin->write_meta; return $self; } sub version_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->version( ExtUtils::MM_Unix->parse_version($file) ); # for version integrity check $self->makemaker_args( VERSION_FROM => $file ); } sub abstract_from { require ExtUtils::MM_Unix; my ( $self, $file ) = @_; $self->abstract( bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix' )->parse_abstract($file) ); } # Add both distribution and module name sub name_from { my ($self, $file) = @_; if ( Module::Install::_read($file) =~ m/ ^ \s* package \s* ([\w:]+) [\s|;]* /ixms ) { my ($name, $module_name) = ($1, $1); $name =~ s{::}{-}g; $self->name($name); unless ( $self->module_name ) { $self->module_name($module_name); } } else { die("Cannot determine name from $file\n"); } } sub _extract_perl_version { if ( $_[0] =~ m/ ^\s* (?:use|require) \s* v? ([\d_\.]+) \s* ; /ixms ) { my $perl_version = $1; $perl_version =~ s{_}{}g; return $perl_version; } else { return; } } sub perl_version_from { my $self = shift; my $perl_version=_extract_perl_version(Module::Install::_read($_[0])); if ($perl_version) { $self->perl_version($perl_version); } else { warn "Cannot determine perl version info from $_[0]\n"; return; } } sub author_from { my $self = shift; my $content = Module::Install::_read($_[0]); if ($content =~ m/ =head \d \s+ (?:authors?)\b \s* ([^\n]*) | =head \d \s+ (?:licen[cs]e|licensing|copyright|legal)\b \s* .*? copyright .*? \d\d\d[\d.]+ \s* (?:\bby\b)? \s* ([^\n]*) /ixms) { my $author = $1 || $2; # XXX: ugly but should work anyway... if (eval "require Pod::Escapes; 1") { # Pod::Escapes has a mapping table. # It's in core of perl >= 5.9.3, and should be installed # as one of the Pod::Simple's prereqs, which is a prereq # of Pod::Text 3.x (see also below). $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $Pod::Escapes::Name2character_number{$1} ? chr($Pod::Escapes::Name2character_number{$1}) : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) { # Pod::Text < 3.0 has yet another mapping table, # though the table name of 2.x and 1.x are different. # (1.x is in core of Perl < 5.6, 2.x is in core of # Perl < 5.9.3) my $mapping = ($Pod::Text::VERSION < 2) ? \%Pod::Text::HTML_Escapes : \%Pod::Text::ESCAPES; $author =~ s{ E<( (\d+) | ([A-Za-z]+) )> } { defined $2 ? chr($2) : defined $mapping->{$1} ? $mapping->{$1} : do { warn "Unknown escape: E<$1>"; "E<$1>"; }; }gex; } else { $author =~ s{E}{<}g; $author =~ s{E}{>}g; } $self->author($author); } else { warn "Cannot determine author info from $_[0]\n"; } } #Stolen from M::B my %license_urls = ( perl => 'http://dev.perl.org/licenses/', apache => 'http://apache.org/licenses/LICENSE-2.0', apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1', artistic => 'http://opensource.org/licenses/artistic-license.php', artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php', lgpl => 'http://opensource.org/licenses/lgpl-license.php', lgpl2 => 'http://opensource.org/licenses/lgpl-2.1.php', lgpl3 => 'http://opensource.org/licenses/lgpl-3.0.html', bsd => 'http://opensource.org/licenses/bsd-license.php', gpl => 'http://opensource.org/licenses/gpl-license.php', gpl2 => 'http://opensource.org/licenses/gpl-2.0.php', gpl3 => 'http://opensource.org/licenses/gpl-3.0.html', mit => 'http://opensource.org/licenses/mit-license.php', mozilla => 'http://opensource.org/licenses/mozilla1.1.php', open_source => undef, unrestricted => undef, restrictive => undef, unknown => undef, ); sub license { my $self = shift; return $self->{values}->{license} unless @_; my $license = shift or die( 'Did not provide a value to license()' ); $license = __extract_license($license) || lc $license; $self->{values}->{license} = $license; # Automatically fill in license URLs if ( $license_urls{$license} ) { $self->resources( license => $license_urls{$license} ); } return 1; } sub _extract_license { my $pod = shift; my $matched; return __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ L(?i:ICEN[CS]E|ICENSING)\b.*?) (=head \d.*|=cut.*|)\z /xms ) || __extract_license( ($matched) = $pod =~ m/ (=head \d \s+ (?:C(?i:OPYRIGHTS?)|L(?i:EGAL))\b.*?) (=head \d.*|=cut.*|)\z /xms ); } sub __extract_license { my $license_text = shift or return; my @phrases = ( '(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1, '(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1, 'Artistic and GPL' => 'perl', 1, 'GNU general public license' => 'gpl', 1, 'GNU public license' => 'gpl', 1, 'GNU lesser general public license' => 'lgpl', 1, 'GNU lesser public license' => 'lgpl', 1, 'GNU library general public license' => 'lgpl', 1, 'GNU library public license' => 'lgpl', 1, 'GNU Free Documentation license' => 'unrestricted', 1, 'GNU Affero General Public License' => 'open_source', 1, '(?:Free)?BSD license' => 'bsd', 1, 'Artistic license 2\.0' => 'artistic_2', 1, 'Artistic license' => 'artistic', 1, 'Apache (?:Software )?license' => 'apache', 1, 'GPL' => 'gpl', 1, 'LGPL' => 'lgpl', 1, 'BSD' => 'bsd', 1, 'Artistic' => 'artistic', 1, 'MIT' => 'mit', 1, 'Mozilla Public License' => 'mozilla', 1, 'Q Public License' => 'open_source', 1, 'OpenSSL License' => 'unrestricted', 1, 'SSLeay License' => 'unrestricted', 1, 'zlib License' => 'open_source', 1, 'proprietary' => 'proprietary', 0, ); while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) { $pattern =~ s#\s+#\\s+#gs; if ( $license_text =~ /\b$pattern\b/i ) { return $license; } } return ''; } sub license_from { my $self = shift; if (my $license=_extract_license(Module::Install::_read($_[0]))) { $self->license($license); } else { warn "Cannot determine license info from $_[0]\n"; return 'unknown'; } } sub _extract_bugtracker { my @links = $_[0] =~ m#L<( https?\Q://rt.cpan.org/\E[^>]+| https?\Q://github.com/\E[\w_]+/[\w_]+/issues| https?\Q://code.google.com/p/\E[\w_\-]+/issues/list )>#gx; my %links; @links{@links}=(); @links=keys %links; return @links; } sub bugtracker_from { my $self = shift; my $content = Module::Install::_read($_[0]); my @links = _extract_bugtracker($content); unless ( @links ) { warn "Cannot determine bugtracker info from $_[0]\n"; return 0; } if ( @links > 1 ) { warn "Found more than one bugtracker link in $_[0]\n"; return 0; } # Set the bugtracker bugtracker( $links[0] ); return 1; } sub requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+(v?[\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->requires( $module => $version ); } } sub test_requires_from { my $self = shift; my $content = Module::Install::_readperl($_[0]); my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; while ( @requires ) { my $module = shift @requires; my $version = shift @requires; $self->test_requires( $module => $version ); } } # Convert triple-part versions (eg, 5.6.1 or 5.8.9) to # numbers (eg, 5.006001 or 5.008009). # Also, convert double-part versions (eg, 5.8) sub _perl_version { my $v = $_[-1]; $v =~ s/^([1-9])\.([1-9]\d?\d?)$/sprintf("%d.%03d",$1,$2)/e; $v =~ s/^([1-9])\.([1-9]\d?\d?)\.(0|[1-9]\d?\d?)$/sprintf("%d.%03d%03d",$1,$2,$3 || 0)/e; $v =~ s/(\.\d\d\d)000$/$1/; $v =~ s/_.+$//; if ( ref($v) ) { # Numify $v = $v + 0; } return $v; } sub add_metadata { my $self = shift; my %hash = @_; for my $key (keys %hash) { warn "add_metadata: $key is not prefixed with 'x_'.\n" . "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/; $self->{values}->{$key} = $hash{$key}; } } ###################################################################### # MYMETA Support sub WriteMyMeta { die "WriteMyMeta has been deprecated"; } sub write_mymeta_yaml { my $self = shift; # We need YAML::Tiny to write the MYMETA.yml file unless ( eval { require YAML::Tiny; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.yml\n"; YAML::Tiny::DumpFile('MYMETA.yml', $meta); } sub write_mymeta_json { my $self = shift; # We need JSON to write the MYMETA.json file unless ( eval { require JSON; 1; } ) { return 1; } # Generate the data my $meta = $self->_write_mymeta_data or return 1; # Save as the MYMETA.yml file print "Writing MYMETA.json\n"; Module::Install::_write( 'MYMETA.json', JSON->new->pretty(1)->canonical->encode($meta), ); } sub _write_mymeta_data { my $self = shift; # If there's no existing META.yml there is nothing we can do return undef unless -f 'META.yml'; # We need Parse::CPAN::Meta to load the file unless ( eval { require Parse::CPAN::Meta; 1; } ) { return undef; } # Merge the perl version into the dependencies my $val = $self->Meta->{values}; my $perl = delete $val->{perl_version}; if ( $perl ) { $val->{requires} ||= []; my $requires = $val->{requires}; # Canonize to three-dot version after Perl 5.6 if ( $perl >= 5.006 ) { $perl =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2||0), int($3||0))}e } unshift @$requires, [ perl => $perl ]; } # Load the advisory META.yml file my @yaml = Parse::CPAN::Meta::LoadFile('META.yml'); my $meta = $yaml[0]; # Overwrite the non-configure dependency hashes delete $meta->{requires}; delete $meta->{build_requires}; delete $meta->{recommends}; if ( exists $val->{requires} ) { $meta->{requires} = { map { @$_ } @{ $val->{requires} } }; } if ( exists $val->{build_requires} ) { $meta->{build_requires} = { map { @$_ } @{ $val->{build_requires} } }; } return $meta; } 1; Data-ICal-DateTime-0.82/inc/Module/Install/Can.pm0000644000175000017500000000615713145634223020615 0ustar flavioflavio#line 1 package Module::Install::Can; use strict; use Config (); use ExtUtils::MakeMaker (); use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.14'; @ISA = 'Module::Install::Base'; $ISCORE = 1; } # check if we can load some module ### Upgrade this to not have to load the module if possible sub can_use { my ($self, $mod, $ver) = @_; $mod =~ s{::|\\}{/}g; $mod .= '.pm' unless $mod =~ /\.pm$/i; my $pkg = $mod; $pkg =~ s{/}{::}g; $pkg =~ s{\.pm$}{}i; local $@; eval { require $mod; $pkg->VERSION($ver || 0); 1 }; } # Check if we can run some command sub can_run { my ($self, $cmd) = @_; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { next if $dir eq ''; require File::Spec; my $abs = File::Spec->catfile($dir, $cmd); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } # Can our C compiler environment build XS files sub can_xs { my $self = shift; # Ensure we have the CBuilder module $self->configure_requires( 'ExtUtils::CBuilder' => 0.27 ); # Do we have the configure_requires checker? local $@; eval "require ExtUtils::CBuilder;"; if ( $@ ) { # They don't obey configure_requires, so it is # someone old and delicate. Try to avoid hurting # them by falling back to an older simpler test. return $self->can_cc(); } # Do we have a working C compiler my $builder = ExtUtils::CBuilder->new( quiet => 1, ); unless ( $builder->have_compiler ) { # No working C compiler return 0; } # Write a C file representative of what XS becomes require File::Temp; my ( $FH, $tmpfile ) = File::Temp::tempfile( "compilexs-XXXXX", SUFFIX => '.c', ); binmode $FH; print $FH <<'END_C'; #include "EXTERN.h" #include "perl.h" #include "XSUB.h" int main(int argc, char **argv) { return 0; } int boot_sanexs() { return 1; } END_C close $FH; # Can the C compiler access the same headers XS does my @libs = (); my $object = undef; eval { local $^W = 0; $object = $builder->compile( source => $tmpfile, ); @libs = $builder->link( objects => $object, module_name => 'sanexs', ); }; my $result = $@ ? 0 : 1; # Clean up all the build files foreach ( $tmpfile, $object, @libs ) { next unless defined $_; 1 while unlink; } return $result; } # Can we locate a (the) C compiler sub can_cc { my $self = shift; my @chunks = split(/ /, $Config::Config{cc}) or return; # $Config{cc} may contain args; try to find out the program part while (@chunks) { return $self->can_run("@chunks") || (pop(@chunks), next); } return; } # Fix Cygwin bug on maybe_command(); if ( $^O eq 'cygwin' ) { require ExtUtils::MM_Cygwin; require ExtUtils::MM_Win32; if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) { *ExtUtils::MM_Cygwin::maybe_command = sub { my ($self, $file) = @_; if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) { ExtUtils::MM_Win32->maybe_command($file); } else { ExtUtils::MM_Unix->maybe_command($file); } } } } 1; __END__ #line 236 Data-ICal-DateTime-0.82/inc/Module/Install/WriteAll.pm0000644000175000017500000000237613145634223021636 0ustar flavioflavio#line 1 package Module::Install::WriteAll; use strict; use Module::Install::Base (); use vars qw{$VERSION @ISA $ISCORE}; BEGIN { $VERSION = '1.14'; @ISA = qw{Module::Install::Base}; $ISCORE = 1; } sub WriteAll { my $self = shift; my %args = ( meta => 1, sign => 0, inline => 0, check_nmake => 1, @_, ); $self->sign(1) if $args{sign}; $self->admin->WriteAll(%args) if $self->is_admin; $self->check_nmake if $args{check_nmake}; unless ( $self->makemaker_args->{PL_FILES} ) { # XXX: This still may be a bit over-defensive... unless ($self->makemaker(6.25)) { $self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL'; } } # Until ExtUtils::MakeMaker support MYMETA.yml, make sure # we clean it up properly ourself. $self->realclean_files('MYMETA.yml'); if ( $args{inline} ) { $self->Inline->write; } else { $self->Makefile->write; } # The Makefile write process adds a couple of dependencies, # so write the META.yml files after the Makefile. if ( $args{meta} ) { $self->Meta->write; } # Experimental support for MYMETA if ( $ENV{X_MYMETA} ) { if ( $ENV{X_MYMETA} eq 'JSON' ) { $self->Meta->write_mymeta_json; } else { $self->Meta->write_mymeta_yaml; } } return 1; } 1; Data-ICal-DateTime-0.82/inc/Module/Install.pm0000644000175000017500000003021713145634223020106 0ustar flavioflavio#line 1 package Module::Install; # For any maintainers: # The load order for Module::Install is a bit magic. # It goes something like this... # # IF ( host has Module::Install installed, creating author mode ) { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install # 3. The installed version of inc::Module::Install loads # 4. inc::Module::Install calls "require Module::Install" # 5. The ./inc/ version of Module::Install loads # } ELSE { # 1. Makefile.PL calls "use inc::Module::Install" # 2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install # 3. The ./inc/ version of Module::Install loads # } use 5.006; use strict 'vars'; use Cwd (); use File::Find (); use File::Path (); use vars qw{$VERSION $MAIN}; BEGIN { # All Module::Install core packages now require synchronised versions. # This will be used to ensure we don't accidentally load old or # different versions of modules. # This is not enforced yet, but will be some time in the next few # releases once we can make sure it won't clash with custom # Module::Install extensions. $VERSION = '1.14'; # Storage for the pseudo-singleton $MAIN = undef; *inc::Module::Install::VERSION = *VERSION; @inc::Module::Install::ISA = __PACKAGE__; } sub import { my $class = shift; my $self = $class->new(@_); my $who = $self->_caller; #------------------------------------------------------------- # all of the following checks should be included in import(), # to allow "eval 'require Module::Install; 1' to test # installation of Module::Install. (RT #51267) #------------------------------------------------------------- # Whether or not inc::Module::Install is actually loaded, the # $INC{inc/Module/Install.pm} is what will still get set as long as # the caller loaded module this in the documented manner. # If not set, the caller may NOT have loaded the bundled version, and thus # they may not have a MI version that works with the Makefile.PL. This would # result in false errors or unexpected behaviour. And we don't want that. my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm'; unless ( $INC{$file} ) { die <<"END_DIE" } Please invoke ${\__PACKAGE__} with: use inc::${\__PACKAGE__}; not: use ${\__PACKAGE__}; END_DIE # This reportedly fixes a rare Win32 UTC file time issue, but # as this is a non-cross-platform XS module not in the core, # we shouldn't really depend on it. See RT #24194 for detail. # (Also, this module only supports Perl 5.6 and above). eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006; # If the script that is loading Module::Install is from the future, # then make will detect this and cause it to re-run over and over # again. This is bad. Rather than taking action to touch it (which # is unreliable on some platforms and requires write permissions) # for now we should catch this and refuse to run. if ( -f $0 ) { my $s = (stat($0))[9]; # If the modification time is only slightly in the future, # sleep briefly to remove the problem. my $a = $s - time; if ( $a > 0 and $a < 5 ) { sleep 5 } # Too far in the future, throw an error. my $t = time; if ( $s > $t ) { die <<"END_DIE" } Your installer $0 has a modification time in the future ($s > $t). This is known to create infinite loops in make. Please correct this, then run $0 again. END_DIE } # Build.PL was formerly supported, but no longer is due to excessive # difficulty in implementing every single feature twice. if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" } Module::Install no longer supports Build.PL. It was impossible to maintain duel backends, and has been deprecated. Please remove all Build.PL files and only use the Makefile.PL installer. END_DIE #------------------------------------------------------------- # To save some more typing in Module::Install installers, every... # use inc::Module::Install # ...also acts as an implicit use strict. $^H |= strict::bits(qw(refs subs vars)); #------------------------------------------------------------- unless ( -f $self->{file} ) { foreach my $key (keys %INC) { delete $INC{$key} if $key =~ /Module\/Install/; } local $^W; require "$self->{path}/$self->{dispatch}.pm"; File::Path::mkpath("$self->{prefix}/$self->{author}"); $self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self ); $self->{admin}->init; @_ = ($class, _self => $self); goto &{"$self->{name}::import"}; } local $^W; *{"${who}::AUTOLOAD"} = $self->autoload; $self->preload; # Unregister loader and worker packages so subdirs can use them again delete $INC{'inc/Module/Install.pm'}; delete $INC{'Module/Install.pm'}; # Save to the singleton $MAIN = $self; return 1; } sub autoload { my $self = shift; my $who = $self->_caller; my $cwd = Cwd::getcwd(); my $sym = "${who}::AUTOLOAD"; $sym->{$cwd} = sub { my $pwd = Cwd::getcwd(); if ( my $code = $sym->{$pwd} ) { # Delegate back to parent dirs goto &$code unless $cwd eq $pwd; } unless ($$sym =~ s/([^:]+)$//) { # XXX: it looks like we can't retrieve the missing function # via $$sym (usually $main::AUTOLOAD) in this case. # I'm still wondering if we should slurp Makefile.PL to # get some context or not ... my ($package, $file, $line) = caller; die <<"EOT"; Unknown function is found at $file line $line. Execution of $file aborted due to runtime errors. If you're a contributor to a project, you may need to install some Module::Install extensions from CPAN (or other repository). If you're a user of a module, please contact the author. EOT } my $method = $1; if ( uc($method) eq $method ) { # Do nothing return; } elsif ( $method =~ /^_/ and $self->can($method) ) { # Dispatch to the root M:I class return $self->$method(@_); } # Dispatch to the appropriate plugin unshift @_, ( $self, $1 ); goto &{$self->can('call')}; }; } sub preload { my $self = shift; unless ( $self->{extensions} ) { $self->load_extensions( "$self->{prefix}/$self->{path}", $self ); } my @exts = @{$self->{extensions}}; unless ( @exts ) { @exts = $self->{admin}->load_all_extensions; } my %seen; foreach my $obj ( @exts ) { while (my ($method, $glob) = each %{ref($obj) . '::'}) { next unless $obj->can($method); next if $method =~ /^_/; next if $method eq uc($method); $seen{$method}++; } } my $who = $self->_caller; foreach my $name ( sort keys %seen ) { local $^W; *{"${who}::$name"} = sub { ${"${who}::AUTOLOAD"} = "${who}::$name"; goto &{"${who}::AUTOLOAD"}; }; } } sub new { my ($class, %args) = @_; delete $INC{'FindBin.pm'}; { # to suppress the redefine warning local $SIG{__WARN__} = sub {}; require FindBin; } # ignore the prefix on extension modules built from top level. my $base_path = Cwd::abs_path($FindBin::Bin); unless ( Cwd::abs_path(Cwd::getcwd()) eq $base_path ) { delete $args{prefix}; } return $args{_self} if $args{_self}; $args{dispatch} ||= 'Admin'; $args{prefix} ||= 'inc'; $args{author} ||= ($^O eq 'VMS' ? '_author' : '.author'); $args{bundle} ||= 'inc/BUNDLES'; $args{base} ||= $base_path; $class =~ s/^\Q$args{prefix}\E:://; $args{name} ||= $class; $args{version} ||= $class->VERSION; unless ( $args{path} ) { $args{path} = $args{name}; $args{path} =~ s!::!/!g; } $args{file} ||= "$args{base}/$args{prefix}/$args{path}.pm"; $args{wrote} = 0; bless( \%args, $class ); } sub call { my ($self, $method) = @_; my $obj = $self->load($method) or return; splice(@_, 0, 2, $obj); goto &{$obj->can($method)}; } sub load { my ($self, $method) = @_; $self->load_extensions( "$self->{prefix}/$self->{path}", $self ) unless $self->{extensions}; foreach my $obj (@{$self->{extensions}}) { return $obj if $obj->can($method); } my $admin = $self->{admin} or die <<"END_DIE"; The '$method' method does not exist in the '$self->{prefix}' path! Please remove the '$self->{prefix}' directory and run $0 again to load it. END_DIE my $obj = $admin->load($method, 1); push @{$self->{extensions}}, $obj; $obj; } sub load_extensions { my ($self, $path, $top) = @_; my $should_reload = 0; unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) { unshift @INC, $self->{prefix}; $should_reload = 1; } foreach my $rv ( $self->find_extensions($path) ) { my ($file, $pkg) = @{$rv}; next if $self->{pathnames}{$pkg}; local $@; my $new = eval { local $^W; require $file; $pkg->can('new') }; unless ( $new ) { warn $@ if $@; next; } $self->{pathnames}{$pkg} = $should_reload ? delete $INC{$file} : $INC{$file}; push @{$self->{extensions}}, &{$new}($pkg, _top => $top ); } $self->{extensions} ||= []; } sub find_extensions { my ($self, $path) = @_; my @found; File::Find::find( sub { my $file = $File::Find::name; return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is; my $subpath = $1; return if lc($subpath) eq lc($self->{dispatch}); $file = "$self->{path}/$subpath.pm"; my $pkg = "$self->{name}::$subpath"; $pkg =~ s!/!::!g; # If we have a mixed-case package name, assume case has been preserved # correctly. Otherwise, root through the file to locate the case-preserved # version of the package name. if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) { my $content = Module::Install::_read($subpath . '.pm'); my $in_pod = 0; foreach ( split /\n/, $content ) { $in_pod = 1 if /^=\w/; $in_pod = 0 if /^=cut/; next if ($in_pod || /^=cut/); # skip pod text next if /^\s*#/; # and comments if ( m/^\s*package\s+($pkg)\s*;/i ) { $pkg = $1; last; } } } push @found, [ $file, $pkg ]; }, $path ) if -d $path; @found; } ##################################################################### # Common Utility Functions sub _caller { my $depth = 0; my $call = caller($depth); while ( $call eq __PACKAGE__ ) { $depth++; $call = caller($depth); } return $call; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _read { local *FH; open( FH, '<', $_[0] ) or die "open($_[0]): $!"; binmode FH; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_NEW sub _read { local *FH; open( FH, "< $_[0]" ) or die "open($_[0]): $!"; binmode FH; my $string = do { local $/; }; close FH or die "close($_[0]): $!"; return $string; } END_OLD sub _readperl { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; $string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s; $string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg; return $string; } sub _readpod { my $string = Module::Install::_read($_[0]); $string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg; return $string if $_[0] =~ /\.pod\z/; $string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg; $string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg; $string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg; $string =~ s/^\n+//s; return $string; } # Done in evals to avoid confusing Perl::MinimumVersion eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@; sub _write { local *FH; open( FH, '>', $_[0] ) or die "open($_[0]): $!"; binmode FH; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_NEW sub _write { local *FH; open( FH, "> $_[0]" ) or die "open($_[0]): $!"; binmode FH; foreach ( 1 .. $#_ ) { print FH $_[$_] or die "print($_[0]): $!"; } close FH or die "close($_[0]): $!"; } END_OLD # _version is for processing module versions (eg, 1.03_05) not # Perl versions (eg, 5.8.1). sub _version { my $s = shift || 0; my $d =()= $s =~ /(\.)/g; if ( $d >= 2 ) { # Normalise multipart versions $s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg; } $s =~ s/^(\d+)\.?//; my $l = $1 || 0; my @v = map { $_ . '0' x (3 - length $_) } $s =~ /(\d{1,3})\D?/g; $l = $l . '.' . join '', @v if @v; return $l + 0; } sub _cmp { _version($_[1]) <=> _version($_[2]); } # Cloned from Params::Util::_CLASS sub _CLASS { ( defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s ) ? $_[0] : undef; } 1; # Copyright 2008 - 2012 Adam Kennedy. Data-ICal-DateTime-0.82/lib/0000755000175000017500000000000013146616577014724 5ustar flavioflavioData-ICal-DateTime-0.82/lib/Data/0000755000175000017500000000000013146616577015575 5ustar flavioflavioData-ICal-DateTime-0.82/lib/Data/ICal/0000755000175000017500000000000013146616577016405 5ustar flavioflavioData-ICal-DateTime-0.82/lib/Data/ICal/DateTime.pm0000644000175000017500000005264513146616157020445 0ustar flavioflaviopackage Data::ICal::DateTime; use strict; use Clone; use Data::ICal; use DateTime::Set; use DateTime::Format::ICal; our $VERSION = '0.82'; # mmm, mixin goodness sub import { my $class = shift; no strict 'refs'; no warnings 'redefine'; *Data::ICal::events = \&events; *Data::ICal::collapse = \&collapse; foreach my $sub (qw(start end duration period summary description original all_day floating recurrence recurrence_id rdate exrule exdate uid url _simple_property _rule_set _date_set explode is_in _normalise split_up _escape _unescape _make_dt_param)) { *{"Data::ICal::Entry::Event::$sub"} = \&$sub; } push @Data::ICal::Entry::Event::ISA, 'Clone'; } =head1 NAME Data::ICal::DateTime - convenience methods for using Data::ICal with DateTime =head1 SYNPOSIS # performs mixin voodoo use Data::ICal::DateTime; my $cal = Data::ICal->new( filename => 'example.ics'); my $date1 = DateTime->new( year => 2005, month => 7, day => 01 ); my $date2 = DateTime->new( year => 2005, month => 7, day => 07 ); my $span = DateTime::Span->from_datetimes( start => $date1, end => $date2 ); my @events = $cal->events(); # all VEVENTS my @week = $cal->events($span); # just in that week my @week = $cal->events($span,'day');# explode long events into days my $event = Data::ICal::Entry::Event->new(); $event->start($start); # $start is a DateTime object $event->end($end); # so is $end $event->all_day # is this an all day event $event->duration($duration); # $duration is DateTime::Duration $event->recurrence($recurrence); # $reccurence is a DateTime list, # a DateTime::Span list, # a DateTime::Set, # or a DateTime::SpanSet $event->start; # returns a DateTime object $event->end; # ditto $event->duration; # returns a DateTime::Duration $event->recurrence; # returns a DateTime::Set $event->period; # returns a DateTime::Span object $event->rdate; # returns a DateTime::Set $event->exrule; # returns a DateTime::Set $event->exdate; # returns a DateTime::Set $event->explode($span); # returns an array of sub events # (if this is recurring); $event->explode($span,'week'); # if any events are longer than a # week then split them up $event->is_in($span); # whether this event falls within a # Set, Span, or SetSpan $cal->add_entry($event); methods =head1 DESCRIPTION =head1 METHODS =cut =head2 events [span] [period] Provides a L object with a method to return all events. If a L, L or L object is passed then only the events that occur within that set will be returned including expansion of all recurring events. All events will be normalised to have a dtstart and dtend rather than any other method of determining their start and stop time. Additionally you can pass a period string which can be one of the following year month week day hour minute second This will explode an event into as many sub events as needed e.g a period of 'day' will explode a 2-day event into 2 one day events with the second starting just after the first =cut sub events { my $self = shift; my $set = shift; my $period = shift; my @events = grep { $_->ical_entry_type eq 'VEVENT' } @{$self->entries}; # NOTE: this won't normalise events return @events if (!$set); @events = map { $_->explode($set) } @events; @events = $self->collapse(@events); return @events unless defined $period; return map { $_->split_up($period) } @events; } =head2 collapse Provides a L object with a method to collapse Cs. Given a list of events, some of which might have Cs, return a list of events with all recurrences within C and all Cs handled correctly. Used internally by C. =cut sub collapse { my ($self, @events) = @_; my %rid; my @recurs; for (@events) { my $uid = $_->uid; # TODO: this feels very hacky $uid = rand().{}.time unless defined $uid; $_->uid($uid); if ($_->recurrence_id) { push @recurs, $_; } else { push @{$rid{$uid}}, $_; } } foreach my $e (@recurs) { my $uid = $e->uid; for (@{$rid{$uid}}) { next unless $_->start == $e->recurrence_id; # TODO: does this need to merge fields? $_ = $e; } } @events = (); push @events, @{$rid{$_}} for keys %rid; return @events; } =head2 start [new] Returns a L object representing the start time of this event. May return undef. If passed a L object will set that to be the new start time. =cut sub _make_dt_param { my $self = shift; my $dt = shift; my $tmp = $dt->clone->set_time_zone('floating'); my $new = DateTime::Format::ICal->format_datetime($tmp); return [ $new, { TZID => $dt->time_zone_long_name } ]; } sub start { my $self = shift; my $new = shift; if ($new) { delete $self->{properties}->{dtstart}; $self->add_property(dtstart => $self->_make_dt_param($new)); } my $dtstart = $self->property('dtstart') || return undef; my $ret = DateTime::Format::ICal->parse_datetime($dtstart->[0]->value); eval { $ret->set_time_zone($dtstart->[0]->parameters->{TZID}) } if $dtstart->[0]->parameters->{TZID}; return $ret; } =head2 end Returns a L object representing the end time of this event. May return undef. If passed a L object will set that to be the new end time. =cut sub end { my $self = shift; my $new = shift; # iCal represents all-day events by using ;VALUE=DATE # and setting DTEND=end_date + 1 my $all_day = $self->all_day; if ($new) { delete $self->{properties}->{dtend}; my $update = $new->clone; if ($all_day) { $update->add( days => 1); $update->set( hour => 0, minute => 0, second => 0 ); } $self->add_property( dtend => $self->_make_dt_param($update) ); $self->property('dtend')->[0]->parameters->{VALUE} = 'DATE' if $all_day; } my $dtend = $self->property('dtend') || return undef; my $ret = DateTime::Format::ICal->parse_datetime($dtend->[0]->value); eval { $ret->set_time_zone($dtend->[0]->parameters->{TZID}) } if ($dtend->[0]->parameters->{TZID}); $ret->truncate(to => 'day' )->subtract( nanoseconds => 1 ) if $all_day; return $ret; } =head2 all_day Returns 1 if event is all day or 0 if not. If no end has been set and 1 is passed then will set end to be a nanosecond before midnight the next day. The have multi-day all-day events simply set the end time to be nanosecond before midnight on the last day of the event. =cut sub all_day { my $self = shift; my $new = shift; # TODO - should be able to make all day with just the start my $dtend = $self->property('dtend'); if (!$dtend) { return 0 unless $new; $dtend = $self->start->clone->add( days => 1 )->truncate(to => 'day' )->subtract( nanoseconds => 1 ); $self->end($dtend); $dtend = $self->property('dtend'); } my $cur = (defined $dtend && defined $dtend->[0]->parameters->{VALUE} && $dtend->[0]->parameters->{VALUE} eq 'DATE') || 0; if (defined $new && $new != $cur) { my $end = $self->end; if ($new == 0) { delete $self->property('dtend')->[0]->parameters->{VALUE}; } else { $self->property('dtend')->[0]->parameters->{VALUE} = 'DATE'; } $self->end($end); $cur = $new; } return $cur; } =head2 floating An event is considered floating if it has a start but no end. It is intended to represent an event that is associated with a given calendar date and time of day, such as an anniversary and should not be considered as taking up any amount of time. Returns 1 if the evnt is floating and 0 if it isn't. If passed a 1 then will set the event to be floating by deleting the end time. If passed a 0 and no end is currently set then it will set end to be a nanosecond before midnight the next day. =cut sub floating { my $self = shift; my $new = shift; my $end = $self->end; my $cur = (defined $end)? 0 : 1; if (defined $new && $new != $cur) { # it is floating - delete the end if ($new) { delete $self->{properties}->{dtend}; # it's not floating - simulate end as 1 nanosecond before midnight after the start } else { my $dtend = $self->start->clone->add( days => 1 )->truncate(to => 'day' )->subtract( nanoseconds => 1 ); $self->end($dtend); } $cur = $new; } return $cur; } =head2 duration Returns a L object representing the duration of this event. May return undef. If passed a L object will set that to be the new duration. =cut sub duration { my $self = shift; my $new = shift; if ($new) { delete $self->{properties}->{duration}; $self->add_property( duration => DateTime::Format::ICal->format_duration($new) ); } my $duration = $self->property('duration') || return undef; return DateTime::Format::ICal->parse_duration($duration->[0]->value); } =head2 period Returns a L object representing the period of this event. May return undef. If passed a L object will set that to be the new period. =cut sub period { my $self = shift; my $new = shift; if ($new) { delete $self->{properties}->{period}; $self->add_property( period => DateTime::Format::ICal->format_period($new) ); } my $period = $self->property('period') || return undef; my $ret = DateTime::Format::ICal->parse_period($period->[0]->value); # $ret->set_time_zone($period->[0]->parameters->{TZID}) if ($period->[0]->parameters->{TZID}); return $ret; } =head2 recurrence Returns a L object representing the union of all the Cs in this object. May return undef. If passed one or more L lists, L lists, Ls, or Ls then set the recurrence rules to be those. =cut sub recurrence { my $self = shift; return $self->_rule_set('rrule', @_); } =head2 rdate Returns a L object representing the set of all Cs in the object. May return undef. =cut sub rdate { my $self = shift; return $self->_date_set('rdate', @_); } =head2 exrule Returns a L object representing the union of all the Cs in this object. May return undef. If passed one or more L lists, L lists, Ls, or Ls then set the recurrence exclusion rules to be those. =cut sub exrule { my $self = shift; return $self->_rule_set('exrule', @_); } =head2 exdate Returns a L object representing the set of all Cs in the object. May return undef. =cut sub exdate { my $self = shift; return $self->_date_set('exdate', @_); } sub _date_set { my $self = shift; my $name = shift; $self->property($name) || return undef; my @dates; for (@{ $self->property($name) }) { foreach my $bit (split /,/, $_->value) { my $date = DateTime::Format::ICal->parse_datetime($bit); # $date->set_time_zone($_->parameters->{TZID}) if $_->parameters->{TZID}; push @dates, $date; } } return DateTime::Set->from_datetimes( dates => \@dates ); } sub _rule_set { my $self = shift; my $name = shift; if (@_) { delete $self->{properties}->{$name}; foreach my $rule (DateTime::Format::ICal->format_recurrence(@_)) { #$rule =~ s!^$name:!!i; $rule =~ s!^[^:]+:!!; $self->add_properties( $name => $rule ); } } my @recurrence; my $start = $self->start || return undef; #my $tz = $start->time_zone; $start = $start->clone; #$start->set_time_zone("floating"); my $set = DateTime::Set->empty_set; $self->property($name) || return undef; for (@{ $self->property($name) }) { my $recur = DateTime::Format::ICal->parse_recurrence(recurrence => $_->value, dtstart => $start); # $recur->set_time_zone($_->parameters->{TZID}) if $_->parameters->{TZID}; $recur->set_time_zone($start->time_zone) if !$start->time_zone->is_floating; $set = $set->union($recur); } # $set->set_time_zone($tz); return $set; } =head2 recurrence_id Returns a L object representing the recurrence-id of this event. May return undef. If passed a L object will set that to be the new recurrence-id. =cut sub recurrence_id { my $self = shift; my $new = shift; if ($new) { delete $self->{properties}->{'recurrence-id'}; $self->add_property('recurrence-id' => DateTime::Format::ICal->format_datetime($new)); } my $rid = $self->property('recurrence-id') || return undef; my $ret = DateTime::Format::ICal->parse_datetime($rid->[0]->value); # $ret->set_time_zone($rid->[0]->parameters->{TZID}) if $rid->[0]->parameters->{TZID}; return $ret; } sub _simple_property { my $self = shift; my $name = shift; my $val = shift; if ($val) { delete $self->{properties}->{$name}; $self->add_property( $name => $val ); } $val = $self->property($name) || return undef; return $val->[0]->value; } =head2 uid Returns the uid of this event. If passed a new value then sets that to be the new uid value. =cut sub uid { my $self = shift; return $self->_simple_property('uid', @_); } =head2 summary Returns a string representing the summary of this event. May return undef. If passed a new value then sets that to be the new summary (and will escape all relevant characters). =cut sub summary { my $self = shift; return $self->_simple_property('summary', @_); } =head2 description Returns a string representing the description of this event. May return undef. If passed a new value then sets that to be the new description (and will escape all relevant characters). =cut sub description { my $self = shift; return $self->_simple_property('description', @_); } =head2 url Returns a string representing the url of this event. May return undef. If passed a new value then sets that to be the new description (and will escape all relevant characters). =cut sub url { my $self = shift; return $self->_simple_property('url', @_); } sub _escape { my $string = shift; $string =~ s!(\\|,|;)!\\$1!mg; $string =~ s!\x0a!\\n!mg; return $string; } sub _unescape { my $string = shift; $string =~ s!\\n!\x0a!gm; $string =~ s!(\\\\|\\,|\\;)!substr($1,-1)!gem; return $string; } =head2 explode [period] Takes L, L or L and returns an array of events. If this is not a recurring event, and it falls with the span, then it will return one event with the dtstart and dtend properties set and no other time information. If this is a recurring event then it will return all times that this recurs within the span. All returned events will have the dtstart and dtend properties set and no other time information. If C is optionally passed then events longer than C will be exploded into multiple events. C can be any of the following year month week day hour minute second =cut # this is quite heavily based on 'wgo' in the bin/ directory of Text::vFile::asData sub explode { my $self = shift; my $span = shift; my $period = shift; my %e = $self->_normalise; my @events; if (! $e{recur} && $e{span}->intersects($span) ) { my $event = $self->clone(); delete $event->{properties}->{$_} for qw(rrule exrule rdate exdate duration period); $event->start($e{start}); $event->end($e{end}); push @events, $event; } if($e{recur} && $e{recur}->intersects($span)) { my $int_set = $e{recur}->intersection($span); # Change the event's recurrence details so that only the events # inside the time span we're interested in are listed. $e{recur} = $int_set; my $it = $e{recur}->iterator; while(my $dt = $it->next()) { next if $e{exrule} && $e{exrule}->contains($dt); next if $e{exdate} && $e{exdate}->contains($dt); my $event = $self->clone(); delete $event->{properties}->{$_} for qw(rrule exrule rdate exdate duration period); $event->start($dt); if (defined $e{duration}) { my $end = $dt + $e{duration}; $event->end($end); } $event->all_day($self->all_day); $event->original($self); push @events, $event; } } return @events if (!defined $period); my @new; push @new, $_->split_up($period) for @events; return @new; } =head2 original Store or fetch a reference to the original event this was derived from. =cut sub original { my $self = shift; $self->{_original} = $_[0] if @_; return $self->{_original}; } =head2 split_up Split an n-period event into n 1-period events. =cut sub split_up { my $event = shift; my $period = shift; return ($event) if $event->floating; my @new; my $span = DateTime::Span->from_datetimes( start => $event->start, end => $event->end ); my $dur = DateTime::Duration->new("${period}s" => 1)->subtract( "nanoseconds" => 1 ); my $r = DateTime::Set->from_recurrence( recurrence => sub { $_[0]->truncate(to => $period )->add("${period}s" => 1); }, span => $span); $r = $r->union(DateTime::Set->from_datetimes(dates => [$event->start])); my $i = $r->iterator; while (my $dt = $i->next) { last if $dt >= $event->end; # && !$event->all_day; my $e = $event->clone; $e->start($dt); $e->all_day(0); $e->original($event); # $e->all_day($event->all_day) if $period ne 'second' && $period ne 'minute' && $period ne 'day'; my $end = $dt->truncate( to => $period )->add( "${period}s" => 1 )->subtract( nanoseconds => 1 ); $e->end($end); push @new, $e; } # If, say we have a one week and 1 day event and period is # 'week' then need to truncate to one 1 week event and one # day event. # $end = $e{end} if ( defined $period && $e{end} < $end); $new[-1]->end($event->end); # if !$event->all_day; return @new; } =head2 is_in Takes L, L or L and returns whether this event can fall within that time frame. =cut sub is_in { my $self = shift; my $span = shift; my %e = $self->_normalise; return ( ( !$e{recur} && $e{span}->intersects($span) ) || ( $e{recur} && $e{recur}->intersection($span) ) ); } # return normalised information about this event sub _normalise { my $self = shift; my %e = (); $e{period} = $self->period; $e{start} = $self->start; $e{end} = $self->end; $e{duration} = $self->duration; $e{recur} = $self->recurrence; $e{exrule} = $self->exrule; $e{rdate} = $self->rdate; $e{exdate} = $self->exdate; $e{rid} = $self->recurrence_id; $e{uid} = $self->uid; if (defined $e{period}) { if (defined $e{start} || defined $e{end}) { die "Found a period *and* a start or end:\n".$self->as_string; } $e{start} = $e{period}->start; $e{end} = $e{period}->end; } if (!defined $e{start}) { die "Couldn't find start\n".$self->as_string; } if (defined $e{end} && defined $e{duration}) { die "Found both end *and* duration:\n".$self->as_string; } # events can be floating #if (!defined $e{end} && !defined $e{duration}) { # die "Couldn't find end *or* duration:\n".$self->as_string; #} if (defined $e{duration}) { $e{end} = $e{start} + $e{duration}; } if (defined $e{rdate}) { $e{recur} = (defined $e{recur}) ? $e{recur}->union($e{rdate}) : $e{rdate}; } my $end = $e{end} || $e{start}->clone->add(seconds => 1 ); $e{span} = DateTime::Span->from_datetimes( start => $e{start}, end => $end ); $e{duration} = $e{span}->duration if $e{end}; return %e; } =head1 AUTHOR Simon Wistow =head1 COPYING Copyright, 2005 Simon Wistow Distributed under the same terms as Perl itself. =head1 BUGS Potential timezone problems? =head1 SEE ALSO L, L, L, L, L =cut 1; Data-ICal-DateTime-0.82/examples/0000755000175000017500000000000013146616577015774 5ustar flavioflavioData-ICal-DateTime-0.82/examples/ics2rss0000644000175000017500000000331413145634223017273 0ustar flavioflavio#!/usr/bin/perl use constant SOURCE => "/Users/mark/Library/Application Support/iCal/Sources/E49F498D-968C-4A4F-93E8-6E9AF7F44B2B.calendar/corestorage.ics"; use strict; use warnings; use XML::RSS; # load the calendar use Data::ICal::DateTime; # create a new RSS feed my $rss = new XML::RSS (version => '1.0'); rss(0, 1, "today!"); rss(1, 2, "tomorrow!"); rss(2, 3, "day after tomorrow!"); rss(3, 7, "within a week"); rss(7, 14, "within a fortnight"); print $rss->as_string; ################################# my ($ical, @events); sub rss { my ($start, $end, $comment) = @_; # calculate the next 14 days. This is done once because it 'explodes' # the events and hence is quite expensive unless ($ical) { $ical = Data::ICal->new( filename => SOURCE ); @events = $ical->events( DateTime::Span->from_datetimes( start => midnight(), end => midnight()->add( days => 14, seconds => -1), ) ); } # what are we looking for this time? my $span = DateTime::Span->from_datetimes( start => midnight()->add( days => $start ), end => midnight()->add( days => $end, seconds => -1), ); # find which of those events in the next 14 days we're concerned # with and add them to the rss feed foreach my $event (grep { $_->is_in($span) } @events) { $rss->add_item( title => $event->summary . " $comment", description => "On ".$event->start->ymd." (".(qw( Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday ))[ $event->start->dow ] . ")" ); } } # midnight today. my $midnight; sub midnight { $midnight ||= DateTime->now->set( hour => 0, minute => 0, second => 0, nanosecond => 0 ); return $midnight->clone; } Data-ICal-DateTime-0.82/Changes0000644000175000017500000000444013146615427015444 0ustar flavioflavio0.82 - Mon 21 Aug 2017 * Set recurrence timezone to the same as the 'start' attribute (fix github issue #2) 0.81 - Mon 24 Nov 2014 10:11:50 PST * Add Makefile.PL back into MANIFEST (fixes RT 100524) * Remove MYMETA.* files from MANIFEST (fixes RT 100525) 0.8 - Fri 21 Nov 2014 11:26:57 PST * Update docs * Fix some timezone bugs (Fixes RT 43610 and RT 99804 - thanks Sterling Hanenkamp) * Refactor for more DRYness * Add URL field * Update Module::Install to add META.yml (fixes RT 80668) * Add a note about all day events (RT 63049) 0.7 - Thu 29 Nov 2007 16:45:39 GMT * Add VERSION to .ics files since new Data::ICal requires it 0.65 - Mon Feb 20 12:24:18 GMT 2006 * New Data::ICal does quoting for us 0.64 - Wed Oct 12 13:59:39 BST 2005 * Split events() up into events() and collapse() * Fix a bug with exploding floating events 0.63 - Mon Oct 10 12:20:33 BST 2005 * Added support for comma seperated (EX|R)DATES * Fix floating events - the way we were doing it before is wrong and there is now a floating() method 0.62 - Tue Oct 4 15:32:57 BST 2005 * Added auto setting of end if you set all_day without an existing end * Related to that worked round a bug related to Palm floating events noticed by Graham Gough * Documentation patches * Adding setting of exdates and rdates 0.61 - Wed Sep 21 17:48:36 BST 2005 * Make Clone a prereq 0.6 - Tue Sep 20 12:40:43 BST 2005 * Make setting of recurrence work * Add reference to original untainted object * Expose split_up method * Escape and Unescape summary and description 0.5 - Wed Sep 7 17:58:07 BST 2005 * Tests (and setting) for all_day * Fix all day events * Fix recurrence-id for exploded events 0.4 - Sat Sep 3 10:10:06 BST 2005 * Add recurrence-id support for event updates * Add all_day and uid methods * Make sure that recurring events get exploded 0.3 - Wed Aug 17 11:52:24 BST 2005 * match Data::ICal 0.03 API change 0.2 - Mon Aug 15 10:36:01 BST 2005 * More support for timezones * Note some todos * Fix a bug with premature truncation of RRULEs * Added EXRULE, EXDATE and RDATE support - we can now parse London.pm's insane meeting shcedule. YAY! 0.1 - Tue Aug 9 09:44:22 BST 2005 * initial release Data-ICal-DateTime-0.82/META.yml0000644000175000017500000000140213146616201015404 0ustar flavioflavio--- abstract: 'convenience methods for using Data::ICal with DateTime' author: - 'Simon Wistow ' build_requires: ExtUtils::MakeMaker: '6.36' Test::LongString: '0' Test::More: '0' Test::NoWarnings: '0' Test::Warn: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'ExtUtils::MakeMaker version 7.1002, CPAN::Meta::Converter version 2.150005' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Data-ICal-DateTime no_index: directory: - t - inc requires: Class::Accessor: '0' Clone: '0' Data::ICal: '0.07' DateTime::Format::ICal: '0' DateTime::Set: '0' version: '0.82' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Data-ICal-DateTime-0.82/Makefile.PL0000644000175000017500000000104113145634223016107 0ustar flavioflaviouse inc::Module::Install; name ('Data-ICal-DateTime'); author ('Simon Wistow '); version_from ('lib/Data/ICal/DateTime.pm'); abstract_from('lib/Data/ICal/DateTime.pm'); license('perl'); build_requires('Test::More'); build_requires('Test::Warn'); build_requires('Test::NoWarnings'); build_requires('Test::LongString'); requires('Class::Accessor'); requires('Data::ICal','0.07'); requires('Clone'); requires('DateTime::Set'); requires('DateTime::Format::ICal'); # requires('DateTime::Event::Recurrence','0.17'); &WriteAll;