| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Calendar::Any::Chinese; |
|
2
|
|
|
|
|
|
|
{ |
|
3
|
|
|
|
|
|
|
$Calendar::Any::Chinese::VERSION = '0.5'; |
|
4
|
|
|
|
|
|
|
} |
|
5
|
1
|
|
|
1
|
|
19778
|
use base 'Calendar::Any'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
555
|
|
|
6
|
1
|
|
|
1
|
|
7
|
use Carp; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
62
|
|
|
7
|
1
|
|
|
1
|
|
527
|
use Calendar::Any::Gregorian; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
32
|
|
|
8
|
1
|
|
|
1
|
|
680
|
use Calendar::Any::Util::Lunar; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
2956
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
sub new { |
|
11
|
1
|
|
|
1
|
1
|
12
|
my $_class = shift; |
|
12
|
1
|
|
33
|
|
|
7
|
my $class = ref $_class || $_class; |
|
13
|
1
|
|
|
|
|
2
|
my $self = {}; |
|
14
|
1
|
|
|
|
|
2
|
bless $self, $class; |
|
15
|
1
|
50
|
|
|
|
4
|
if ( @_ ) { |
|
16
|
1
|
|
|
|
|
2
|
my %arg; |
|
17
|
1
|
50
|
|
|
|
6
|
if ( $_[0] =~ /-\D/ ) { |
|
18
|
0
|
|
|
|
|
0
|
%arg = @_; |
|
19
|
|
|
|
|
|
|
} else { |
|
20
|
1
|
50
|
|
|
|
4
|
if ( $#_ > 0 ) { |
|
21
|
1
|
|
|
|
|
9
|
$arg{$_} = shift for qw(-cycle -year -month -day); |
|
22
|
|
|
|
|
|
|
} else { |
|
23
|
0
|
|
|
|
|
0
|
return $self->from_absolute(@_); |
|
24
|
|
|
|
|
|
|
} |
|
25
|
|
|
|
|
|
|
} |
|
26
|
1
|
|
|
|
|
2
|
foreach ( qw(-cycle -year -month -day) ) { |
|
27
|
4
|
50
|
|
|
|
84
|
$self->{substr($_, 1)} = $arg{$_} if exists $arg{$_}; |
|
28
|
|
|
|
|
|
|
} |
|
29
|
1
|
|
|
|
|
4
|
$self->absolute_date(); |
|
30
|
|
|
|
|
|
|
} |
|
31
|
1
|
|
|
|
|
3
|
return $self; |
|
32
|
|
|
|
|
|
|
} |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub from_absolute { |
|
35
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
36
|
0
|
|
|
|
|
0
|
my $absdate = shift; |
|
37
|
0
|
|
|
|
|
0
|
$self->{absolute} = $absdate; |
|
38
|
0
|
|
|
|
|
0
|
my $date = Calendar::Any::Gregorian->new($absdate); |
|
39
|
0
|
|
|
|
|
0
|
$self->{gdate} = $date; |
|
40
|
0
|
|
|
|
|
0
|
my $cyear = $date->year+2695; |
|
41
|
0
|
|
|
|
|
0
|
my @list = (@{_year($date->year-1)}, |
|
|
0
|
|
|
|
|
0
|
|
|
42
|
0
|
|
|
|
|
0
|
@{_year($date->year)}, |
|
43
|
0
|
|
|
|
|
0
|
@{_year($date->year+1)}); |
|
44
|
0
|
|
|
|
|
0
|
foreach ( 0..$#list ) { |
|
45
|
0
|
0
|
|
|
|
0
|
if ( $list[$_]->[0] == 1 ) { |
|
46
|
0
|
|
|
|
|
0
|
$cyear++; |
|
47
|
|
|
|
|
|
|
} |
|
48
|
0
|
0
|
|
|
|
0
|
if ( $list[$_+1]->[1] > $absdate ) { |
|
49
|
0
|
|
|
|
|
0
|
$date = $list[$_]; |
|
50
|
0
|
|
|
|
|
0
|
last; |
|
51
|
|
|
|
|
|
|
} |
|
52
|
|
|
|
|
|
|
} |
|
53
|
0
|
|
|
|
|
0
|
$self->{cycle} = int(($cyear-1)/60); |
|
54
|
0
|
|
|
|
|
0
|
$self->{year} = _mod($cyear, 60); |
|
55
|
0
|
|
|
|
|
0
|
$self->{month} = $date->[0]; |
|
56
|
0
|
|
|
|
|
0
|
$self->{day} = $absdate - $date->[1] + 1; |
|
57
|
0
|
|
|
|
|
0
|
return $self; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub absolute_date { |
|
61
|
5
|
|
|
5
|
0
|
6
|
my $self = shift; |
|
62
|
5
|
100
|
|
|
|
14
|
if (exists $self->{absolute} ) { |
|
63
|
4
|
|
|
|
|
36
|
return $self->{absolute}; |
|
64
|
|
|
|
|
|
|
} |
|
65
|
1
|
|
|
|
|
4
|
my ($cycle, $year, $month, $day) = ($self->{cycle}, $self->{year}, $self->{month}, $self->{day}); |
|
66
|
1
|
|
|
|
|
4
|
my $gyear = 60*($cycle-1)+$year-1-2636; |
|
67
|
1
|
|
|
|
|
4
|
my $monthday = _assoc_month($month, [_memq_month(1, _year($gyear)), @{_year($gyear+1)}]); |
|
|
1
|
|
|
|
|
3
|
|
|
68
|
1
|
|
|
|
|
6
|
$self->{absolute} = $day-1+$monthday->[1]; |
|
69
|
1
|
|
|
|
|
4
|
$self->assert_date(); |
|
70
|
1
|
|
|
|
|
4
|
return $self->{absolute}; |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
|
|
73
|
0
|
|
|
0
|
1
|
0
|
sub cycle { shift->{cycle}; } |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub is_leap_year { |
|
76
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
77
|
0
|
|
|
|
|
0
|
my $list = _year_month_list($self->cycle, $self->year); |
|
78
|
0
|
|
|
|
|
0
|
return $#{$list} == 12; |
|
|
0
|
|
|
|
|
0
|
|
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
1
|
|
|
1
|
1
|
6
|
sub gyear { shift->gdate->year; } |
|
82
|
|
|
|
|
|
|
|
|
83
|
1
|
|
|
1
|
1
|
3
|
sub gmonth { shift->gdate->month; } |
|
84
|
|
|
|
|
|
|
|
|
85
|
1
|
|
|
1
|
1
|
4
|
sub gday { shift->gdate->day; } |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub gdate { |
|
88
|
3
|
|
|
3
|
1
|
4
|
my $self = shift; |
|
89
|
3
|
100
|
|
|
|
7
|
if ( !exists $self->{gdate} ) { |
|
90
|
1
|
|
|
|
|
3
|
$self->{gdate} = Calendar::Any::Gregorian->new($self->absolute_date); |
|
91
|
|
|
|
|
|
|
} |
|
92
|
3
|
|
|
|
|
17
|
return $self->{gdate}; |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub last_day_of_month { |
|
96
|
1
|
|
|
1
|
1
|
3
|
my $self = shift; |
|
97
|
1
|
50
|
|
|
|
4
|
my $date = Calendar::Any::Util::Lunar::new_moon_date |
|
98
|
|
|
|
|
|
|
( $self->day==1 ? $self->absolute_date+1 : $self, |
|
99
|
|
|
|
|
|
|
timezone(Calendar::Any::Gregorian->new($self->absolute_date)->year)); |
|
100
|
1
|
|
|
|
|
4
|
return int($date-1-$self->absolute_date + $self->day); |
|
101
|
|
|
|
|
|
|
} |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub year_month_list { |
|
104
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
105
|
0
|
|
|
|
|
0
|
return _year_month_list($self->cycle, $self->year); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub timezone { |
|
109
|
1
|
|
|
1
|
1
|
2
|
my $year = shift; |
|
110
|
1
|
50
|
33
|
|
|
11
|
return ((defined $year && $year >= 1928) ? 480 : 465 + 40.0/60.0 ); |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub next_jieqi_date { |
|
114
|
0
|
|
|
0
|
1
|
0
|
Calendar::Any::Util::Solar::next_longitude_date($_[0], 15, $_[1]); |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub assert_date { |
|
118
|
1
|
|
|
1
|
0
|
2
|
my $self = shift; |
|
119
|
1
|
50
|
33
|
|
|
11
|
if ( $self->year < 1 || $self->year > 60 ) { |
|
120
|
0
|
|
|
|
|
0
|
confess('Not a valid year: should not from 1 to 60 for ' . ref $self); |
|
121
|
|
|
|
|
|
|
} |
|
122
|
1
|
50
|
33
|
|
|
8
|
if ( $self->month < 1 || $self->month > 12 ) { |
|
123
|
0
|
|
|
|
|
0
|
confess(sprintf('Not a valid month %d: should from 1 to 12 for %s', $self->month, ref $self)); |
|
124
|
|
|
|
|
|
|
} |
|
125
|
1
|
50
|
33
|
|
|
7
|
if ( $self->day < 1 || $self->day > $self->last_day_of_month() ) { |
|
126
|
0
|
|
|
|
|
0
|
confess(sprintf('Not a valid day %d: should from 1 to %d in %d, %d for %s', |
|
127
|
|
|
|
|
|
|
$self->day, $self->last_day_of_month, $self->month, $self->year, ref $self)); |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
#========================================================== |
|
132
|
|
|
|
|
|
|
# Format calendar |
|
133
|
|
|
|
|
|
|
#========================================================== |
|
134
|
|
|
|
|
|
|
our @celestial_stem = qw(甲 乙 丙 丁 戊 已 庚 辛 壬 癸); |
|
135
|
|
|
|
|
|
|
our @terrestrial_branch = qw(子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥); |
|
136
|
|
|
|
|
|
|
our @weekday_name = qw(日 一 二 三 四 五 六); |
|
137
|
|
|
|
|
|
|
our @month_name = |
|
138
|
|
|
|
|
|
|
qw(正月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 腊月); |
|
139
|
|
|
|
|
|
|
our @day_name = qw |
|
140
|
|
|
|
|
|
|
(初一 初二 初三 初四 初五 初六 初七 初八 初九 初十 |
|
141
|
|
|
|
|
|
|
十一 十二 十三 十四 十五 十六 十七 十八 十九 二十 |
|
142
|
|
|
|
|
|
|
廿一 廿二 廿三 廿四 廿五 廿六 廿七 廿八 廿九 三十 |
|
143
|
|
|
|
|
|
|
卅一); |
|
144
|
|
|
|
|
|
|
our @zodiac_name = qw(鼠 牛 虎 兔 龙 蛇 马 羊 猴 鸡 狗 猪); |
|
145
|
|
|
|
|
|
|
our @jieqi_name = qw |
|
146
|
|
|
|
|
|
|
(小寒 大寒 立春 雨水 惊蛰 春分 |
|
147
|
|
|
|
|
|
|
清明 谷雨 立夏 小满 芒种 夏至 |
|
148
|
|
|
|
|
|
|
小暑 大暑 立秋 处暑 白露 秋分 |
|
149
|
|
|
|
|
|
|
寒露 霜降 立冬 小雪 大雪 冬至); |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub day_name { |
|
152
|
0
|
|
|
0
|
0
|
0
|
return $day_name[shift->day-1]; |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub month_name { |
|
156
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
157
|
0
|
|
|
|
|
0
|
my $month = $self->month; |
|
158
|
0
|
0
|
|
|
|
0
|
if ( _is_int($month) ) { |
|
159
|
0
|
|
|
|
|
0
|
$month_name[$month-1]; |
|
160
|
|
|
|
|
|
|
} else { |
|
161
|
0
|
|
|
|
|
0
|
return "闰".$month_name[$month-1]; |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub weekday_name { |
|
166
|
0
|
|
|
0
|
1
|
0
|
return "星期".$weekday_name[shift->weekday]; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub sexagesimal_name { |
|
170
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
171
|
0
|
|
|
|
|
0
|
my $year = $self->year-1; |
|
172
|
0
|
|
|
|
|
0
|
return $celestial_stem[$year%10] . $terrestrial_branch[$year%12]; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub zodiac_name { |
|
176
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
177
|
0
|
|
|
|
|
0
|
my $year = $self->year-1; |
|
178
|
0
|
|
|
|
|
0
|
return $zodiac_name[$year%12]; |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
0
|
|
|
0
|
0
|
0
|
sub format_Y { shift->gyear } |
|
182
|
0
|
|
|
0
|
0
|
0
|
sub format_S { shift->sexagesimal_name } |
|
183
|
0
|
|
|
0
|
0
|
0
|
sub format_D { shift->day_name } |
|
184
|
0
|
|
|
0
|
0
|
0
|
sub format_Z { shift->zodiac_name } |
|
185
|
0
|
|
|
0
|
0
|
0
|
sub format_m { sprintf("%02d", shift->gmonth) } |
|
186
|
0
|
|
|
0
|
0
|
0
|
sub format_d { sprintf("%02d", shift->gday) } |
|
187
|
|
|
|
|
|
|
our $default_format = "%Y年%m月%d日 %W %S%Z年%M%D"; |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
#========================================================== |
|
190
|
|
|
|
|
|
|
# Private functions |
|
191
|
|
|
|
|
|
|
#========================================================== |
|
192
|
|
|
|
|
|
|
#========================================================== |
|
193
|
|
|
|
|
|
|
# Input : chinese year cycle, year |
|
194
|
|
|
|
|
|
|
# Output : the array of month in the chinese year |
|
195
|
|
|
|
|
|
|
# Desc : |
|
196
|
|
|
|
|
|
|
#========================================================== |
|
197
|
|
|
|
|
|
|
sub _year_month_list { |
|
198
|
0
|
|
|
0
|
|
0
|
my ($cycle, $year) = @_; |
|
199
|
0
|
|
|
|
|
0
|
my $date = __PACKAGE__->new($cycle, $year, 1, 1); |
|
200
|
0
|
|
|
|
|
0
|
$year = $date->gyear; |
|
201
|
0
|
|
|
|
|
0
|
my $list1 = _year($year); |
|
202
|
0
|
|
|
|
|
0
|
my $list2 = _year($year+1); |
|
203
|
0
|
|
|
|
|
0
|
my @list = _memq_month(1, $list1); |
|
204
|
0
|
|
|
|
|
0
|
foreach ( @$list2 ) { |
|
205
|
0
|
0
|
|
|
|
0
|
last if $_->[0]==1; |
|
206
|
0
|
|
|
|
|
0
|
push @list, $_; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
0
|
|
|
|
|
0
|
return \@list; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
#========================================================== |
|
212
|
|
|
|
|
|
|
# Input : x, y |
|
213
|
|
|
|
|
|
|
# Output : x modulo y, range from 1-y |
|
214
|
|
|
|
|
|
|
# Desc : like operator %, but instead of 0, return the exclusive y |
|
215
|
|
|
|
|
|
|
#========================================================== |
|
216
|
|
|
|
|
|
|
sub _mod { |
|
217
|
0
|
0
|
|
0
|
|
0
|
$_[0] % $_[1] || $_[1]; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub _is_int { |
|
221
|
0
|
|
|
0
|
|
0
|
$_[0]-int($_[0])==0; |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
#========================================================== |
|
225
|
|
|
|
|
|
|
# Input : month, an array of month list |
|
226
|
|
|
|
|
|
|
# Output : the month list from month |
|
227
|
|
|
|
|
|
|
# Desc : eg, _memq_month(2, [[12, 726464], [1, 726494], [2, 726523], [3, 726553], ...]) |
|
228
|
|
|
|
|
|
|
# return [[2, 726523], [3, 726553], ...] |
|
229
|
|
|
|
|
|
|
#========================================================== |
|
230
|
|
|
|
|
|
|
sub _memq_month { |
|
231
|
1
|
|
|
1
|
|
2
|
my ($month, $list) = @_; |
|
232
|
1
|
|
|
|
|
2
|
my $i = 0; |
|
233
|
1
|
|
|
|
|
4
|
for ( ; $i<=$#$list; $i++ ) { |
|
234
|
2
|
100
|
|
|
|
8
|
last if ($list->[$i][0] == $month); |
|
235
|
|
|
|
|
|
|
} |
|
236
|
1
|
|
|
|
|
4
|
return @{$list}[$i..$#$list]; |
|
|
1
|
|
|
|
|
12
|
|
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
#========================================================== |
|
240
|
|
|
|
|
|
|
# Input : month, an array of month list |
|
241
|
|
|
|
|
|
|
# Output : the month in the list |
|
242
|
|
|
|
|
|
|
# Desc : eg, _assoc_month(2, [[12, 726464], [1, 726494], [2, 726523], [3, 726553], ...]) |
|
243
|
|
|
|
|
|
|
# return [2, 726523] |
|
244
|
|
|
|
|
|
|
#========================================================== |
|
245
|
|
|
|
|
|
|
sub _assoc_month { |
|
246
|
1
|
|
|
1
|
|
1
|
my ($month, $list) = @_; |
|
247
|
1
|
|
|
|
|
3
|
foreach ( @$list ) { |
|
248
|
12
|
100
|
|
|
|
22
|
return $_ if $_->[0] == $month; |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
} |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
#========================================================== |
|
253
|
|
|
|
|
|
|
# Input : Gregorian year |
|
254
|
|
|
|
|
|
|
# Output : the chinese month list of the year |
|
255
|
|
|
|
|
|
|
# Desc : The month list always range from winter solstice day in year-1 |
|
256
|
|
|
|
|
|
|
# to winter in solstice day. Usually, the month list is start |
|
257
|
|
|
|
|
|
|
# chinese month 12 in last year, but possible start from 11.5. |
|
258
|
|
|
|
|
|
|
# The month with .5 indicate that is a leap month. |
|
259
|
|
|
|
|
|
|
#========================================================== |
|
260
|
|
|
|
|
|
|
my %year_cache = ( |
|
261
|
|
|
|
|
|
|
'2000' => [ |
|
262
|
|
|
|
|
|
|
[12, 730126],[1, 730155],[2, 730185],[3, 730215],[4, 730244],[5, 730273], |
|
263
|
|
|
|
|
|
|
[6, 730303],[7, 730332],[8, 730361],[9, 730391],[10, 730420],[11, 730450] |
|
264
|
|
|
|
|
|
|
], |
|
265
|
|
|
|
|
|
|
'2001' => [ |
|
266
|
|
|
|
|
|
|
[12, 730480],[1, 730509],[2, 730539],[3, 730569],[4, 730598],[4.5, 730628], |
|
267
|
|
|
|
|
|
|
[5, 730657],[6, 730687],[7, 730716],[8, 730745],[9, 730775],[10, 730804], |
|
268
|
|
|
|
|
|
|
[11, 730834] |
|
269
|
|
|
|
|
|
|
], |
|
270
|
|
|
|
|
|
|
'2002' => [ |
|
271
|
|
|
|
|
|
|
[12, 730863],[1, 730893],[2, 730923],[3, 730953],[4, 730982],[5, 731012], |
|
272
|
|
|
|
|
|
|
[6, 731041],[7, 731071],[8, 731100],[9, 731129],[10, 731159],[11, 731188] |
|
273
|
|
|
|
|
|
|
], |
|
274
|
|
|
|
|
|
|
'2003' => [ |
|
275
|
|
|
|
|
|
|
[12, 731218],[1, 731247],[2, 731277],[3, 731307],[4, 731336],[5, 731366], |
|
276
|
|
|
|
|
|
|
[6, 731396],[7, 731425],[8, 731455],[9, 731484],[10, 731513],[11, 731543] |
|
277
|
|
|
|
|
|
|
], |
|
278
|
|
|
|
|
|
|
'2004' => [ |
|
279
|
|
|
|
|
|
|
[12, 731572],[1, 731602],[2, 731631],[2.5, 731661],[3, 731690],[4, 731720], |
|
280
|
|
|
|
|
|
|
[5, 731750],[6, 731779],[7, 731809],[8, 731838],[9, 731868],[10, 731897], |
|
281
|
|
|
|
|
|
|
[11, 731927] |
|
282
|
|
|
|
|
|
|
], |
|
283
|
|
|
|
|
|
|
'2005' => [ |
|
284
|
|
|
|
|
|
|
[12, 731956],[1, 731986],[2, 732015],[3, 732045],[4, 732074],[5, 732104], |
|
285
|
|
|
|
|
|
|
[6, 732133],[7, 732163],[8, 732193],[9, 732222],[10, 732252],[11, 732281] |
|
286
|
|
|
|
|
|
|
], |
|
287
|
|
|
|
|
|
|
'2006' => [ |
|
288
|
|
|
|
|
|
|
[12, 732311],[1, 732340],[2, 732370],[3, 732399],[4, 732429],[5, 732458], |
|
289
|
|
|
|
|
|
|
[6, 732488],[7, 732517],[7.5, 732547],[8, 732576],[9, 732606],[10, 732636], |
|
290
|
|
|
|
|
|
|
[11, 732665] |
|
291
|
|
|
|
|
|
|
], |
|
292
|
|
|
|
|
|
|
'2007' => [ |
|
293
|
|
|
|
|
|
|
[12, 732695],[1, 732725],[2, 732754],[3, 732783],[4, 732813],[5, 732842], |
|
294
|
|
|
|
|
|
|
[6, 732871],[7, 732901],[8, 732930],[9, 732960],[10, 732990],[11, 733020] |
|
295
|
|
|
|
|
|
|
], |
|
296
|
|
|
|
|
|
|
'2008' => [ |
|
297
|
|
|
|
|
|
|
[12, 733049],[1, 733079],[2, 733109],[3, 733138],[4, 733167],[5, 733197], |
|
298
|
|
|
|
|
|
|
[6, 733226],[7, 733255],[8, 733285],[9, 733314],[10, 733344],[11, 733374] |
|
299
|
|
|
|
|
|
|
], |
|
300
|
|
|
|
|
|
|
'2009' => [ |
|
301
|
|
|
|
|
|
|
[12, 733403],[1, 733433],[2, 733463],[3, 733493],[4, 733522],[5, 733551], |
|
302
|
|
|
|
|
|
|
[5.5, 733581],[6, 733610],[7, 733639],[8, 733669],[9, 733698],[10, 733728], |
|
303
|
|
|
|
|
|
|
[11, 733757] |
|
304
|
|
|
|
|
|
|
], |
|
305
|
|
|
|
|
|
|
'2010' => [ |
|
306
|
|
|
|
|
|
|
[12, 733787],[1, 733817],[2, 733847],[3, 733876],[4, 733906],[5, 733935], |
|
307
|
|
|
|
|
|
|
[6, 733965],[7, 733994],[8, 734023],[9, 734053],[10, 734082],[11, 734112] |
|
308
|
|
|
|
|
|
|
], |
|
309
|
|
|
|
|
|
|
'2011' => [ |
|
310
|
|
|
|
|
|
|
[12, 734141],[1, 734171],[2, 734201],[3, 734230],[4, 734260],[5, 734290], |
|
311
|
|
|
|
|
|
|
[6, 734319],[7, 734349],[8, 734378],[9, 734407],[10, 734437],[11, 734466] |
|
312
|
|
|
|
|
|
|
], |
|
313
|
|
|
|
|
|
|
'2012' => [ |
|
314
|
|
|
|
|
|
|
[12, 734496],[1, 734525],[2, 734555],[3, 734584],[4, 734614],[4.5, 734644], |
|
315
|
|
|
|
|
|
|
[5, 734673],[6, 734703],[7, 734732],[8, 734762],[9, 734791],[10, 734821], |
|
316
|
|
|
|
|
|
|
[11, 734850] |
|
317
|
|
|
|
|
|
|
], |
|
318
|
|
|
|
|
|
|
'2013' => [ |
|
319
|
|
|
|
|
|
|
[12, 734880],[1, 734909],[2, 734939],[3, 734968],[4, 734998],[5, 735027], |
|
320
|
|
|
|
|
|
|
[6, 735057],[7, 735087],[8, 735116],[9, 735146],[10, 735175],[11, 735205] |
|
321
|
|
|
|
|
|
|
], |
|
322
|
|
|
|
|
|
|
'2014' => [ |
|
323
|
|
|
|
|
|
|
[12, 735234],[1, 735264],[2, 735293],[3, 735323],[4, 735352],[5, 735382], |
|
324
|
|
|
|
|
|
|
[6, 735411],[7, 735441],[8, 735470],[9, 735500],[9.5, 735530],[10, 735559], |
|
325
|
|
|
|
|
|
|
[11, 735589] |
|
326
|
|
|
|
|
|
|
], |
|
327
|
|
|
|
|
|
|
'2015' => [ |
|
328
|
|
|
|
|
|
|
[12, 735618],[1, 735648],[2, 735677],[3, 735707],[4, 735736],[5, 735765], |
|
329
|
|
|
|
|
|
|
[6, 735795],[7, 735824],[8, 735854],[9, 735884],[10, 735914],[11, 735943] |
|
330
|
|
|
|
|
|
|
], |
|
331
|
|
|
|
|
|
|
'2016' => [ |
|
332
|
|
|
|
|
|
|
[12, 735973],[1, 736002],[2, 736032],[3, 736061],[4, 736091],[5, 736120], |
|
333
|
|
|
|
|
|
|
[6, 736149],[7, 736179],[8, 736208],[9, 736238],[10, 736268],[11, 736297] |
|
334
|
|
|
|
|
|
|
], |
|
335
|
|
|
|
|
|
|
'2017' => [ |
|
336
|
|
|
|
|
|
|
[12, 736327],[1, 736357],[2, 736386],[3, 736416],[4, 736445],[5, 736475], |
|
337
|
|
|
|
|
|
|
[6, 736504],[6.5, 736533],[7, 736563],[8, 736592],[9, 736622],[10, 736651], |
|
338
|
|
|
|
|
|
|
[11, 736681] |
|
339
|
|
|
|
|
|
|
], |
|
340
|
|
|
|
|
|
|
'2018' => [ |
|
341
|
|
|
|
|
|
|
[12, 736711],[1, 736741],[2, 736770],[3, 736800],[4, 736829],[5, 736859], |
|
342
|
|
|
|
|
|
|
[6, 736888],[7, 736917],[8, 736947],[9, 736976],[10, 737006],[11, 737035] |
|
343
|
|
|
|
|
|
|
], |
|
344
|
|
|
|
|
|
|
'2019' => [ |
|
345
|
|
|
|
|
|
|
[12, 737065],[1, 737095],[2, 737125],[3, 737154],[4, 737184],[5, 737213], |
|
346
|
|
|
|
|
|
|
[6, 737243],[7, 737272],[8, 737301],[9, 737331],[10, 737360],[11, 737389] |
|
347
|
|
|
|
|
|
|
], |
|
348
|
|
|
|
|
|
|
'2020' => [ |
|
349
|
|
|
|
|
|
|
[12, 737419],[1, 737449],[2, 737478],[3, 737508],[4, 737538],[4.5, 737568], |
|
350
|
|
|
|
|
|
|
[5, 737597],[6, 737627],[7, 737656],[8, 737685],[9, 737715],[10, 737744], |
|
351
|
|
|
|
|
|
|
[11, 737774] |
|
352
|
|
|
|
|
|
|
], |
|
353
|
|
|
|
|
|
|
); |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
sub _year { |
|
356
|
2
|
|
|
2
|
|
4
|
my $y = shift; |
|
357
|
2
|
50
|
|
|
|
7
|
if ( !exists $year_cache{$y} ) { |
|
358
|
0
|
|
|
|
|
0
|
$year_cache{$y} = _compute_chinese_year($y); |
|
359
|
|
|
|
|
|
|
} |
|
360
|
2
|
|
|
|
|
12
|
return $year_cache{$y}; |
|
361
|
|
|
|
|
|
|
} |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub _compute_chinese_year { |
|
364
|
0
|
|
|
0
|
|
|
my $y = shift; |
|
365
|
0
|
|
|
|
|
|
my $oldtz = $Calendar::Any::Util::Solar::timezone; |
|
366
|
0
|
|
|
|
|
|
$Calendar::Any::Util::Solar::timezone = timezone($y); |
|
367
|
0
|
|
|
|
|
|
my $next_solstice = _zodiac_sign(Calendar::Any::Gregorian->new(12, 15, $y)); |
|
368
|
0
|
|
|
|
|
|
my $months = _month_list(_zodiac_sign(Calendar::Any::Gregorian->new(12, 15, $y-1))+1, |
|
369
|
|
|
|
|
|
|
$next_solstice); |
|
370
|
0
|
|
|
|
|
|
my $list; |
|
371
|
0
|
0
|
|
|
|
|
if ( scalar(@$months) == 12 ) { |
|
372
|
0
|
|
|
|
|
|
$list = [[12, $months->[0]], map { [ $_, $months->[$_] ]} 1..11]; |
|
|
0
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
} else { |
|
374
|
0
|
|
|
|
|
|
my $next_sign = _zodiac_sign($months->[0]); |
|
375
|
0
|
0
|
0
|
|
|
|
if ( $months->[0]>$next_sign || $next_sign >= $months->[1] ) { |
|
376
|
0
|
|
|
|
|
|
$list = [[11.5, $months->[0]], [12, $months->[1]], |
|
377
|
0
|
|
|
|
|
|
map { [ $_, $months->[$_+1] ] } 1..11]; |
|
378
|
|
|
|
|
|
|
} else { |
|
379
|
0
|
|
|
|
|
|
my @list = ([12, $months->[0]]); |
|
380
|
0
|
0
|
|
|
|
|
if ( _zodiac_sign($months->[1]) >= _zodiac_sign($months->[2]) ) { |
|
381
|
0
|
|
|
|
|
|
push @list, [12.5, $months->[1]], |
|
382
|
0
|
|
|
|
|
|
map { [ $_, $months->[$_+1] ] } 1..11; |
|
383
|
|
|
|
|
|
|
} else { |
|
384
|
0
|
|
|
|
|
|
push @list, [1, $months->[1]]; |
|
385
|
0
|
|
|
|
|
|
my $i = 2; |
|
386
|
0
|
|
|
|
|
|
while ( $months->[$i+1] > _zodiac_sign($months->[$i]) ) { |
|
387
|
0
|
|
|
|
|
|
push @list, [$i, $months->[$i]]; |
|
388
|
0
|
|
|
|
|
|
$i++; |
|
389
|
|
|
|
|
|
|
} |
|
390
|
0
|
|
|
|
|
|
push @list, [$i-0.5, $months->[$i]]; |
|
391
|
0
|
|
|
|
|
|
foreach ( $i..11 ) { |
|
392
|
0
|
|
|
|
|
|
push @list, [$_, $months->[$_+1]]; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
} |
|
395
|
0
|
|
|
|
|
|
$list = \@list; |
|
396
|
|
|
|
|
|
|
} |
|
397
|
|
|
|
|
|
|
} |
|
398
|
0
|
|
|
|
|
|
$Calendar::Any::Util::Solar::timezone = $oldtz; |
|
399
|
0
|
|
|
|
|
|
return $list; |
|
400
|
|
|
|
|
|
|
} |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub _zodiac_sign { |
|
403
|
0
|
|
|
0
|
|
|
int(Calendar::Any::Util::Solar::next_longitude_date(shift, 30)); |
|
404
|
|
|
|
|
|
|
} |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
#========================================================== |
|
407
|
|
|
|
|
|
|
# Input : start, end, timezone |
|
408
|
|
|
|
|
|
|
# Output : the array of new moon date between start and end |
|
409
|
|
|
|
|
|
|
# Desc : start and end should be Calendar object or absolute date |
|
410
|
|
|
|
|
|
|
#========================================================== |
|
411
|
|
|
|
|
|
|
sub _month_list { |
|
412
|
0
|
|
|
0
|
|
|
my ($start, $end) = @_; |
|
413
|
0
|
|
|
|
|
|
my @list; |
|
414
|
0
|
|
|
|
|
|
while ( $start <= $end ) { |
|
415
|
0
|
|
|
|
|
|
$start = int(Calendar::Any::Util::Lunar::new_moon_date($start)); |
|
416
|
0
|
|
|
|
|
|
push @list, $start; |
|
417
|
0
|
|
|
|
|
|
$start++; |
|
418
|
|
|
|
|
|
|
} |
|
419
|
0
|
0
|
|
|
|
|
pop @list if $list[-1]>$end; |
|
420
|
0
|
|
|
|
|
|
return \@list; |
|
421
|
|
|
|
|
|
|
} |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
1; |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
__END__ |