File Coverage

blib/lib/Date/Korean.pm
Criterion Covered Total %
statement 84 98 85.7
branch 23 34 67.6
condition 19 33 57.5
subroutine 14 15 93.3
pod 4 4 100.0
total 144 184 78.2


line stmt bran cond sub pod time code
1             package Date::Korean;
2            
3 2     2   24342 use strict;
  2         3  
  2         77  
4 2     2   10 use warnings;
  2         4  
  2         57  
5 2     2   2001 use version; our $VERSION = qv('0.0.2');
  2         5124  
  2         13  
6 2     2   199 use base 'Exporter';
  2         4  
  2         274  
7 2     2   3144 use DateTime;
  2         415840  
  2         84  
8 2     2   1980 use DateTime::Calendar::Julian;
  2         1608  
  2         63  
9 2     2   1915 use Date::ISO8601 qw/cjdn_to_ymd/;
  2         5600  
  2         176  
10 2     2   2352 use Date::Korean::Table;
  2         9  
  2         518  
11 2     2   27 use Carp;
  2         5  
  2         2610  
12            
13             our @EXPORT = qw/get_ganzi get_ganzi_ko sol2lun lun2sol/;
14            
15             sub _calculate_ganzi {
16 12     12   30 my($year,$month,$day,$leap) = @_;
17            
18 12         40 my @ganzis = ( ($year+56)%60, ($year*12+$month+13)%60 );
19 12         28 ($year,$month,$day) = lun2sol($year,$month,$day,$leap);
20             # mjd(Modified Julian Date)
21 12         546 my $mjd = DateTime->new(year=>$year,month=>$month,day=>$day)->mjd;
22             # solar 1582-10-15 -> mjd:-100840
23 12 100       2638 if ($mjd < -100840) {
24 6         23 $mjd += DateTime::Calendar::Julian
25             ->new(year=>$year,month=>$month,day=>$day)
26             ->gregorian_deviation;
27             }
28 12         1405 push @ganzis, ($mjd+50)%60;
29 12         41 return @ganzis;
30             }
31            
32             sub get_ganzi {
33 12     12 1 6631 return map { $CELESTIAL_STEMS[$_%10].$TERRESTRIAL_BRANCHES[$_%12] }
  36         123  
34             _calculate_ganzi(@_);
35             }
36            
37             sub get_ganzi_ko {
38 0     0 1 0 return map { $CELESTIAL_STEMS_KO[$_%10].$TERRESTRIAL_BRANCHES_KO[$_%12] }
  0         0  
39             _calculate_ganzi(@_);
40             }
41            
42             sub sol2lun {
43            
44 12     12 1 5775 my($year,$month,$day) = @_;
45            
46 12         19 my $days;
47 12         17 eval {
48             # Chronological Julian Day(cjd)
49 12         98 $days = DateTime->new(year=>$year,month=>$month,day=>$day)->jd+0.5;
50             };
51 12 50       2686 if ($@) { # Maybe valid Julian date.
52 0 0       0 if ( $year<=1582 ) {
53 0         0 eval {
54 0         0 $days = DateTime::Calendar::Julian
55             ->new(year=>$year,month=>$month,day=>$day)->jd+0.5;
56             };
57 0 0       0 if ($@) {
58 0         0 croak "Invalid date.";
59             }
60             }
61             else {
62 0         0 croak "Invalid date.";
63             }
64             }
65             # solar 1582-10-15 -> cjd:2299161 ,After this are gregorian calendar range.
66 12 100       35 if ( $days < 2299161 ) { # julian calendar range
67             # gregorian 1582-10~05 ~ 1582-10-14 dates do not exist.
68 6 50 66     31 if ( $year==1582 && $month==10 && $day>=5 && $day<=14) {
      66        
      33        
69 0         0 croak "The gregorian date does not exist\n";
70             }
71 6         36 $days = DateTime::Calendar::Julian
72             ->new(year=>$year,month=>$month,day=>$day)->jd+0.5;
73             }
74            
75 12 50 33     1656 if ( $days<$MINDATE || $days>$MAXDATE ) {
76 0         0 croak "The date is out of range."
77             }
78            
79 12         18 $days -= $MINDATE;
80 12         35 $month = _bisect(\@MONTHTABLE,$days);
81 12         29 $year = _bisect(\@YEARTABLE,$month);
82 12         31 ($month,$day) = ( $month-$YEARTABLE[$year]+1, $days-$MONTHTABLE[$month]+1);
83 12         13 my $leap;
84 12 100 100     55 if ( $LEAPTABLE[$year]!=0 && $LEAPTABLE[$year]<=$month ) {
85 6 100       15 if ( $LEAPTABLE[$year] == $month ) {
86 4         9 $leap = 1;
87             }
88             else {
89 2         4 $leap = 0;
90             }
91 6         7 $month -= 1;
92             }
93             else {
94 6         7 $leap = 0;
95             }
96            
97 12         79 return ( $year+$BASEYEAR, $month, $day, $leap );
98             }
99            
100             sub lun2sol {
101            
102 24     24 1 44 my($year,$month,$day,$leap) = @_;
103            
104 24         27 $year -= $BASEYEAR;
105            
106 24 50 33     206 unless ( $year>=0 && $year< $#YEARTABLE ) {
107 0         0 croak "Year is out of range.";
108             }
109            
110 24 50 33     93 unless ( $month>=1 && $month <=12 ) {
111 0         0 croak "Month is out of range.";
112             }
113            
114 24 50 66     77 if ( $leap!=0 && ($LEAPTABLE[$year]-1)!=$month ) {
115 0         0 croak "Wrong leap month.";
116             }
117            
118 24         41 my $months = $YEARTABLE[$year] + $month - 1;
119            
120 24 100 66     133 if ( $leap==1 && ($month+1)==$LEAPTABLE[$year] ) {
    100 100        
121 8         14 $months += 1;
122             }
123             elsif ( $LEAPTABLE[$year]!=0 && $LEAPTABLE[$year]<=$month ) {
124 4         6 $months += 1;
125             }
126            
127 24         36 my $days = $MONTHTABLE[$months] + $day -1;
128            
129 24 50 33     132 if ( $day<1 || $days>=$MONTHTABLE[$months+1]) {
130 0         0 croak "Wrong day.";
131             }
132            
133             # 1582-10-15 -> cjd(chronical julian date):2299161
134 24 100       76 if ( ($days+$MINDATE) < 2299161 ) {
135 12         43 my ($y,$m,$d) = cjdn_to_ymd($days+$MINDATE);
136 12         574 my $deviation = DateTime::Calendar::Julian
137             ->new(year=>$y,month=>$m,day=>$d)
138             ->gregorian_deviation;
139 12         3072 return cjdn_to_ymd($days+$MINDATE-$deviation);
140             }
141             else {
142 12         40 return cjdn_to_ymd($days+$MINDATE);
143             }
144             }
145            
146             sub _bisect {
147 24     24   32 my ($a,$x) = @_;
148 24         25 my $lo = 0;
149 24         24 my $hi = $#{$a};
  24         40  
150 24         53 while ( $lo < $hi ) {
151 270         298 my $mid = int( ($lo+$hi)/2 );
152 270 100       417 if ( $x < $a->[$mid] ) {
153 176         293 $hi = $mid;
154             }
155             else {
156 94         152 $lo = $mid + 1;
157             }
158             }
159            
160 24         41 return $lo-1;
161             }
162            
163             1;
164             __END__