line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
# Date::HolidayParser |
3
|
|
|
|
|
|
|
# A parser of ~/.holiday-style files. |
4
|
|
|
|
|
|
|
# The format is based off of the holiday files found bundled |
5
|
|
|
|
|
|
|
# with the plan program, not any official spec. This because no |
6
|
|
|
|
|
|
|
# official spec could be found. |
7
|
|
|
|
|
|
|
# Copyright (C) Eskild Hustvedt 2006, 2007, 2008, 2010 |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify it |
10
|
|
|
|
|
|
|
# under the same terms as Perl itself. There is NO warranty; |
11
|
|
|
|
|
|
|
# not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
12
|
|
|
|
|
|
|
# |
13
|
|
|
|
|
|
|
# This is the iCalendar component, which emulates a DP::iCalendar-like interface |
14
|
|
|
|
|
|
|
# in order to make it easier to use for users familiar with iCalendar, and |
15
|
|
|
|
|
|
|
# make it compatible with DP::iCalendar::Manager. |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
package Date::HolidayParser::iCalendar; |
18
|
|
|
|
|
|
|
|
19
|
2
|
|
|
2
|
|
47857
|
use Any::Moose; |
|
2
|
|
|
|
|
95660
|
|
|
2
|
|
|
|
|
15
|
|
20
|
2
|
|
|
2
|
|
2942
|
use Date::HolidayParser; |
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
83
|
|
21
|
2
|
|
|
2
|
|
23
|
use constant { true => 1, false => undef }; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
2588
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our $VERSION = 0.41; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
extends 'Date::HolidayParser'; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
has '_UID_List' => ( |
28
|
|
|
|
|
|
|
is => 'rw', |
29
|
|
|
|
|
|
|
isa => 'HashRef', |
30
|
|
|
|
|
|
|
default => sub { {} }, |
31
|
|
|
|
|
|
|
); |
32
|
|
|
|
|
|
|
has '_iCal_cache' => ( |
33
|
|
|
|
|
|
|
is => 'rw', |
34
|
|
|
|
|
|
|
isa => 'HashRef', |
35
|
|
|
|
|
|
|
default => sub { {} }, |
36
|
|
|
|
|
|
|
); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# -- Public methods -- |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Purpose: Get an iCalendar hash with holiday info matching the supplied UID |
41
|
|
|
|
|
|
|
# Usage: get_info(UID); |
42
|
|
|
|
|
|
|
sub get_info |
43
|
|
|
|
|
|
|
{ |
44
|
72
|
|
|
72
|
1
|
110
|
my $self = shift; |
45
|
72
|
|
|
|
|
95
|
my $UID = shift; |
46
|
72
|
100
|
|
|
|
545
|
return($self->_UID_List->{$UID}) if $self->_UID_List->{$UID}; |
47
|
3
|
|
|
|
|
14
|
return(false); |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Purpose: List events in said year, on said month and day |
51
|
|
|
|
|
|
|
# Usage: obj->list_events(year?,month?,day?); |
52
|
|
|
|
|
|
|
# year is required, others are optional. |
53
|
|
|
|
|
|
|
# |
54
|
|
|
|
|
|
|
# This is the primary API for this module. It does only wrap the other |
55
|
|
|
|
|
|
|
# methods, but provides a cleaner interface for new code. |
56
|
|
|
|
|
|
|
sub list_events |
57
|
|
|
|
|
|
|
{ |
58
|
24
|
|
|
24
|
1
|
8114
|
my ($self,$Year,$Month,$Day) = @_; |
59
|
24
|
50
|
|
|
|
79
|
if(not defined $Year) |
60
|
|
|
|
|
|
|
{ |
61
|
0
|
|
|
|
|
0
|
croak('Requried parameter "Year" not supplied'); |
62
|
|
|
|
|
|
|
} |
63
|
24
|
100
|
|
|
|
64
|
if(defined $Day) |
|
|
100
|
|
|
|
|
|
64
|
|
|
|
|
|
|
{ |
65
|
9
|
|
|
|
|
26
|
return $self->get_timeinfo($Year,$Month,$Day,'DAY'); |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
elsif(defined $Month) |
68
|
|
|
|
|
|
|
{ |
69
|
12
|
|
|
|
|
35
|
return $self->get_monthinfo($Year,$Month); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
else |
72
|
|
|
|
|
|
|
{ |
73
|
3
|
|
|
|
|
10
|
return $self->get_months($Year); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Purpose: Get information for the supplied month (list of days there are events) |
78
|
|
|
|
|
|
|
# Usage: my $TimeRef = $object->get_monthinfo(YEAR,MONTH,DAY); |
79
|
|
|
|
|
|
|
sub get_monthinfo |
80
|
|
|
|
|
|
|
{ |
81
|
24
|
|
|
24
|
0
|
8803
|
my($self, $Year, $Month) = @_; # TODO: verify that they are set |
82
|
24
|
|
|
|
|
80
|
$self->get($Year); |
83
|
24
|
|
|
|
|
33
|
my @Array; |
84
|
24
|
50
|
33
|
|
|
184
|
if(defined($self->_iCal_cache->{$Year}) and defined($self->_iCal_cache->{$Year}{$Month})){ |
85
|
24
|
|
|
|
|
33
|
@Array = sort keys(%{$self->_iCal_cache->{$Year}{$Month}}); |
|
24
|
|
|
|
|
160
|
|
86
|
|
|
|
|
|
|
} |
87
|
24
|
|
|
|
|
144
|
return(\@Array); |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# Purpose: Get information for the supplied date (list of times in the day there are events) |
91
|
|
|
|
|
|
|
# Usage: my $TimeRef = $object->get_dateinfo(YEAR,MONTH,DAY); |
92
|
|
|
|
|
|
|
sub get_dateinfo |
93
|
|
|
|
|
|
|
{ |
94
|
6
|
|
|
6
|
0
|
1358
|
my($self, $Year, $Month, $Day) = @_; # TODO: verify that they are set |
95
|
6
|
|
|
|
|
21
|
$self->get($Year); |
96
|
6
|
|
|
|
|
9
|
my @Array; |
97
|
6
|
100
|
33
|
|
|
80
|
if(defined($self->_iCal_cache->{$Year}) and defined($self->_iCal_cache->{$Year}{$Month}) and defined($self->_iCal_cache->{$Year}{$Month}{$Day})) { |
|
|
|
66
|
|
|
|
|
98
|
3
|
|
|
|
|
6
|
@Array = sort keys(%{$self->_iCal_cache->{$Year}{$Month}{$Day}}); |
|
3
|
|
|
|
|
20
|
|
99
|
|
|
|
|
|
|
} |
100
|
6
|
|
|
|
|
34
|
return(\@Array); |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Purpose: Return an empty array, unsupported. |
104
|
|
|
|
|
|
|
# Usage: my $UIDRef = $object->get_timeinfo(YEAR,MONTH,DAY,TIME); |
105
|
|
|
|
|
|
|
sub get_timeinfo |
106
|
|
|
|
|
|
|
{ |
107
|
18
|
|
|
18
|
0
|
35
|
my($self, $Year, $Month, $Day,$Time) = @_; |
108
|
|
|
|
|
|
|
|
109
|
18
|
50
|
|
|
|
43
|
return(undef) if not $Time eq 'DAY'; |
110
|
|
|
|
|
|
|
|
111
|
18
|
|
|
|
|
58
|
$self->get($Year); |
112
|
|
|
|
|
|
|
|
113
|
18
|
100
|
33
|
|
|
209
|
if( defined($self->_iCal_cache->{$Year}) and |
|
|
|
66
|
|
|
|
|
114
|
|
|
|
|
|
|
defined($self->_iCal_cache->{$Year}{$Month}) and |
115
|
|
|
|
|
|
|
defined($self->_iCal_cache->{$Year}{$Month}{$Day}) |
116
|
|
|
|
|
|
|
) |
117
|
|
|
|
|
|
|
{ |
118
|
12
|
|
|
|
|
89
|
return($self->_iCal_cache->{$Year}{$Month}{$Day}{$Time}); |
119
|
|
|
|
|
|
|
} |
120
|
6
|
|
|
|
|
27
|
return([]); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Purpose: Get a list of months which have events (those with *only* recurring not counted) |
124
|
|
|
|
|
|
|
# Usage: my $ArrayRef = $object->get_months(YEAR); |
125
|
|
|
|
|
|
|
sub get_months |
126
|
|
|
|
|
|
|
{ |
127
|
6
|
|
|
6
|
0
|
12
|
my ($self, $Year) = @_; |
128
|
6
|
|
|
|
|
33
|
$self->get($Year); |
129
|
6
|
|
|
|
|
7
|
my @Array = sort keys(%{$self->_iCal_cache->{$Year}}); |
|
6
|
|
|
|
|
54
|
|
130
|
6
|
|
|
|
|
43
|
return(\@Array); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# Purpose: Check if there is an holiday event with the supplied UID |
134
|
|
|
|
|
|
|
# Usage: $bool = $object->exists($UID); |
135
|
|
|
|
|
|
|
sub exists |
136
|
|
|
|
|
|
|
{ |
137
|
36
|
|
|
36
|
0
|
47068
|
my $self = shift; |
138
|
36
|
|
|
|
|
62
|
my $UID = shift; |
139
|
36
|
100
|
|
|
|
284
|
return(true) if defined($self->_UID_List->{$UID}); |
140
|
3
|
|
|
|
|
12
|
return(false); |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# -- Unsupported or dummy methods, here for compatibility -- |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# Purpose: Return an empty array, unsupported. |
146
|
|
|
|
|
|
|
# Usage: my $ArrayRef = $object->get_years(); |
147
|
|
|
|
|
|
|
sub get_years |
148
|
|
|
|
|
|
|
{ |
149
|
3
|
|
|
3
|
0
|
4293
|
return([]); |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# -- DP::iCalendar compatibility code -- |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# Used by DP::iCalendar::Manager to set the prodid in output iCalendar files. |
155
|
|
|
|
|
|
|
# We can't output iCalendar files, so we just ignore calls to it. |
156
|
3
|
|
|
3
|
0
|
6
|
sub set_prodid { } |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# Purpose: Return manager information |
159
|
|
|
|
|
|
|
# Usage: get_manager_version(); |
160
|
|
|
|
|
|
|
sub get_manager_version |
161
|
|
|
|
|
|
|
{ |
162
|
6
|
|
|
6
|
0
|
2214
|
my $self = shift; |
163
|
6
|
|
|
|
|
29
|
return('01_capable'); |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# Purpose: Return manager capability information |
167
|
|
|
|
|
|
|
# Usage: get_manager_capabilities |
168
|
|
|
|
|
|
|
sub get_manager_capabilities |
169
|
|
|
|
|
|
|
{ |
170
|
|
|
|
|
|
|
# All capabilites as of 01_capable |
171
|
6
|
|
|
6
|
0
|
35
|
return(['LIST_DPI',]) |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# -- Private methods -- |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# Purpose: Wraps _addParsedEvent in Date::HolidayParser so that an iCalendar version |
178
|
|
|
|
|
|
|
# is also created at the same time. |
179
|
|
|
|
|
|
|
around '_addParsedEvent' => sub |
180
|
|
|
|
|
|
|
{ |
181
|
|
|
|
|
|
|
my $orig = shift; |
182
|
|
|
|
|
|
|
my $self = shift; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
my($FinalParsing,$final_mon,$final_mday,$HolidayName,$holidayType,$FinalYDay,$PosixYear) = @_; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
my $UID = $self->_event_to_iCalendar($FinalYDay,$PosixYear,$HolidayName); |
187
|
|
|
|
|
|
|
my $Year = $PosixYear+1900; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
if(not $self->_iCal_cache->{$Year}->{$final_mon}{$final_mday}{'DAY'}) |
190
|
|
|
|
|
|
|
{ |
191
|
|
|
|
|
|
|
$self->_iCal_cache->{$Year}->{$final_mon}{$final_mday}{'DAY'} = []; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
push(@{$self->_iCal_cache->{$Year}->{$final_mon}{$final_mday}{'DAY'}}, $UID); |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
return $self->$orig(@_); |
196
|
|
|
|
|
|
|
}; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Purpose: Generate an iCalendar entry |
199
|
|
|
|
|
|
|
# Usage: this->_event_to_iCalendar(UNIXTIME, NAME); |
200
|
|
|
|
|
|
|
sub _event_to_iCalendar |
201
|
|
|
|
|
|
|
{ |
202
|
44
|
|
|
44
|
|
56
|
my $self = shift; |
203
|
44
|
|
|
|
|
56
|
my $FinalYDay = shift; |
204
|
44
|
|
|
|
|
57
|
my $PosixYear = shift; |
205
|
44
|
|
|
|
|
54
|
my $name = shift; |
206
|
44
|
|
|
|
|
252
|
$name =~ s/\s/-/g; |
207
|
|
|
|
|
|
|
|
208
|
44
|
|
|
|
|
492
|
my $unixtime = POSIX::mktime(0, 0, 0, $FinalYDay, 0, $PosixYear); |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# Generate the UID of the event, this is simply a |
211
|
44
|
|
|
|
|
132
|
my $sum = unpack('%32C*', $name); |
212
|
|
|
|
|
|
|
# This should be unique enough for our needs. |
213
|
|
|
|
|
|
|
# We don't want it to be random, because if someone copies the events to their |
214
|
|
|
|
|
|
|
# own calendar, we want DP::iCalendar::Manager to fetch the information from |
215
|
|
|
|
|
|
|
# the changed calendar, instead of from the HolidayParser object. |
216
|
44
|
|
|
|
|
123
|
my $UID = 'D-HP-ICS-'.$FinalYDay.'-'.$PosixYear.'-'.$sum; |
217
|
|
|
|
|
|
|
|
218
|
44
|
|
|
|
|
85
|
$self->_UID_List->{$UID} = { |
219
|
|
|
|
|
|
|
UID => $UID, |
220
|
|
|
|
|
|
|
DTSTART => iCal_ConvertFromUnixTime($unixtime), |
221
|
|
|
|
|
|
|
DTEND => iCal_ConvertFromUnixTime($unixtime+86390), # Yes, this is purposefully not 86400 |
222
|
|
|
|
|
|
|
SUMMARY => $name, |
223
|
|
|
|
|
|
|
}; |
224
|
44
|
|
|
|
|
138
|
return($UID); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# The following three functions are originally from DP::iCalendar |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# Purpose: Generate an iCalendar date-time from multiple values |
230
|
|
|
|
|
|
|
# Usage: my $iCalDateTime = iCal_GenDateTime(YEAR, MONTH, DAY, TIME); |
231
|
|
|
|
|
|
|
sub iCal_GenDateTime { |
232
|
|
|
|
|
|
|
# NOTE: This version ignores $Time because it isn't used in HolidayParser |
233
|
88
|
|
|
88
|
0
|
152
|
my ($Year, $Month, $Day, $Time) = @_; |
234
|
|
|
|
|
|
|
# Fix the month and day |
235
|
88
|
|
|
|
|
150
|
my $iCalMonth = _PrefixZero($Month); |
236
|
88
|
|
|
|
|
157
|
my $iCalDay = _PrefixZero($Day); |
237
|
88
|
|
|
|
|
552
|
return("$Year$iCalMonth$iCalDay"); |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# Purpose: Generate an iCalendar date-time string from a UNIX time string |
241
|
|
|
|
|
|
|
# Usage: my $iCalDateTime = iCal_ConvertFromUnixTime(UNIX TIME); |
242
|
|
|
|
|
|
|
sub iCal_ConvertFromUnixTime { |
243
|
88
|
|
|
88
|
0
|
115
|
my $UnixTime = shift; |
244
|
88
|
|
|
|
|
605
|
my ($realsec,$realmin,$realhour,$realmday,$realmonth,$realyear,$realwday,$realyday,$realisdst) = localtime($UnixTime); |
245
|
88
|
|
|
|
|
155
|
$realyear += 1900; # Fix the year |
246
|
88
|
|
|
|
|
98
|
$realmonth++; # Fix the month |
247
|
|
|
|
|
|
|
# Return data from iCal_GenDateTime |
248
|
88
|
|
|
|
|
397
|
return(iCal_GenDateTime($realyear,$realmonth,$realmday,"$realhour:$realmin")); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# Purpose: Prefix a "0" to a number if it is only one digit. |
252
|
|
|
|
|
|
|
# Usage: my $NewNumber = PrefixZero(NUMBER); |
253
|
|
|
|
|
|
|
sub _PrefixZero { |
254
|
176
|
100
|
|
176
|
|
559
|
if ($_[0] =~ /^\d$/) { |
255
|
88
|
|
|
|
|
221
|
return("0$_[0]"); |
256
|
|
|
|
|
|
|
} |
257
|
88
|
|
|
|
|
180
|
return($_[0]); |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
# End of Date::HolidayParser::iCalendar |
261
|
|
|
|
|
|
|
1; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
__END__ |