File Coverage

blib/lib/Net/ICal/Time.pm
Criterion Covered Total %
statement 29 51 56.8
branch 1 4 25.0
condition n/a
subroutine 10 19 52.6
pod 11 12 91.6
total 51 86 59.3


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             # -*- Mode: perl -*-
3             #======================================================================
4             #
5             # This package is free software and is provided "as is" without express
6             # or implied warranty. It may be used, redistributed and/or modified
7             # under the same terms as perl itself. ( Either the Artistic License or the
8             # GPL. )
9             #
10             # (C) COPYRIGHT 2000-2001, Reefknot developers.
11             #
12             # See the AUTHORS file included in the distribution for a full list.
13             #======================================================================
14              
15             =pod
16              
17             =head1 NAME
18              
19             Net::ICal::Time -- represent a time and date
20              
21             =head1 SYNOPSIS
22              
23             $t = Net::ICal::Time->new( epoch => time );
24             $t = Net::ICal::Time->new( ical => '19970101' );
25             $t = Net::ICal::Time->new( ical => '19970101T120000',
26             timezone => 'America/Los_Angeles' );
27              
28             # Eventually ...
29             $t = Net::ICal::Time-new( iso => '1997-10-14' );
30             # or other time formats ...
31              
32             # Not yet implemented
33             $t = Net::ICal::Time->new(
34             second => 12,
35             minute => 5,
36             hour => 6,
37             day => 10,
38             month => 9,
39             year => 1997,
40             );
41              
42             # Not yet implemented
43             $t2 = $t->add( hour => '6' );
44            
45             =head1 WARNING
46              
47             This is ALPHA QUALITY CODE. Due to a roundoff error in
48             Date::ICal, which it's based on, addition and subtraction is
49             often one second off. Patches welcome. See the README that
50             came with this module for how you can help.
51              
52             =head1 DESCRIPTION
53              
54             I
55             time and indicate if the time should be treated as a date. The time
56             can be constructed from a variey of formats.
57              
58             =head1 METHODS
59              
60             =cut
61              
62             package Net::ICal::Time;
63 2     2   24392 use strict;
  2         3  
  2         85  
64              
65 2     2   10 use base qw(Date::ICal);
  2         4  
  2         1320  
66              
67 2     2   13901 use Net::ICal::Duration;
  2         5  
  2         18  
68 2     2   58 use Time::Local;
  2         4  
  2         119  
69 2     2   2232 use POSIX;
  2         19639  
  2         16  
70 2     2   8175 use Carp qw(confess cluck);
  2         11  
  2         123  
71 2     2   12 use UNIVERSAL;
  2         4  
  2         42  
