Changeset 369

Show
Ignore:
Timestamp:
05/18/07 10:58:50 (18 months ago)
Author:
ogawa
Message:

merged from cybozu2ical

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • WWW-CybozuOffice6-Calendar/trunk/lib/WWW/CybozuOffice6/Calendar.pm

    r360 r369  
    5151        next if $#fields < 13; # num. of fields 
    5252 
    53         my $item = $fields[7] ? 
    54             $this->_parse_recurrent_event(@fields) : 
    55             $this->_parse_general_event(@fields); 
    56         push @items, $item if $item; 
     53        # Cybozu Calendar CSV Format 
     54        #      GENERIC     | RECCURENT 
     55        # [ 0] id?         | id? 
     56        # [ 1] created     | created 
     57        # [ 2] <BLANK>     x start_date 
     58        # [ 3] start_date  x end_date 
     59        # [ 4] end_date    x until_date 
     60        # [ 5] start_time  | start_time 
     61        # [ 6] end_time    | end_time 
     62        # [ 7] <BLANK>     | freq 
     63        # [ 8] <BLANK>     | freq_value 
     64        # [ 9] ???         | ??? 
     65        # [10] ???         | ??? 
     66        # [11] abbrev      | abbrev 
     67        # [12] summary     | summary 
     68        # [13] description | description 
     69 
     70        my %param; 
     71        @param{qw(created start_time end_time freq freq_value abbrev summary description)} = @fields[1,5..8,11..13]; 
     72        $param{created} =~ s/^ts\.//; 
     73        $param{time_zone} = $this->{time_zone} || 'Asia/Tokyo'; 
     74 
     75        my $item; 
     76        if (!$param{freq}) { 
     77            @param{qw(start_date end_date)} = @fields[3,4]; 
     78            $item = WWW::CybozuOffice6::Calendar::Event->new(%param); 
     79        } else { 
     80            @param{qw(start_date end_date until_date)} = @fields[2..4]; 
     81            $item = WWW::CybozuOffice6::Calendar::RecurentEvent->new(%param); 
     82        } 
     83 
     84        next unless $item; 
     85        $item->comment($line); # save the CSV line as for debug info. 
     86        push @items, $item; 
    5787    } 
    5888    wantarray ? @items : $items[0]; 
     
    72102} 
    73103 
    74 # handle non-recurrent events 
    75 sub _parse_general_event { 
    76     my $this = shift; 
    77     my @fields = @_; 
    78  
    79     my $now = DateTime->now; 
    80     my $is_full_day = 0; 
    81  
    82     my $start = $this->to_datetime($fields[3], $fields[5]); 
    83     my $end   = $this->to_datetime($fields[4], $fields[6]); 
     104package WWW::CybozuOffice6::Calendar::Event; 
     105 
     106sub new { 
     107    my $class = shift; 
     108    my $self = { 
     109        is_full_day => 0, 
     110#       modified => DateTime->now, 
     111    }; 
     112    bless $self, $class; 
     113    return unless $self->parse(@_); 
     114    $self; 
     115} 
     116 
     117sub start       { shift->_accessor('start',             @_) } 
     118sub end         { shift->_accessor('end',               @_) } 
     119sub summary     { shift->_accessor('summary',           @_) } 
     120sub description { shift->_accessor('description',       @_) } 
     121sub created     { shift->_accessor('created',           @_) } 
     122sub modified    { shift->_accessor('modified',          @_) } 
     123sub is_full_day { shift->_accessor('is_full_day',       @_) } 
     124sub comment     { shift->_accessor('comment',           @_) } 
     125sub _accessor { 
     126    my $this = shift; 
     127    my $key = shift; 
     128    $this->{$key} = shift if @_; 
     129    $this->{$key}; 
     130} 
     131 
     132sub parse { 
     133    my($this, %param) = @_; 
     134 
     135    $this->{time_zone} = $param{time_zone} || 'Asia/Tokyo'; 
     136 
     137    my $start = $this->to_datetime($param{start_date}, $param{start_time}); 
     138    my $end   = $this->to_datetime($param{end_date},   $param{end_time}); 
    84139    return unless $start && $end; 
    85     if ($fields[5] eq ':') {            # full-day event 
     140 
     141    # (start_time == empty) => A full-day event 
     142    # (start_time != empty) && (end_time == empty) => A malformed event 
     143    if ($param{start_time} eq ':') { 
    86144        $start = $start->truncate(to => 'day'); 
    87145        $end   = $end->add(days => 1)->truncate(to => 'day'); 
    88         $is_full_day = 1; 
    89     } elsif ($fields[6] eq ':') {       # event w/o endtime 
     146        $this->{is_full_day} = 1; 
     147    } elsif ($param{end_time} eq ':') { 
    90148        $end   = $start->clone->add(minutes => 10); 
    91149    } 
    92  
    93     my($created) = $fields[1] =~ m/^ts\.(\d+)$/; 
    94     $created = DateTime->from_epoch(epoch => $created || 0); 
    95  
    96     my $summary = $fields[11] || ''; 
    97     $summary .= ': ' if $summary; 
    98     $summary .= $fields[12] || ''; 
    99  
    100     my $item = { 
    101         start       => $start, 
    102         end         => $end, 
    103         is_full_day => $is_full_day, 
    104         summary     => $summary, 
    105         description => $fields[13] || $summary, 
    106         created     => $created, 
    107         modified    => $now, 
    108     }; 
    109 } 
    110  
    111 # handle recurrent events 
    112 our %FREQUENCY = ( y => 'YEARLY', m => 'MONTHLY', w => 'WEEKLY', 
    113                    d => 'DAILY', n => 'WEEKDAYS' ); 
    114 sub _parse_recurrent_event { 
    115     my $this = shift; 
    116     my @fields = @_; 
    117  
    118     # arrange for _parse_general_event 
    119     my @f = @fields; 
    120     $f[4] = $f[3]; 
    121     $f[3] = $f[2]; 
    122     my $item = $this->_parse_general_event(@f); 
    123  
    124     # frequency 
    125     my $freq = $fields[7]; 
    126     if ($freq && exists $FREQUENCY{$freq}) { 
    127         $item->{frequency} = $FREQUENCY{$freq}; 
    128         $item->{frequency_value} = $fields[8] || 0; 
    129         if ($fields[4] =~ m!^(\d+)/(\d+)/(\d+)$!) { 
    130             my %args = (year => $1, month => $2, day => $3); 
    131             my $until; 
    132             if ($item->{is_full_day}) { 
    133                 $until = $this->to_datetime($fields[4], ':'); 
    134             } else { 
    135                 $until = $item->{end}->clone->set(%args); 
    136                 $until->set_time_zone('UTC'); # timezone must be UTC 
    137             } 
    138             $item->{until} = $until; 
    139         } 
    140     } 
    141  
    142     $item; 
    143 } 
    144  
     150    $this->{start} = $start; 
     151    $this->{end}   = $end; 
     152 
     153    $this->{created} = DateTime->from_epoch(epoch => $param{created} || 0); 
     154    $this->{modified} = DateTime->from_epoch(epoch => $param{created} || 0); 
     155 
     156    my $summary = ($param{abbrev} ? $param{abbrev} . ': ' : '') . $param{summary}; 
     157    $this->{summary} = $summary; 
     158    $this->{description} = $param{description} || $summary; 
     159    1; 
     160} 
     161 
     162# convert (ymd, hms) pair to a DateTime object (timezone: localtime) 
    145163sub to_datetime { 
    146164    my $this = shift; 
     
    159177    } 
    160178 
    161     $args{time_zone} = $this->{time_zone} || 'Asia/Tokyo'; 
     179    $args{time_zone} = $this->{time_zone}; 
    162180 
    163181    DateTime->new(%args); 
     182} 
     183 
     184package WWW::CybozuOffice6::Calendar::RecurrentEvent; 
     185 
     186@WWW::CybozuOffice6::Calendar::RecurrentEvent::ISA = qw( WWW::CybozuOffice6::Calendar::Event ); 
     187 
     188sub frequency           { shift->_accessor('frequency',         @_) } 
     189sub frequency_value     { shift->_accessor('frequency_value',   @_) } 
     190 
     191our %FREQUENCY = ( y => 'YEARLY', m => 'MONTHLY', w => 'WEEKLY', 
     192                   d => 'DAILY', n => 'WEEKDAYS' ); 
     193sub parse { 
     194    my($this, %param) = @_; 
     195    $this->SUPER::parse(%param); 
     196 
     197    # frequency 
     198    my $freq = $param{freq}; 
     199    return unless $freq && exists $FREQUENCY{$freq}; 
     200 
     201    $this->{frequency} = $FREQUENCY{$freq}; 
     202    $this->{frequency_value} = $param{freq_value} || 0; 
     203 
     204    if ($param{until_date} =~ m!^(\d+)/(\d+)/(\d+)$!) { 
     205        my %args = (year => $1, month => $2, day => $3); 
     206        my $until; 
     207        if ($this->{is_full_day}) { 
     208            $until = $this->to_datetime($param{until_date}, ':'); 
     209        } else { 
     210            $until = $this->{end}->clone->set(%args); 
     211            $until->set_time_zone('UTC'); # timezone must be UTC 
     212        } 
     213        $this->{until} = $until; 
     214    } 
     215    1; 
    164216} 
    165217