Blame examples/ICal.pm

Packit 9002b2
# we need to comment this out or PAUSE might index it
Packit 9002b2
# pack age DateTime::Format::ICal;
Packit 9002b2
Packit 9002b2
use strict;
Packit 9002b2
Packit 9002b2
use DateTime;
Packit 9002b2
Packit 9002b2
# Builder relevant stuff starts here.
Packit 9002b2
Packit 9002b2
use DateTime::Format::Builder parsers => {
Packit 9002b2
    parse_datetime => [
Packit 9002b2
        [ preprocess => \&_parse_tz ],
Packit 9002b2
        {
Packit 9002b2
            length => 15,
Packit 9002b2
            params => [qw( year month day hour minute second )],
Packit 9002b2
            regex  => qr/^(\d\d\d\d)(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d)$/,
Packit 9002b2
        },
Packit 9002b2
        {
Packit 9002b2
            length => 13,
Packit 9002b2
            params => [qw( year month day hour minute )],
Packit 9002b2
            regex  => qr/^(\d\d\d\d)(\d\d)(\d\d)T(\d\d)(\d\d)$/,
Packit 9002b2
        },
Packit 9002b2
        {
Packit 9002b2
            length => 11,
Packit 9002b2
            params => [qw( year month day hour )],
Packit 9002b2
            regex  => qr/^(\d\d\d\d)(\d\d)(\d\d)T(\d\d)$/,
Packit 9002b2
        },
Packit 9002b2
        {
Packit 9002b2
            length => 8,
Packit 9002b2
            params => [qw( year month day )],
Packit 9002b2
            regex  => qr/^(\d\d\d\d)(\d\d)(\d\d)$/,
Packit 9002b2
        },
Packit 9002b2
    ],
Packit 9002b2
};
Packit 9002b2
Packit 9002b2
sub _parse_tz {
Packit 9002b2
    my %args = @_;
Packit 9002b2
    my ( $date, $p ) = @args{qw( input parsed )};
Packit 9002b2
    if ( $date =~ s/^TZID=([^:]+):// ) {
Packit 9002b2
        $p->{time_zone} = $1;
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
    # Z at end means UTC
Packit 9002b2
    elsif ( $date =~ s/Z$// ) {
Packit 9002b2
        $p->{time_zone} = 'UTC';
Packit 9002b2
    }
Packit 9002b2
    else {
Packit 9002b2
        $p->{time_zone} = 'floating';
Packit 9002b2
    }
Packit 9002b2
    return $date;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
# Builder relevant stuff ends here.
Packit 9002b2
Packit 9002b2
sub parse_duration {
Packit 9002b2
    my ( $self, $dur ) = @_;
Packit 9002b2
Packit 9002b2
    my @units = qw( weeks days hours minutes seconds );
Packit 9002b2
Packit 9002b2
    $dur =~ m{ ([\+\-])?         # Sign
Packit 9002b2
               P                 # 'P' for period? This is our magic character)
Packit 9002b2
               (?:
Packit 9002b2
                   (?:(\d+)W)?   # Weeks
Packit 9002b2
                   (?:(\d+)D)?   # Days
Packit 9002b2
               )?
Packit 9002b2
               (?: T             # Time prefix
Packit 9002b2
                   (?:(\d+)H)?   # Hours
Packit 9002b2
                   (?:(\d+)M)?   # Minutes
Packit 9002b2
                   (?:(\d+)S)?   # Seconds
Packit 9002b2
               )?
Packit 9002b2
             }x;
Packit 9002b2
Packit 9002b2
    my $sign = $1;
Packit 9002b2
Packit 9002b2
    my %units;
Packit 9002b2
    $units{weeks}   = $2 if defined $2;
Packit 9002b2
    $units{days}    = $3 if defined $3;
Packit 9002b2
    $units{hours}   = $4 if defined $4;
Packit 9002b2
    $units{minutes} = $5 if defined $5;
Packit 9002b2
    $units{seconds} = $6 if defined $6;
Packit 9002b2
Packit 9002b2
    die "Invalid ICal duration string ($dur)\n"
Packit 9002b2
        unless %units;
Packit 9002b2
Packit 9002b2
    if ( $sign eq '-' ) {
Packit 9002b2
        $_ *= -1 foreach values %units;
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
    return DateTime::Duration->new(%units);
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub format_datetime {
Packit 9002b2
    my ( $self, $dt ) = @_;
Packit 9002b2
Packit 9002b2
    my $tz = $dt->time_zone;
Packit 9002b2
Packit 9002b2
    unless ( $tz->is_floating || $tz->is_utc || $tz->name ) {
Packit 9002b2
        $dt = $dt->clone->set_time_zone('UTC');
Packit 9002b2
        $tz = $dt->time_zone;
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
    my $base = (
Packit 9002b2
        $dt->hour || $dt->min || $dt->sec
Packit 9002b2
        ? sprintf(
Packit 9002b2
            '%04d%02d%02dT%02d%02d%02d',
Packit 9002b2
            $dt->year, $dt->month,  $dt->day,
Packit 9002b2
            $dt->hour, $dt->minute, $dt->second
Packit 9002b2
            )
Packit 9002b2
        : sprintf( '%04d%02d%02d', $dt->year, $dt->month, $dt->day )
Packit 9002b2
    );
Packit 9002b2
Packit 9002b2
    return $base if $tz->is_floating;
Packit 9002b2
Packit 9002b2
    return $base . 'Z' if $tz->is_utc;
Packit 9002b2
Packit 9002b2
    return 'TZID=' . $tz->name . ':' . $base;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub format_duration {
Packit 9002b2
    my ( $self, $duration ) = @_;
Packit 9002b2
Packit 9002b2
    die "Cannot represent years or months in an iCal duration\n"
Packit 9002b2
        if $duration->delta_months;
Packit 9002b2
Packit 9002b2
    # simple string for 0-length durations
Packit 9002b2
    return '+PT0S'
Packit 9002b2
        unless $duration->delta_days || $duration->delta_seconds;
Packit 9002b2
Packit 9002b2
    my $ical = $duration->is_positive ? '+' : '-';
Packit 9002b2
    $ical .= 'P';
Packit 9002b2
Packit 9002b2
    if ( $duration->delta_days ) {
Packit 9002b2
        $ical .= $duration->weeks . 'W' if $duration->weeks;
Packit 9002b2
        $ical .= $duration->days . 'D'  if $duration->days;
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
    if ( $duration->delta_seconds ) {
Packit 9002b2
        $ical .= 'T';
Packit 9002b2
Packit 9002b2
        $ical .= $duration->hours . 'H'   if $duration->hours;
Packit 9002b2
        $ical .= $duration->minutes . 'M' if $duration->minutes;
Packit 9002b2
        $ical .= $duration->seconds . 'S' if $duration->seconds;
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
    return $ical;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
1;