File Coverage

blib/lib/Date/Qreki.pm
Criterion Covered Total %
statement 382 413 92.4
branch 39 60 65.0
condition 15 36 41.6
subroutine 18 18 100.0
pod 4 13 30.7
total 458 540 84.8


line stmt bran cond sub pod time code
1             package Date::Qreki;
2 1     1   14228 use warnings;
  1         1  
  1         29  
3 1     1   3 use strict;
  1         1  
  1         94  
4             require Exporter;
5             our @ISA = qw(Exporter);
6             our @EXPORT_OK = qw/calc_kyureki get_rokuyou rokuyou_unicode check_24sekki/;
7             our %EXPORT_TAGS = (all => \@EXPORT_OK);
8             our $VERSION = '0.07';
9 1     1   5 use utf8;
  1         7  
  1         6  
10              
11             #=========================================================================
12             # 旧暦計算サンプルプログラム $Revision: 1.1 $
13             # Coded by H.Takano 1993,1994
14             #
15             # Arranged for Perl Script by N.Ueno
16             #
17             #
18             # オリジナルのスクリプトは高野氏のAWKです。下記より入手できます。
19             # http://www.vector.co.jp/soft/dos/personal/se016093.html
20             #
21             #
22             #========================================================================
23              
24             #-----------------------------------------------------------------------
25             # 円周率の定義と(角度の)度からラジアンに変換する係数の定義
26             #-----------------------------------------------------------------------
27 1     1   26 use constant PI => 3.141592653589793238462;
  1         1  
  1         116  
28 1     1   3 use constant k => PI/180.0;
  1         1  
  1         2588  
