File Coverage

blib/lib/Bank/Holidays.pm
Criterion Covered Total %
statement 63 72 87.5
branch 22 34 64.7
condition 2 6 33.3
subroutine 9 9 100.0
pod 0 3 0.0
total 96 124 77.4


line stmt bran cond sub pod time code
1             package Bank::Holidays;
2              
3 2     2   1117 use 5.006001;
  2         4  
4 2     2   8 use strict;
  2         2  
  2         36  
5 2     2   13 use warnings;
  2         2  
  2         55  
6 2     2   1283 use HTML::TableExtract;
  2         24645  
  2         16  
7 2     2   1534 use LWP::UserAgent;
  2         76953  
  2         68  
8 2     2   1653 use DateTime;
  2         488160  
  2         1279  
9              
10             our $VERSION = '0.82';
11              
12             sub new {
13 2     2 0 2480 my ( $package, %params ) = @_;
14              
15 2         3 my $param;
16             $param->{dt} =
17             $params{dt}
18             ? $params{dt}
19             : $params{date}
20             ? $params{date}
21 2 50       9 : DateTime->now;
    100          
22 2         77 $param->{holidays} = reserve_holidays();
23 2         19 bless $param, $package;
24             }
25              
26             sub reserve_holidays() {
27 2     2 0 12 my $te = HTML::TableExtract->new();
28              
29 2         222 my $ua = LWP::UserAgent->new();
30              
31 2         2653 $ua->timeout(120);
32              
33 2   33     26 my $home = $ENV{HOME} || $ENV{LOCALAPPDATA};
34              
35 2 50       41 unless ( -d $home . "/.bankholidays" ) {
36 0         0 mkdir( $home . "/.bankholidays" );
37             }
38              
39 2         5 my $cache = $home . "/.bankholidays/frbholidays.html";
40              
41             # Cache the content from the FRB since holdays are unlikely to
42             # change from day to day (or year to year)
43              
44 2         3 my $content;
45              
46 2 50 33     43 if ( -f $cache && ( time() - ( stat($cache) )[9] ) < 86400 ) {
47 2 50       60 open( my $fh, "<", $cache ) or die $!;
48 2         9 local $/ = undef;
49 2         54 $content = <$fh>;
50 2         19 close $fh;
51             }
52             else {
53 0         0 my $url = 'http://www.federalreserve.gov/aboutthefed/k8.htm';
54              
55 0         0 my $request = HTTP::Request->new( 'GET', $url );
56              
57 0         0 my $response = $ua->request($request);
58              
59 0         0 $content = $response->content();
60              
61 0 0       0 open( my $fh, ">", $cache ) or die $!;
62 0         0 print $fh $content;
63 0         0 close $fh;
64             }
65              
66 2         11 $te->parse($content);
67              
68 2         21673 my $months = {
69             'January' => 1,
70             'February' => 2,
71             'March' => 3,
72             'April' => 4,
73             'May' => 5,
74             'June' => 6,
75             'July' => 7,
76             'August' => 8,
77             'September' => 9,
78             'October' => 10,
79             'November' => 11,
80             'December' => 12
81             };
82              
83 2         5 my $holidays;
84              
85 2         7 foreach my $ts ( $te->tables ) {
86 6 100       46 next if ( $ts->coords ) != 2;
87 2         9 my @colyears;
88 2         6 foreach my $row ( $ts->rows ) {
89              
90 22 50       1109 next unless @$row;
91 22 50       20 map { s/\r|\n//g if $_ } @$row;
  132         606  
92 22         18 my $colcount = 0;
93 22         21 foreach my $col (@$row) {
94 132 50       147 if ($col) {
95 132 100       407 if ( $col =~ /(\d{4})/ ) {
    100          
96 10         19 $colyears[$colcount] = $1;
97             }
98             elsif ( $col =~ /(\w+)\s(\d{1,2})(\*?)/ ) {
99 100         62 push @{ $holidays->{ $colyears[$colcount] }->{ $months->{$1} } },
  100         396  
100             {
101             day => $2,
102             satflag => $3
103             };
104              
105             }
106             }
107 132         117 $colcount++;
108             }
109             }
110             }
111 2         249 return $holidays;
112             }
113              
114             sub is_holiday {
115 6     6 0 1125 my ( $param, %opts ) = @_;
116              
117 6 50       17 if ( $opts{date} ) {
118 0         0 $param->{dt} = $opts{date};
119             }
120              
121 6 100       81 if ( $opts{Tomorrow} ) {
    100          
122 2         11 $param->{dt}->add( days => 1 );
123             }
124             elsif ( $opts{Yesterday} ) {
125 2         9 $param->{dt}->subtract( days => 1 );
126             }
127 6 50       2349 return 1 if $param->{dt}->dow == 7;
128 6         25 foreach my $holiday ( @{ $param->{holidays}->{ $param->{dt}->year }->{ int( $param->{dt}->month ) } } ) {
  6         15  
129 6 50       58 return 1 if int( $param->{dt}->day ) == $holiday->{day};
130             }
131 6         46 return undef;
132             }
133              
134             # Preloaded methods go here.
135              
136             1;
137             __END__