72              
73             =pod
74              
75             =head2 new
76              
77             Creates a new time object given one of:
78              
79             =over 4
80              
81             =item * epoch => integer seconds past the POSIX epoch.
82              
83             =item * ical => iCalendar date-time string
84              
85             =back
86              
87             If neither of these arguments is supplied, the value will default to
88             the current date.
89              
90             WARNING: Timezone handling is currently in flux in Net::ICal, pending
91             Date::ICal awareness of timezones. This may change the call syntax slightly.
92              
93             =begin testing
94             use lib "../lib";
95              
96             use Net::ICal::Time;
97             my $t1 = new Net::ICal::Time(ical => '20010402');
98              
99             ok(defined($t1), 'simple iCal creation test (date only)');
100              
101             print $t1->as_ical . "\n";
102              
103             # note: there *should* be a Z on the end of the string, because we assume
104             # that new dates are in UTC unless otherwise specified.
105             ok($t1->as_ical eq ':20010402Z', 'simple iCal creation (date only) makes correct iCal');
106              
107             # TODO: define more tests in this vein that are Net::ICal specific.
108             # Mostly, you want the tests here to be Date::ICal tests;
109             # Don't just add tests here unless they test something specific to N::I.
110              
111             =end testing
112              
113              
114              
115             =head2 clone()
116              
117             Create a new copy of this time.
118              
119             =begin testing
120              
121             $t1 = new Net::ICal::Time(epoch => '22');
122             my $t2 = $t1->clone();
123              
124             # FIXME: This test is weak because it relies on compare() working
125             ok($t1->compare($t2) == 0, "Clone comparison says they're the same");
126              
127             =end testing
128              
129             =cut
130              
131             # clone a Time object.
132             sub clone {
133 0     0 1 0 my $self = shift;
134              
135 0         0 return bless( {%$self},ref($self));
136              
137             }
138              
139              
140             =pod
141              
142             =head2 zone
143              
144             Accessor to the timezone. Takes & Returns an Olsen place name
145             ("America/Los_Angeles", etc. ) , an Abbreviation, 'UTC', or 'float' if
146             no zone was specified.
147              
148             THIS IS NOT YET IMPLEMENTED. Date::ICal does not yet support timezones.
149              
150             =begin testing
151              
152             #XXX: commented because todo tests aren't implemented yet in Test::More
153             #todo { ok (1==1, 'timezone testing') } 1, "no timezone support yet";
154              
155             =end testing
156              
157             =cut
158              
159             # XXX This needs to be defined.
160 0     0 1 0 sub zone {}
161              
162             =pod
163              
164             =head2 add($duration)
165              
166             Takes a duration string or I and returns a
167             I
168             Does not modify this time.
169              
170             =begin testing
171              
172             $t1 = Net::ICal::Time->new( ical => '20010405T160000Z');
173             my $d1 = Net::ICal::Duration->new ('PT15M');
174             print $d1->as_ical_value() . "\n";
175              
176             $t1->add($d1->as_ical_value);
177              
178             print $t1->ical . "\n";
179             ok($t1->ical eq "20010405T161500Z", "adding minutes from an iCal string works");
180              
181             #---------------------------------------------------
182             $t1 = Net::ICal::Time->new( ical => '20010405T160000Z');
183             $t1->add($d1);
184              
185             print $t1->ical . "\n";
186             ok($t1->ical eq "20010405T161500Z", "adding minutes from a Duration object works");
187              
188             # NOTE: Most tests of whether the arithmetic actually works should
189             # be in the Date::ICal inline tests. These tests just make sure that
190             # N::I::Time is wrappering D::I sanely.
191              
192             =end testing
193              
194             =cut
195             sub add {
196 10     10 1 4524 my ($self, $param) = @_;
197            
198             # FIXME: need input validation here
199 10         19 my $duration = $param;
200            
201             # be backwards-compatible for now.
202 10 50       71 if (UNIVERSAL::isa($param,'Net::ICal::Duration')) {
203             #probably the Wrong Way, but it works for now.
204 0         0 $duration = $param->as_ical_value;
205             };
206              
207             # at this point, assume that duration is an iCalendar string.
208 10         53 return $self->SUPER::add(duration=>$duration);
209              
210             }
211              
212             =pod
213              
214             =head2 subtract($time)
215              
216             Subtract out a time of type I
217             modify this time.
218              
219             =begin testing
220              
221             $t1 = Net::ICal::Time->new( ical => '20010405T160000Z');
222             $d1 = Net::ICal::Duration->new('PT15M');
223              
224             print $d1->as_ical_value . "\n";
225             $t1->subtract($d1->as_ical_value);
226             print "result was " . $t1->as_ical_value . "\n";
227             ok($t1->as_ical_value eq "20010405T154500Z", "subtracting minutes using an iCal string works");
228              
229             #---------------------------------------------------
230             $t1 = Net::ICal::Time->new( ical => '20010405T160000Z');
231             $t1->subtract($d1);
232              
233             print $t1->as_ical_value . "\n";
234              
235             ok($t1->as_ical_value eq "20010405T154500Z", "subtracting minutes using a Duration object works");
236              
237             # NOTE: Most tests of whether the arithmetic actually works should
238             # be in the Date::ICal inline tests. These tests just make sure that
239             # N::I::Time is wrappering D::I sanely.
240              
241             =end testing
242              
243             =cut
244             sub subtract {
245 0     0 1 0 my $self = shift;
246 0         0 my $param = shift;
247              
248 0         0 my $duration = $param;
249            
250             # be backwards-compatible for now.
251 0 0       0 if (UNIVERSAL::isa($param,'Net::ICal::Duration')) {
252             # probably the Wrong Way, but it works for now.
253 0         0 $duration = $param->as_ical_value();
254             };
255              
256 0         0 $duration = "-" . $duration; # negate the duration they gave, so we can subtract
257              
258 0         0 return $self->add($duration);
259              
260             }
261              
262             =pod
263              
264             =head2 move_to_zone($zone);
265              
266             Change the time to what it would be in the named timezone.
267             The zone can be an Olsen placename or "UTC".
268              
269             THIS FUNCTION IS NOT YET IMPLEMENTED. We're waiting on Date::ICal
270             to provide this function.
271              
272             =begin testing
273             TODO: {
274             local $TODO = "implement move_to_zone";
275             ok(0, "move_to_zone isn't implemented yet");
276              
277             };
278             =end testing
279              
280             =cut
281              
282             # XXX this needs implementing, possibly by Date::ICal.
283             sub move_to_zone {
284 0     0 1 0 confess "Not Implemented\n";
285             }
286              
287              
288             =pod
289              
290             =head2 as_ical()
291              
292             Convert to an iCal format property string.
293              
294             =begin testing
295             #TODO
296             =end testing
297              
298              
299             =cut
300             sub as_ical {
301 6     6 1 7928 my $self = shift;
302            
303             # fallback to Date::ICal here
304 6         26 return ":" . $self->ical;
305             }
306              
307             sub as_ical_value {
308 16     16 0 936 my ($self) = @_;
309 16         59 return $self->ical;
310             }
311              
312             =pod
313              
314             =head2 as_localtime()
315              
316             Convert to list format, as per localtime(). This is *not* timezone safe.
317              
318             =for testing
319             #TODO
320              
321             =cut
322             sub as_localtime {
323 0     0 1   my $self = shift;
324              
325 0           return localtime($self->epoch());
326              
327             }
328              
329             =pod
330              
331             =head2 as_gmtime()
332              
333             Convert to list format, as per gmtime()
334              
335             =for testing
336             #TODO
337              
338             =cut
339             sub as_gmtime {
340 0     0 1   my $self = shift;
341              
342 0           return gmtime($self->epoch());
343              
344             }
345              
346             =pod
347              
348             =head2 day_of_week()
349              
350             Return 0-6 representing day of week of this date.
351              
352             =for testing
353             #TODO
354              
355             =cut
356             # XXX Implement this
357             sub day_of_week {
358 0     0 1   my $self = shift;
359              
360 0           return (gmtime($self->epoch()))[6];
361             }
362              
363             =pod
364              
365             =head2 day_of_year()
366              
367             Return 1-365 representing day of year of this date.
368              
369             =for testing
370             #TODO
371              
372             =cut
373              
374             # XXX Implement this
375             sub day_of_year {
376 0     0 1   my $self = shift;
377              
378 0           return (gmtime($self->epoch()))[7];
379             }
380              
381              
382             =pod
383              
384             =head2 start_of_week()
385              
386             Return the day of year of the first day (Sunday) of the week that
387             this date is in
388              
389             =for testing
390             #TODO
391              
392             =cut
393              
394             # XXX Implement this
395             sub start_of_week {
396 0     0 1   my $self = shift;
397              
398             # There's an issue here when Sunday is in the previous year. Should we return
399             # the day number in the previous year? But then the calling program has to
400             # be smart enough to notice this, Ive chosen here to return a negative year
401             # day to indicate last year (okay Im lazy means I don't have to worry about
402             # leap years). Note that it seems that localtime etc count days from 0..364
403             # rather than 1..365 as it states in the man pages, am I missing something??
404             # Sunday is zero hence the need to subtract an extra day
405 0           return $self->day_of_year() - $self->day_of_week() + 1;
406             }
407              
408              
409             1;
410              
411             __END__