29              
30             sub deg_cos
31             {
32 24875     24875 0 14884 my ($angle) = @_;
33 24875         22153 return cos ($angle * k);
34             }
35              
36             #=========================================================================
37             # 六曜算出関数
38             #
39             # 引数:新暦年月日
40             # 戻値:0:大安 1:赤口 2:先勝 3:友引 4:先負 5:仏滅
41             #
42             #=========================================================================
43             sub get_rokuyou
44             {
45              
46 4     4 1 2153 my ($year,$mon,$day) = @_;
47 4         4 my ($tm0,$q_year,$q_mon,$q_day,$uruu,$q_yaer);
48              
49 4         10 ($q_yaer,$uruu,$q_mon,$q_day) = calc_kyureki($year,$mon,$day);
50              
51 4         20 return(($q_mon + $q_day) % 6);
52             }
53              
54             sub rokuyou_unicode
55             {
56              
57 1     1 1 496 my ($year,$mon,$day) = @_;
58 1         2 my ($tm0,$q_year,$q_mon,$q_day,$uruu,$q_yaer);
59              
60 1         3 ($q_yaer,$uruu,$q_mon,$q_day) = calc_kyureki($year,$mon,$day);
61              
62 1         7 return (qw/大安 赤口 先勝 友引 先負 仏滅/)[(($q_mon + $q_day) % 6)];
63             }
64             #=========================================================================
65             # 新暦に対応する、旧暦を求める。
66             #
67             # 呼び出し時にセットする変数
68             # 引 数 year : 計算する日付
69             # mon
70             # day
71             #
72             # 戻り値 kyureki : 答えの格納先(配列に答えをかえす)
73             #    kyureki[0] : 旧暦年
74             #    kyureki[1] : 平月/閏月 flag .... 平月:0 閏月:1
75             #    kyureki[2] : 旧暦月
76             #    kyureki[3] : 旧暦日
77             #
78             #=========================================================================
79             sub calc_kyureki
80             {
81 9     9 1 9371 my ($year,$mon,$day) = @_;
82 9         12 my (@kyureki,$tm,@saku,$lap,@a,$i,@m);
83              
84 9         23 my $tm0 = YMDT2JD($year,$mon,$day,0,0,0);
85              
86             #-----------------------------------------------------------------------
87             # 計算対象の直前にあたる二分二至の時刻を求める
88             # chu[0,0]:二分二至の時刻 chu[0,1]:その時の太陽黄経
89             #-----------------------------------------------------------------------
90 9         9 my @chu;
91 9         19 ($chu[0][0],$chu[0][1]) = before_nibun($tm0);
92              
93             #-----------------------------------------------------------------------
94             # 中気の時刻を計算(4回計算する)
95             # chu[i,0]:中気の時刻 chu[i,1]:太陽黄経
96             #-----------------------------------------------------------------------
97 9         22 for($i=1;$i<4;$i++){
98 27         49 ($chu[$i][0],$chu[$i][1]) = calc_chu($chu[$i-1][0]+32.0);
99             }
100              
101             #-----------------------------------------------------------------------
102             # 計算対象の直前にあたる二分二至の直前の朔の時刻を求める
103             #-----------------------------------------------------------------------
104 9         14 $saku[0] = calc_saku($chu[0][0]);
105              
106              
107             #-----------------------------------------------------------------------
108             # 朔の時刻を求める
109             #-----------------------------------------------------------------------
110 9         19 for($i=1;$i<5;$i++){
111 36         31 $tm=$saku[$i-1];
112 36         30 $tm += 30.0;
113 36         38 $saku[$i]=calc_saku($tm);
114              
115             # 前と同じ時刻を計算した場合(両者の差が26日以内)には、初期値を
116             # +33日にして再実行させる。
117 36 50       123 if( abs( int($saku[$i-1])-int($saku[$i]) ) <= 26.0 ){
118 0         0 $saku[$i]=calc_saku($saku[$i-1]+35.0);
119             }
120             }
121              
122             #-----------------------------------------------------------------------
123             # saku[1]が二分二至の時刻以前になってしまった場合には、朔をさかのぼり過ぎ
124             # たと考えて、朔の時刻を繰り下げて修正する。
125             # その際、計算もれ(saku[4])になっている部分を補うため、朔の時刻を計算
126             # する。(近日点通過の近辺で朔があると起こる事があるようだ...?)
127             #-----------------------------------------------------------------------
128 9 50       48 if( int($saku[1]) <= int($chu[0][0]) ){
    50          
129 0         0 for($i=0;$i<5;$i++){
130 0         0 $saku[$i]=$saku[$i+1];
131             }
132 0         0 $saku[4] = calc_saku($saku[3]+35.0);
133             }
134              
135             #-----------------------------------------------------------------------
136             # saku[0]が二分二至の時刻以後になってしまった場合には、朔をさかのぼり足
137             # りないと見て、朔の時刻を繰り上げて修正する。
138             # その際、計算もれ(saku[0])になっている部分を補うため、朔の時刻を計算
139             # する。(春分点の近辺で朔があると起こる事があるようだ...?)
140             #-----------------------------------------------------------------------
141             elsif( int($saku[0]) > int($chu[0][0]) ){
142 0         0 for($i=4;$i>0;$i--){
143 0         0 $saku[$i] = $saku[$i-1];
144             }
145 0         0 $saku[0] = calc_saku($saku[0]-27.0);
146             }
147              
148             #-----------------------------------------------------------------------
149             # 閏月検索Flagセット
150             # (節月で4ヶ月の間に朔が5回あると、閏月がある可能性がある。)
151             # lap=0:平月 lap=1:閏月
152             #-----------------------------------------------------------------------
153 9 50       25 if(int($saku[4]) <= int($chu[3][0]) ){
154 0         0 $lap=1;
155             }else{
156 9         12 $lap=0;
157             }
158              
159             #-----------------------------------------------------------------------
160             # 朔日行列の作成
161             # m[i,0] ... 月名(1:正月 2:2月 3:3月 ....)
162             # m[i,1] ... 閏フラグ(0:平月 1:閏月)
163             # m[i,2] ... 朔日のjd
164             #-----------------------------------------------------------------------
165 9         32 $m[0][0]=int($chu[0][1]/30.0) + 2;
166 9 50 33     21 if(defined $m[0][1] && $m[0][1] > 12 ){
167 0         0 $m[0][0]-=12;
168             }
169 9         13 $m[0][2]=int($saku[0]);
170 9         10 $m[0][1]=0;
171              
172 9         27 for($i=1;$i<5;$i++){
173 36 50 33     67 if($lap == 1 && $i !=1 ){
174 0 0 0     0 if( int($chu[$i-1][0]) <= int($saku[$i-1]) || int($chu[$i-1][0]) >= int($saku[$i]) ){
175 0         0 $m[$i-1][0] = $m[$i-2][0];
176 0         0 $m[$i-1][1] = 1;
177 0         0 $m[$i-1][2] = int($saku[$i-1]);
178 0         0 $lap=0;
179             }
180             }
181 36         52 $m[$i][0] = $m[$i-1][0]+1;
182 36 100       47 if( $m[$i][0] > 12 ){
183 7         9 $m[$i][0]-=12;
184             }
185 36         34 $m[$i][2]=int($saku[$i]);
186 36         51 $m[$i][1]=0;
187             }
188              
189             #-----------------------------------------------------------------------
190             # 朔日行列から旧暦を求める。
191             #-----------------------------------------------------------------------
192 9         13 my $state=0;
193 9         18 for($i=0;$i<5;$i++){
194 32 100       66 if(int($tm0) < int($m[$i][2])){
    50          
195 9         7 $state=1;
196 9         16 last;
197             }elsif(int($tm0) == int($m[$i][2])){
198 0         0 $state=2;
199 0         0 last;
200             }
201             }
202 9 50 33     33 if($state==0||$state==1){
203 9         8 $i--;
204             }
205              
206 9         10 $kyureki[1]=$m[$i][1];
207 9         9 $kyureki[2]=$m[$i][0];
208 9         15 $kyureki[3]=int($tm0)-int($m[$i][2])+1;
209              
210             #-----------------------------------------------------------------------
211             # 旧暦年の計算
212             # (旧暦月が10以上でかつ新暦月より大きい場合には、
213             # まだ年を越していないはず...)
214             #-----------------------------------------------------------------------
215              
216 9         43 @a = JD2YMDT($tm0);
217 9         10 $kyureki[0] = $a[0];
218 9 100 66     29 if($kyureki[2] > 9 && $kyureki[2] > $a[1]){
219 4         3 $kyureki[0]--;
220             }
221              
222 9         55 return($kyureki[0],$kyureki[1],$kyureki[2],$kyureki[3]);
223              
224             }
225              
226             #=========================================================================
227             # 中気の時刻を求める
228             #
229             # 呼び出し時にセットする変数
230             # tm ........ 計算対象となる時刻(ユリウス日)
231             # chu ....... 戻り値を格納する配列のポインター
232             # i ......... 戻り値を格納する配列の要素番号
233             # 戻り値 .... 中気の時刻、その時の黄経を配列で渡す
234             #
235             #=========================================================================
236             sub calc_chu
237             {
238 27     27 0 20 my ($tm) = @_;
239 27         24 my ($tm1,$tm2,$t,$rm_sun0,$rm_sun,$delta_t1,$delta_t2,$delta_rm);
240 0         0 my (@temp);
241             #-----------------------------------------------------------------------
242             #時刻引数を分解する
243             #-----------------------------------------------------------------------
244 27         18 $tm1 = int( $tm );
245 27         21 $tm2 = $tm - $tm1;
246              
247             #-----------------------------------------------------------------------
248             # JST ==> DT (補正時刻=0.0sec と仮定して計算)
249             #-----------------------------------------------------------------------
250 27         21 $tm2-=9.0/24.0;
251              
252             #-----------------------------------------------------------------------
253             # 中気の黄経 λsun0 を求める
254             #-----------------------------------------------------------------------
255 27         19 $t=($tm2+0.5) / 36525.0;
256 27         27 $t=$t + ($tm1-2451545.0) / 36525.0;
257 27         30 $rm_sun = LONGITUDE_SUN( $t );
258              
259 27         26 $rm_sun0 = 30.0*int($rm_sun/30.0);
260              
261             #-----------------------------------------------------------------------
262             # 繰り返し計算によって中気の時刻を計算する
263             # (誤差が±1.0 sec以内になったら打ち切る。)
264             #-----------------------------------------------------------------------
265 27         18 $delta_t1 = 0;
266 27         50 for( $delta_t2 = 1.0 ; abs( $delta_t1 + $delta_t2 ) > ( 1.0 / 86400.0 ) ; ){
267              
268             #-----------------------------------------------------------------------
269             # λsun を計算
270             #-----------------------------------------------------------------------
271 122         78 $t =($tm2+0.5) / 36525.0;
272 122         98 $t =$t + ($tm1-2451545.0) / 36525.0;
273 122         105 $rm_sun=LONGITUDE_SUN( $t );
274              
275             #-----------------------------------------------------------------------
276             # 黄経差 Δλ=λsun −λsun0
277             #-----------------------------------------------------------------------
278 122         85 $delta_rm = $rm_sun - $rm_sun0 ;
279              
280             #-----------------------------------------------------------------------
281             # Δλの引き込み範囲(±180°)を逸脱した場合には、補正を行う
282             #-----------------------------------------------------------------------
283 122 100       196 if( $delta_rm > 180.0 ){
    50          
284 10         6 $delta_rm-=360.0;
285             }elsif( $delta_rm < -180.0 ){
286 0         0 $delta_rm+=360.0;
287             }
288              
289             #-----------------------------------------------------------------------
290             # 時刻引数の補正値 Δt
291             # delta_t = delta_rm * 365.2 / 360.0;
292             #-----------------------------------------------------------------------
293 122         93 $delta_t1 = int($delta_rm * 365.2 / 360.0);
294 122         82 $delta_t2 = $delta_rm * 365.2 / 360.0;
295 122         75 $delta_t2 -= $delta_t1;
296              
297             #-----------------------------------------------------------------------
298             # 時刻引数の補正
299             # tm -= delta_t;
300             #-----------------------------------------------------------------------
301 122         70 $tm1 = $tm1 - $delta_t1;
302 122         75 $tm2 = $tm2 - $delta_t2;
303 122 100       213 if($tm2 < 0){
304 20         16 $tm2+=1.0;$tm1-=1.0;
  20         30  
305             }
306             }
307              
308             #-----------------------------------------------------------------------
309             # 戻り値の作成
310             # chu[i,0]:時刻引数を合成するのと、DT ==> JST 変換を行い、戻り値とする
311             # (補正時刻=0.0sec と仮定して計算)
312             # chu[i,1]:黄経
313             #-----------------------------------------------------------------------
314 27         23 $temp[0] = $tm2+9.0/24.0;
315 27         18 $temp[0] += $tm1;
316 27         17 $temp[1] = $rm_sun0;
317              
318 27         94 return(@temp);
319             }
320              
321             #=========================================================================
322             # 直前の二分二至の時刻を求める
323             #
324             # 呼び出し時にセットする変数
325             # tm ........ 計算対象となる時刻(ユリウス日)
326             # nibun ..... 戻り値を格納する配列のポインター
327             # 戻り値 .... 二分二至の時刻、その時の黄経を配列で渡す
328             # (戻り値の渡し方がちょっと気にくわないがまぁいいや。)
329             #=========================================================================
330             sub before_nibun
331             {
332 9     9 0 11 my ($tm) = @_;
333 9         10 my (@nibun,$tm1,$tm2,$t,$rm_sun0,$rm_sun,$delta_t1,$delta_t2,$delta_rm);
334              
335             #-----------------------------------------------------------------------
336             #時刻引数を分解する
337             #-----------------------------------------------------------------------
338 9         6 $tm1 = int( $tm );
339 9         11 $tm2 = $tm - $tm1;
340              
341             #-----------------------------------------------------------------------
342             # JST ==> DT (補正時刻=0.0sec と仮定して計算)
343             #-----------------------------------------------------------------------
344 9         9 $tm2-=9.0/24.0;
345              
346             #-----------------------------------------------------------------------
347             # 直前の二分二至の黄経 λsun0 を求める
348             #-----------------------------------------------------------------------
349 9         11 $t=($tm2+0.5) / 36525.0;
350 9         12 $t=$t + ($tm1-2451545.0) / 36525.0;
351 9         14 $rm_sun=LONGITUDE_SUN( $t );
352 9         11 $rm_sun0=90*int($rm_sun/90.0);
353              
354             #-----------------------------------------------------------------------
355             # 繰り返し計算によって直前の二分二至の時刻を計算する
356             # (誤差が±1.0 sec以内になったら打ち切る。)
357             #-----------------------------------------------------------------------
358 9         10 $delta_t1 = 0;
359 9         22 for( $delta_t2 = 1.0 ; abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ; ){
360              
361             #-----------------------------------------------------------------------
362             # λsun を計算
363             #-----------------------------------------------------------------------
364 50         37 $t=($tm2+0.5) / 36525.0;
365 50         40 $t=$t + ($tm1-2451545.0) / 36525.0;
366 50         43 $rm_sun=LONGITUDE_SUN( $t );
367              
368             #-----------------------------------------------------------------------
369             # 黄経差 Δλ=λsun −λsun0
370             #-----------------------------------------------------------------------
371 50         33 $delta_rm = $rm_sun - $rm_sun0 ;
372              
373             #-----------------------------------------------------------------------
374             # Δλの引き込み範囲(±180°)を逸脱した場合には、補正を行う
375             #-----------------------------------------------------------------------
376 50 50       91 if( $delta_rm > 180.0 ){
    50          
377 0         0 $delta_rm-=360.0;
378             }elsif( $delta_rm < -180.0){
379 0         0 $delta_rm+=360.0;
380             }
381              
382             #-----------------------------------------------------------------------
383             # 時刻引数の補正値 Δt
384             # delta_t = delta_rm * 365.2 / 360.0;
385             #-----------------------------------------------------------------------
386 50         41 $delta_t1 = int($delta_rm * 365.2 / 360.0);
387 50         26 $delta_t2 = $delta_rm * 365.2 / 360.0;
388 50         37 $delta_t2 -= $delta_t1;
389              
390             #-----------------------------------------------------------------------
391             # 時刻引数の補正
392             # tm -= delta_t;
393             #-----------------------------------------------------------------------
394 50         30 $tm1 = $tm1 - $delta_t1;
395 50         34 $tm2 = $tm2 - $delta_t2;
396 50 100       86 if($tm2 < 0){
397 11         10 $tm2+=1.0;$tm1-=1.0;
  11         19  
398             }
399              
400             }
401              
402             #-----------------------------------------------------------------------
403             # 戻り値の作成
404             # nibun[0,0]:時刻引数を合成するのと、DT ==> JST 変換を行い、戻り値とする
405             # (補正時刻=0.0sec と仮定して計算)
406             # nibun[0,1]:黄経
407             #-----------------------------------------------------------------------
408 9         10 $nibun[0] = $tm2+9.0/24.0;
409 9         9 $nibun[0] += $tm1;
410 9         8 $nibun[1] = $rm_sun0;
411              
412 9         27 return(@nibun);
413              
414             }
415              
416             #=========================================================================
417             # 朔の計算
418             # 与えられた時刻の直近の朔の時刻(JST)を求める
419             #
420             # 呼び出し時にセットする変数
421             # tm ........ 計算対象となる時刻(ユリウス日)
422             # 戻り値 .... 朔の時刻
423             #
424             # ※ 引数、戻り値ともユリウス日で表し、時分秒は日の小数で表す。
425             #
426             #=========================================================================
427             sub calc_saku
428             {
429 45     45 0 34 my ($tm) = @_;
430 45         33 my ($lc,$t,$tm1,$tm2,$rm_sun,$rm_moon,$delta_rm,$delta_t1,$delta_t2);
431              
432             #-----------------------------------------------------------------------
433             # ループカウンタのセット
434             #-----------------------------------------------------------------------
435 45         32 $lc=1;
436              
437             #-----------------------------------------------------------------------
438             #時刻引数を分解する
439             #-----------------------------------------------------------------------
440 45         29 $tm1 = int( $tm );
441 45         33 $tm2 = $tm - $tm1;
442              
443             #-----------------------------------------------------------------------
444             # JST ==> DT (補正時刻=0.0sec と仮定して計算)
445             #-----------------------------------------------------------------------
446 45         30 $tm2-=9.0/24.0;
447              
448             #-----------------------------------------------------------------------
449             # 繰り返し計算によって朔の時刻を計算する
450             # (誤差が±1.0 sec以内になったら打ち切る。)
451             #-----------------------------------------------------------------------
452 45         28 $delta_t1 = 0;
453 45         76 for( $delta_t2 = 1.0 ; abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ; $lc++){
454              
455             #-----------------------------------------------------------------------
456             # 太陽の黄経λsun ,月の黄経λmoon を計算
457             # t = (tm - 2451548.0 + 0.5)/36525.0;
458             #-----------------------------------------------------------------------
459 279         189 $t=($tm2+0.5) / 36525.0;
460 279         203 $t=$t + ($tm1-2451545.0) / 36525.0;
461 279         286 $rm_sun=LONGITUDE_SUN( $t );
462 279         264 $rm_moon=LONGITUDE_MOON( $t );
463              
464             #-----------------------------------------------------------------------
465             # 月と太陽の黄経差Δλ
466             # Δλ=λmoon−λsun
467             #-----------------------------------------------------------------------
468 279         192 $delta_rm = $rm_moon - $rm_sun ;
469              
470             #-----------------------------------------------------------------------
471             # ループの1回目(lc=1)で delta_rm < 0.0 の場合には引き込み範囲に
472             # 入るように補正する
473             #-----------------------------------------------------------------------
474 279 100 100     1475 if( $lc==1 && $delta_rm < 0.0 ){
    50 66        
    100 66        
475 7         7 $delta_rm = NORMALIZATION_ANGLE( $delta_rm );
476             }
477             #-----------------------------------------------------------------------
478             # 春分の近くで朔がある場合(0 ≦λsun≦ 20)で、月の黄経λmoon≧300 の
479             # 場合には、Δλ= 360.0 − Δλ と計算して補正する
480             #-----------------------------------------------------------------------
481             elsif( $rm_sun >= 0 && $rm_sun <= 20 && $rm_moon >= 300 ){
482 0         0 $delta_rm = NORMALIZATION_ANGLE( $delta_rm );
483 0         0 $delta_rm = 360.0 - $delta_rm;
484             }
485             #-----------------------------------------------------------------------
486             # Δλの引き込み範囲(±40°)を逸脱した場合には、補正を行う
487             #-----------------------------------------------------------------------
488             elsif( abs( $delta_rm ) > 40.0 ) {
489 2         3 $delta_rm = NORMALIZATION_ANGLE( $delta_rm );
490             }
491              
492             #-----------------------------------------------------------------------
493             # 時刻引数の補正値 Δt
494             # delta_t = delta_rm * 29.530589 / 360.0;
495             #-----------------------------------------------------------------------
496 279         214 $delta_t1 = int($delta_rm * 29.530589 / 360.0);
497 279         183 $delta_t2 = $delta_rm * 29.530589 / 360.0;
498 279         164 $delta_t2 -= $delta_t1;
499              
500             #-----------------------------------------------------------------------
501             # 時刻引数の補正
502             # tm -= delta_t;
503             #-----------------------------------------------------------------------
504 279         194 $tm1 = $tm1 - $delta_t1;
505 279         202 $tm2 = $tm2 - $delta_t2;
506 279 100       326 if($tm2 < 0.0){
507 41         31 $tm2+=1.0;$tm1-=1.0;
  41         31  
508             }
509              
510             #-----------------------------------------------------------------------
511             # ループ回数が15回になったら、初期値 tm を tm-26 とする。
512             #-----------------------------------------------------------------------
513 279 50 33     1105 if($lc == 15 && abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ){
    50 33        
514 0         0 $tm1 = int( $tm-26 );
515 0         0 $tm2 = 0;
516             }
517              
518             #-----------------------------------------------------------------------
519             # 初期値を補正したにも関わらず、振動を続ける場合には初期値を答えとして
520             # 返して強制的にループを抜け出して異常終了させる。
521             #-----------------------------------------------------------------------
522             elsif( $lc > 30 && abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ){
523 0         0 $tm1=$tm;$tm2=0;
  0         0  
524 0         0 last;
525             }
526             }
527              
528             #-----------------------------------------------------------------------
529             # 時刻引数を合成するのと、DT ==> JST 変換を行い、戻り値とする
530             # (補正時刻=0.0sec と仮定して計算)
531             #-----------------------------------------------------------------------
532              
533 45         73 return($tm2+$tm1+9.0/24.0);
534             }
535              
536             #=========================================================================
537             # 角度の正規化を行う。すなわち引数の範囲を 0≦θ<360 にする。
538             #=========================================================================
539             sub NORMALIZATION_ANGLE
540             {
541 26703     26703 0 15685 my ($angle) = @_;
542 26703         13885 my ($angle1,$angle2);
543              
544 26703 100       23610 if( $angle < 0.0 ){
545 21757         12365 $angle1 = -$angle;
546 21757         12944 $angle2 = int( $angle1 / 360.0 );
547 21757         12834 $angle1 -= 360.0 * $angle2;
548 21757         13556 $angle1 = 360.0 - $angle1;
549             }else{
550 4946         3034 $angle1 = int( $angle / 360.0 );
551 4946         3153 $angle1 = $angle - 360.0 * $angle1;
552             }
553              
554 26703         19533 return($angle1);
555             }
556              
557             #=========================================================================
558             # 太陽の黄経 λsun を計算する
559             #=========================================================================
560             sub LONGITUDE_SUN
561             {
562 491     491 0 358 my ($t) = @_;
563 491         290 my ($th,$ang);
564              
565             #-----------------------------------------------------------------------
566             # 摂動項の計算
567             #-----------------------------------------------------------------------
568 491         549 $ang = NORMALIZATION_ANGLE( 31557.0 * $t + 161.0 );
569 491         490 $th = .0004 * deg_cos( $ang );
570 491         496 $ang = NORMALIZATION_ANGLE( 29930.0 * $t + 48.0 );
571 491         495 $th = $th + .0004 * deg_cos ($ang );
572 491         485 $ang = NORMALIZATION_ANGLE( 2281.0 * $t + 221.0 );
573 491         478 $th = $th + .0005 * deg_cos ($ang );
574 491         532 $ang = NORMALIZATION_ANGLE( 155.0 * $t + 118.0 );
575 491         490 $th = $th + .0005 * deg_cos ($ang );
576 491         501 $ang = NORMALIZATION_ANGLE( 33718.0 * $t + 316.0 );
577 491         453 $th = $th + .0006 * deg_cos ($ang );
578 491         503 $ang = NORMALIZATION_ANGLE( 9038.0 * $t + 64.0 );
579 491         443 $th = $th + .0007 * deg_cos ($ang );
580 491         515 $ang = NORMALIZATION_ANGLE( 3035.0 * $t + 110.0 );
581 491         476 $th = $th + .0007 * deg_cos ($ang );
582 491         515 $ang = NORMALIZATION_ANGLE( 65929.0 * $t + 45.0 );
583 491         456 $th = $th + .0007 * deg_cos ($ang );
584 491         473 $ang = NORMALIZATION_ANGLE( 22519.0 * $t + 352.0 );
585 491         444 $th = $th + .0013 * deg_cos ($ang );
586 491         494 $ang = NORMALIZATION_ANGLE( 45038.0 * $t + 254.0 );
587 491         448 $th = $th + .0015 * deg_cos ($ang );
588 491         477 $ang = NORMALIZATION_ANGLE( 445267.0 * $t + 208.0 );
589 491         469 $th = $th + .0018 * deg_cos ($ang );
590 491         514 $ang = NORMALIZATION_ANGLE( 19.0 * $t + 159.0 );
591 491         469 $th = $th + .0018 * deg_cos ($ang );
592 491         498 $ang = NORMALIZATION_ANGLE( 32964.0 * $t + 158.0 );
593 491         451 $th = $th + .0020 * deg_cos ($ang );
594 491         537 $ang = NORMALIZATION_ANGLE( 71998.1 * $t + 265.1 );
595 491         441 $th = $th + .0200 * deg_cos ($ang );
596 491         513 $ang = NORMALIZATION_ANGLE( 35999.05 * $t + 267.52 );
597 491         501 $th = $th - 0.0048 * $t * deg_cos ($ang ) ;
598 491         437 $th = $th + 1.9147 * deg_cos ($ang ) ;
599              
600             #-----------------------------------------------------------------------
601             # 比例項の計算
602             #-----------------------------------------------------------------------
603 491         461 $ang = NORMALIZATION_ANGLE( 36000.7695 * $t );
604 491         469 $ang = NORMALIZATION_ANGLE( $ang + 280.4659 );
605 491         500 $th = NORMALIZATION_ANGLE( $th + $ang );
606              
607 491         418 return($th);
608             }
609              
610             #=========================================================================
611             # 月の黄経 λmoon を計算する
612             #=========================================================================
613             sub LONGITUDE_MOON
614             {
615 279     279 0 188 my ($t) = @_;
616 279         156 my ($th,$ang);
617              
618             #-----------------------------------------------------------------------
619             # 摂動項の計算
620             #-----------------------------------------------------------------------
621 279         260 $ang = NORMALIZATION_ANGLE( 2322131.0 * $t + 191.0 );
622 279         271 $th = .0003 * deg_cos ($ang );
623 279         293 $ang = NORMALIZATION_ANGLE( 4067.0 * $t + 70.0 );
624 279         294 $th = $th + .0003 * deg_cos ($ang );
625 279         288 $ang = NORMALIZATION_ANGLE( 549197.0 * $t + 220.0 );
626 279         276 $th = $th + .0003 * deg_cos ($ang );
627 279         294 $ang = NORMALIZATION_ANGLE( 1808933.0 * $t + 58.0 );
628 279         272 $th = $th + .0003 * deg_cos ($ang );
629 279         302 $ang = NORMALIZATION_ANGLE( 349472.0 * $t + 337.0 );
630 279         288 $th = $th + .0003 * deg_cos ($ang );
631 279         369 $ang = NORMALIZATION_ANGLE( 381404.0 * $t + 354.0 );
632 279         277 $th = $th + .0003 * deg_cos ($ang );
633 279         284 $ang = NORMALIZATION_ANGLE( 958465.0 * $t + 340.0 );
634 279         278 $th = $th + .0003 * deg_cos ($ang );
635 279         275 $ang = NORMALIZATION_ANGLE( 12006.0 * $t + 187.0 );
636 279         248 $th = $th + .0004 * deg_cos ($ang );
637 279         345 $ang = NORMALIZATION_ANGLE( 39871.0 * $t + 223.0 );
638 279         272 $th = $th + .0004 * deg_cos ($ang );
639 279         284 $ang = NORMALIZATION_ANGLE( 509131.0 * $t + 242.0 );
640 279         265 $th = $th + .0005 * deg_cos ($ang );
641 279         285 $ang = NORMALIZATION_ANGLE( 1745069.0 * $t + 24.0 );
642 279         249 $th = $th + .0005 * deg_cos ($ang );
643 279         271 $ang = NORMALIZATION_ANGLE( 1908795.0 * $t + 90.0 );
644 279         251 $th = $th + .0005 * deg_cos ($ang );
645 279         298 $ang = NORMALIZATION_ANGLE( 2258267.0 * $t + 156.0 );
646 279         251 $th = $th + .0006 * deg_cos ($ang );
647 279         265 $ang = NORMALIZATION_ANGLE( 111869.0 * $t + 38.0 );
648 279         243 $th = $th + .0006 * deg_cos ($ang );
649 279         297 $ang = NORMALIZATION_ANGLE( 27864.0 * $t + 127.0 );
650 279         278 $th = $th + .0007 * deg_cos ($ang );
651 279         273 $ang = NORMALIZATION_ANGLE( 485333.0 * $t + 186.0 );
652 279         262 $th = $th + .0007 * deg_cos ($ang );
653 279         266 $ang = NORMALIZATION_ANGLE( 405201.0 * $t + 50.0 );
654 279         247 $th = $th + .0007 * deg_cos ($ang );
655 279         302 $ang = NORMALIZATION_ANGLE( 790672.0 * $t + 114.0 );
656 279         256 $th = $th + .0007 * deg_cos ($ang );
657 279         272 $ang = NORMALIZATION_ANGLE( 1403732.0 * $t + 98.0 );
658 279         257 $th = $th + .0008 * deg_cos ($ang );
659 279         301 $ang = NORMALIZATION_ANGLE( 858602.0 * $t + 129.0 );
660 279         276 $th = $th + .0009 * deg_cos ($ang );
661 279         291 $ang = NORMALIZATION_ANGLE( 1920802.0 * $t + 186.0 );
662 279         254 $th = $th + .0011 * deg_cos ($ang );
663 279         272 $ang = NORMALIZATION_ANGLE( 1267871.0 * $t + 249.0 );
664 279         268 $th = $th + .0012 * deg_cos ($ang );
665 279         268 $ang = NORMALIZATION_ANGLE( 1856938.0 * $t + 152.0 );
666 279         285 $th = $th + .0016 * deg_cos ($ang );
667 279         269 $ang = NORMALIZATION_ANGLE( 401329.0 * $t + 274.0 );
668 279         251 $th = $th + .0018 * deg_cos ($ang );
669 279         282 $ang = NORMALIZATION_ANGLE( 341337.0 * $t + 16.0 );
670 279         255 $th = $th + .0021 * deg_cos ($ang );
671 279         267 $ang = NORMALIZATION_ANGLE( 71998.0 * $t + 85.0 );
672 279         278 $th = $th + .0021 * deg_cos ($ang );
673 279         286 $ang = NORMALIZATION_ANGLE( 990397.0 * $t + 357.0 );
674 279         238 $th = $th + .0021 * deg_cos ($ang );
675 279         279 $ang = NORMALIZATION_ANGLE( 818536.0 * $t + 151.0 );
676 279         249 $th = $th + .0022 * deg_cos ($ang );
677 279         331 $ang = NORMALIZATION_ANGLE( 922466.0 * $t + 163.0 );
678 279         265 $th = $th + .0023 * deg_cos ($ang );
679 279         325 $ang = NORMALIZATION_ANGLE( 99863.0 * $t + 122.0 );
680 279         277 $th = $th + .0024 * deg_cos ($ang );
681 279         269 $ang = NORMALIZATION_ANGLE( 1379739.0 * $t + 17.0 );
682 279         240 $th = $th + .0026 * deg_cos ($ang );
683 279         273 $ang = NORMALIZATION_ANGLE( 918399.0 * $t + 182.0 );
684 279         290 $th = $th + .0027 * deg_cos ($ang );
685 279         278 $ang = NORMALIZATION_ANGLE( 1934.0 * $t + 145.0 );
686 279         254 $th = $th + .0028 * deg_cos ($ang );
687 279         262 $ang = NORMALIZATION_ANGLE( 541062.0 * $t + 259.0 );
688 279         356 $th = $th + .0037 * deg_cos ($ang );
689 279         274 $ang = NORMALIZATION_ANGLE( 1781068.0 * $t + 21.0 );
690 279         246 $th = $th + .0038 * deg_cos ($ang );
691 279         293 $ang = NORMALIZATION_ANGLE( 133.0 * $t + 29.0 );
692 279         274 $th = $th + .0040 * deg_cos ($ang );
693 279         271 $ang = NORMALIZATION_ANGLE( 1844932.0 * $t + 56.0 );
694 279         265 $th = $th + .0040 * deg_cos ($ang );
695 279         291 $ang = NORMALIZATION_ANGLE( 1331734.0 * $t + 283.0 );
696 279         255 $th = $th + .0040 * deg_cos ($ang );
697 279         298 $ang = NORMALIZATION_ANGLE( 481266.0 * $t + 205.0 );
698 279         267 $th = $th + .0050 * deg_cos ($ang );
699 279         303 $ang = NORMALIZATION_ANGLE( 31932.0 * $t + 107.0 );
700 279         242 $th = $th + .0052 * deg_cos ($ang );
701 279         283 $ang = NORMALIZATION_ANGLE( 926533.0 * $t + 323.0 );
702 279         256 $th = $th + .0068 * deg_cos ($ang );
703 279         291 $ang = NORMALIZATION_ANGLE( 449334.0 * $t + 188.0 );
704 279         235 $th = $th + .0079 * deg_cos ($ang );
705 279         283 $ang = NORMALIZATION_ANGLE( 826671.0 * $t + 111.0 );
706 279         262 $th = $th + .0085 * deg_cos ($ang );
707 279         282 $ang = NORMALIZATION_ANGLE( 1431597.0 * $t + 315.0 );
708 279         277 $th = $th + .0100 * deg_cos ($ang );
709 279         310 $ang = NORMALIZATION_ANGLE( 1303870.0 * $t + 246.0 );
710 279         255 $th = $th + .0107 * deg_cos ($ang );
711 279         281 $ang = NORMALIZATION_ANGLE( 489205.0 * $t + 142.0 );
712 279         243 $th = $th + .0110 * deg_cos ($ang );
713 279         289 $ang = NORMALIZATION_ANGLE( 1443603.0 * $t + 52.0 );
714 279         252 $th = $th + .0125 * deg_cos ($ang );
715 279         265 $ang = NORMALIZATION_ANGLE( 75870.0 * $t + 41.0 );
716 279         258 $th = $th + .0154 * deg_cos ($ang );
717 279         264 $ang = NORMALIZATION_ANGLE( 513197.9 * $t + 222.5 );
718 279         248 $th = $th + .0304 * deg_cos ($ang );
719 279         277 $ang = NORMALIZATION_ANGLE( 445267.1 * $t + 27.9 );
720 279         251 $th = $th + .0347 * deg_cos ($ang );
721 279         303 $ang = NORMALIZATION_ANGLE( 441199.8 * $t + 47.4 );
722 279         242 $th = $th + .0409 * deg_cos ($ang );
723 279         274 $ang = NORMALIZATION_ANGLE( 854535.2 * $t + 148.2 );
724 279         271 $th = $th + .0458 * deg_cos ($ang );
725 279         273 $ang = NORMALIZATION_ANGLE( 1367733.1 * $t + 280.7 );
726 279         250 $th = $th + .0533 * deg_cos ($ang );
727 279         264 $ang = NORMALIZATION_ANGLE( 377336.3 * $t + 13.2 );
728 279         243 $th = $th + .0571 * deg_cos ($ang );
729 279         280 $ang = NORMALIZATION_ANGLE( 63863.5 * $t + 124.2 );
730 279         262 $th = $th + .0588 * deg_cos ($ang );
731 279         286 $ang = NORMALIZATION_ANGLE( 966404.0 * $t + 276.5 );
732 279         257 $th = $th + .1144 * deg_cos ($ang );
733 279         276 $ang = NORMALIZATION_ANGLE( 35999.05 * $t + 87.53 );
734 279         270 $th = $th + .1851 * deg_cos ($ang );
735 279         273 $ang = NORMALIZATION_ANGLE( 954397.74 * $t + 179.93 );
736 279         245 $th = $th + .2136 * deg_cos ($ang );
737 279         261 $ang = NORMALIZATION_ANGLE( 890534.22 * $t + 145.7 );
738 279         237 $th = $th + .6583 * deg_cos ($ang );
739 279         271 $ang = NORMALIZATION_ANGLE( 413335.35 * $t + 10.74 );
740 279         261 $th = $th + 1.2740 * deg_cos ($ang );
741 279         264 $ang = NORMALIZATION_ANGLE( 477198.868 * $t + 44.963 );
742 279         269 $th = $th + 6.2888 * deg_cos ($ang );
743              
744             #-----------------------------------------------------------------------
745             # 比例項の計算
746             #-----------------------------------------------------------------------
747 279         280 $ang = NORMALIZATION_ANGLE( 481267.8809 * $t );
748 279         289 $ang = NORMALIZATION_ANGLE( $ang + 218.3162 );
749 279         295 $th = NORMALIZATION_ANGLE( $th + $ang );
750              
751 279         215 return($th);
752             }
753              
754             #=========================================================================
755             # 年月日、時分秒(世界時)からユリウス日(JD)を計算する
756             #
757             # ※ この関数では、グレゴリオ暦法による年月日から求めるものである。
758             # (ユリウス暦法による年月日から求める場合には使用できない。)
759             #=========================================================================
760             sub YMDT2JD
761             {
762 11     11 0 12 my ($year,$month,$day,$hour,$min,$sec) = @_;
763 11         11 my ($jd,$t);
764              
765 11 100       23 if( $month < 3.0 ){
766 7         9 $year -= 1.0;
767 7         11 $month += 12.0;
768             }
769              
770 11         16 $jd = int( 365.25 * $year );
771 11         20 $jd += int( $year / 400.0 );
772 11         10 $jd -= int( $year / 100.0 );
773 11         15 $jd += int( 30.59 * ( $month-2.0 ) );
774 11         7 $jd += 1721088;
775 11         9 $jd += $day;
776              
777 11         9 $t = $sec / 3600.0;
778 11         10 $t += $min /60.0;
779 11         6 $t += $hour;
780 11         11 $t = $t / 24.0;
781              
782 11         11 $jd += $t;
783              
784 11         13 return( $jd );
785              
786             }
787              
788             #=========================================================================
789             # ユリウス日(JD)から年月日、時分秒(世界時)を計算する
790             #
791             # 戻り値の配列TIME[]の内訳
792             # TIME[0] ... 年 TIME[1] ... 月 TIME[2] ... 日
793             # TIME[3] ... 時 TIME[4] ... 分 TIME[5] ... 秒
794             #
795             # ※ この関数で求めた年月日は、グレゴリオ暦法によって表されている。
796             #
797             #=========================================================================
798             sub JD2YMDT
799             {
800              
801 9     9 0 7 my ($JD) = @_;
802 9         10 my (@TIME,$x0,$x1,$x2,$x3,$x4,$x5,$x6,$tm);
803              
804 9         17 $x0 = int( $JD+68570.0);
805 9         10 $x1 = int( $x0/36524.25 );
806 9         15 $x2 = $x0 - int( 36524.25*$x1 + 0.75 );
807 9         12 $x3 = int( ( $x2+1 )/365.2425 );
808 9         18 $x4 = $x2 - int( 365.25*$x3 )+31.0;
809 9         12 $x5 = int( int($x4) / 30.59 );
810 9         9 $x6 = int( int($x5) / 11.0 );
811              
812 9         14 $TIME[2] = $x4 - int( 30.59*$x5 );
813 9         12 $TIME[1] = $x5 - 12*$x6 + 2;
814 9         11 $TIME[0] = 100*( $x1-49 ) + $x3 + $x6;
815              
816             # 2月30日の補正
817 9 50 33     23 if($TIME[1]==2 && $TIME[2] > 28){
818 0 0 0     0 if($TIME[0] % 100 == 0 && $TIME[0] % 400 == 0){
    0          
819 0         0 $TIME[2]=29;
820             }elsif($TIME[0] % 4 ==0){
821 0         0 $TIME[2]=29;
822             }else{
823 0         0 $TIME[2]=28;
824             }
825             }
826              
827 9         13 $tm=86400.0*( $JD - int( $JD ) );
828 9         9 $TIME[3] = int( $tm/3600.0 );
829 9         17 $TIME[4] = int( ($tm - 3600.0*$TIME[3])/60.0 );
830 9         19 $TIME[5] = int( $tm - 3600.0*$TIME[3] - 60*$TIME[4] );
831              
832 9         28 return(@TIME);
833             }
834              
835             #=========================================================================
836             # 今日が24節気かどうか調べる
837             #
838             # 引数  .... 計算対象となる年月日 $year $mon $day
839             #
840             # 戻り値 .... 24節気の名称
841             #
842             #=========================================================================
843             sub check_24sekki
844             {
845 2     2 1 685 my ($year,$mon,$day) = @_;
846 2         4 my ($tm1,$tm2,$t,$rm_sun_today,$rm_sun_today0,$rm_sun_tommorow,$rm_sun_tommorow0);
847              
848             #-----------------------------------------------------------------------
849             # 24節気の定義
850             #-----------------------------------------------------------------------
851 2         10 my (@sekki24) = ("春分","清明","穀雨","立夏","小満","芒種","夏至","小暑","大暑","立秋","処暑","白露",
852             "秋分","寒露","霜降","立冬","小雪","大雪","冬至","小寒","大寒","立春","雨水","啓蟄");
853              
854 2         3 my $tm = YMDT2JD($year,$mon,$day,0,0,0);
855              
856             #-----------------------------------------------------------------------
857             #時刻引数を分解する
858             #-----------------------------------------------------------------------
859 2         3 $tm1 = int( $tm );
860 2         2 $tm2 = $tm - $tm1;
861 2         3 $tm2-=9.0/24.0;
862 2         3 $t=($tm2+0.5) / 36525.0;
863 2         3 $t=$t + ($tm1-2451545.0) / 36525.0;
864              
865             #今日の太陽の黄経
866 2         3 $rm_sun_today = LONGITUDE_SUN( $t );
867              
868 2         3 $tm++;
869 2         2 $tm1 = int($tm);
870 2         2 $tm2 = $tm - $tm1;
871 2         2 $tm2-=9.0/24.0;
872 2         3 $t=($tm2+0.5) / 36525.0;
873 2         3 $t=$t + ($tm1-2451545.0) / 36525.0;
874              
875             #明日の太陽の黄経
876 2         3 $rm_sun_tommorow = LONGITUDE_SUN($t);
877              
878             #
879 2         3 $rm_sun_today0 = 15.0 * int($rm_sun_today / 15.0);
880 2         3 $rm_sun_tommorow0 = 15.0 * int($rm_sun_tommorow / 15.0);
881              
882 2 100       5 if($rm_sun_today0 != $rm_sun_tommorow0){
883 1         4 return($sekki24[$rm_sun_tommorow0 / 15]);
884             }else{
885 1         3 return('');
886             }
887             }
888              
889             1;