File Coverage

blib/lib/Date/Japanese/Holiday.pm
Criterion Covered Total %
statement 81 89 91.0
branch 17 24 70.8
condition 29 50 58.0
subroutine 21 21 100.0
pod 1 13 7.6
total 149 197 75.6


line stmt bran cond sub pod time code
1             package Date::Japanese::Holiday;
2              
3 9     9   281117 use strict;
  9         23  
  9         379  
4 9     9   8964 use Time::JulianDay ();
  9         56886  
  9         254  
5 9     9   8165 use Date::Calc ();
  9         446716  
  9         319  
6             require Exporter;
7 9     9   113 use vars qw($VERSION @EXPORT_OK);
  9         20  
  9         566  
8 9     9   51 use base qw(Date::Simple Exporter);
  9         20  
  9         10497  
9             @EXPORT_OK = qw(is_japanese_holiday);
10              
11             $VERSION = '0.05';
12              
13             # Too many magic numbers..
14 9     9   79280 use vars qw(%FIXED_HOLIDAY_TABLE);
  9         25  
  9         444  
15 9     9   52 use constant FIRST_DAY => 2432753;
  9         19  
  9         14448  
16             %FIXED_HOLIDAY_TABLE = (
17             '01-01' => [FIRST_DAY, 0],
18             '01-15' => [FIRST_DAY, 2451544],
19             '02-11' => [2439469, 0],
20             '04-29' => [FIRST_DAY, 0],
21             '05-03' => [FIRST_DAY, 0],
22             '05-05' => [FIRST_DAY, 0],
23             '07-20' => [2450084, 2452640],
24             '09-15' => [2439302, 2452640],
25             '10-10' => [2439302, 2451544],
26             '11-03' => [FIRST_DAY, 0],
27             '11-23' => [FIRST_DAY, 0],
28             '12-23' => [2447575, 0],
29             );
30              
31             sub Date::Simple::is_holiday {
32 40     40 0 2387 my $self = shift;
33             return
34 40   100     99 day_of_week($self) == 7 || is_basic_holiday($self) ||
35             is_change_holiday($self) || is_between_holiday($self) ||
36             is_special_holiday($self);
37             }
38              
39             sub is_basic_holiday {
40 50     50 0 1285 my $self = shift;
41 50   100     105 return is_fixed_holiday($self) || is_float_holiday($self) || undef;
42             }
43              
44             sub is_change_holiday {
45 11     11 0 164 my $self = shift;
46 11         112 my $prev = $self->prev;
47 11   100     349 return julian_day($self) >= 2441785 &&
48             is_basic_holiday($prev) && day_of_week($prev) == 7;
49             }
50              
51             sub is_between_holiday {
52 5     5 0 86 my $self = shift;
53 5         27 my $next = $self->next;
54 5         147 my $prev = $self->prev;
55 5 100 33     97 julian_day($self) >= 2446427 &&
      33        
      66        
56             day_of_week($self) != 7 &&
57             !is_change_holiday($self) &&
58             is_basic_holiday($prev) && is_basic_holiday($next);
59             }
60              
61             sub is_special_holiday {
62 4     4 0 61 my $self = shift;
63 4         8 my $jd = julian_day($self);
64 4         49 my $str = sprintf("%04d-%02d-%02d", $self->year, $self->month, $self->day);
65 4   100     79 return $str eq "1989-02-24" || $str eq "1990-11-12" ||
66             $str eq "1993-06-09";
67             }
68              
69             sub is_fixed_holiday {
70 50     50 0 66 my $self = shift;
71 50         279 my $dstr = sprintf("%02d-%02d", $self->month, $self->day);
72 50 100       96 return 1 if julian_day($self) == vernal_equinox($self);
73 49 100       458 return 1 if julian_day($self) == autumnal_equinox($self);
74 48 100       474 return undef unless $FIXED_HOLIDAY_TABLE{$dstr};
75 27         58 my $jd = julian_day($self);
76 27         162 my @range = @{$FIXED_HOLIDAY_TABLE{$dstr}};
  27         74  
77 27 100 100     193 if ($jd > $range[0] && (!$range[1] || $jd < $range[1])) {
      33        
78 26         267 return 1;
79             }
80 1         4 return undef;
81             }
82              
83             sub is_float_holiday {
84 22     22 0 31 my $self = shift;
85 22         38 my $jd = julian_day($self);
86             return
87 22   66     576 ($self->month == 1 &&
88             is_nth_wday($self, 2, 1) && $jd >= 2451545) ||
89             ($self->month == 7 &&
90             is_nth_wday($self, 3, 1) && $jd >= 2452641) ||
91             ($self->month == 9 &&
92             is_nth_wday($self, 3, 1) && $jd >= 2452641) ||
93             ($self->month == 10 &&
94             is_nth_wday($self, 2, 1) && $jd >= 2451545);
95             }
96              
97             sub day_of_week {
98 49     49 1 107 my $self = shift;
99 49         473 return Date::Calc::Day_of_Week($self->year, $self->month, $self->day);
100             }
101              
102             sub is_nth_wday {
103 8     8 0 10 my($self, $n, $dow) = @_;
104 8         42 my($y, $m, $d) =
105             Date::Calc::Nth_Weekday_of_Month_Year($self->year, $self->month, $dow, $n);
106 8   66     971 return $self->year == $y && $self->month == $m && $self->day == $d;
107             }
108              
109             sub julian_day {
110 168     168 0 207 my $self = shift;
111 168         898 return Time::JulianDay::julian_day($self->year, $self->month, $self->day);
112             }
113              
114             sub _deq {
115 99     99   146 my($self, $a, $b) = @_;
116 99         181 my $y = $self->year;
117 99         240 my $d = int($a + 0.242194 * ($y - 1980) - int(($y - $b) / 4));
118 99         421 return $d;
119             }
120              
121             sub vernal_equinox {
122 50     50 0 384 my $self = shift;
123 50         116 my $y = $self->year;
124 50         84 my($a, $b);
125 50 50 33     298 if ($y >= 1900 && $y <= 1979) {
126 0         0 $a = 20.8357; $b = 1983.0;
  0         0  
127             }
128 50 50 33     210 if ($y >= 1980 && $y <= 2099) {
129 50         74 $a = 20.8431; $b = 1980.0;
  50         66  
130             }
131 50 50 33     123 if ($y >= 2100 && $y <= 2150) {
132 0         0 $a = 21.8510; $b = 1980.0;
  0         0  
133             }
134 50         103 return Time::JulianDay::julian_day($y, 3, _deq($self, $a, $b));
135             }
136              
137             sub autumnal_equinox {
138 49     49 0 477 my $self = shift;
139 49         102 my $y = $self->year;
140 49 50 33     232 if ($y >= 1900 && $y <= 1979) {
141 0         0 $a = 23.2588; $b = 1983.0;
  0         0  
142             }
143 49 50 33     190 if ($y >= 1980 && $y <= 2099) {
144 49         80 $a = 23.2488; $b = 1980.0;
  49         56  
145             }
146 49 50 33     179 if ($y >= 2100 && $y <= 2150) {
147 0         0 $a = 24.2488; $b = 1980.0;
  0         0  
148             }
149 49         203 return Time::JulianDay::julian_day($y, 9, _deq($self, $a, $b));
150             }
151              
152             # functional interface
153             sub is_japanese_holiday {
154 2     2 0 22 my($y, $m, $d) = @_;
155 2         23 my $obj = __PACKAGE__->new($y, $m, $d);
156 2 50       176 return $obj->is_holiday ? $obj : undef;
157             }
158              
159             1;
160             __END__