File Coverage

blib/lib/Date/Qreki.pm
Criterion Covered Total %
statement 353 406 86.9
branch 37 60 61.6
condition 15 36 41.6
subroutine 15 16 93.7
pod 2 12 16.6
total 422 530 79.6


line stmt bran cond sub pod time code
1             =encoding UTF-8
2              
3             =head1 NAME
4              
5             Date::Qreki - convert Gregorian to Japanese "kyureki" dates.
6              
7             =head1 SYNOPSIS
8              
9             This module is currently undocumented, so to use it you need to read
10             the source code. If you are interested in helping write documentation
11             for the module or would like to discuss, please contact the module
12             author or visit
13             L
14             and vote for this project.
15              
16             =head1 DESCRIPTION
17              
18             =head1 FUNCTIONS
19              
20             =head2 calc_kyureki
21              
22             =head2 get_rokuyou
23              
24             =head1 SEE ALSO
25              
26             =head1 COPYRIGHT
27              
28             Date::Qreki is copyright H. Takano, N. Ueno.
29              
30             =head1 LICENSE
31              
32             The original licence in Japanese reads as follows:
33              
34             19. 配布規定について
35              
36             本当は、「一般常識の許す範囲で...」としたい所ですが、世の中には色々な人
37             がいますので、ある程度の枠組みが必要なのは仕方の無いことなのでしょう。 と
38             もあれ拙者が希望するのは以下のようなものです。
39              
40             i 本スクリプト・説明書を再配布する場合はオリジナルのアーカイブファイ
41             ルに含まれるファイルを全て含み、オリジナルのスクリプト・説明書を改変
42             しないで下さい。 また、 頒布の都合でアーカイブ形式(.arc .zip .zoo
43             等)を変更する場合も同様に扱って下さい。
44              
45             ii 再配布する際の媒体に要するコストを除いて一切の金銭等の授受は禁止い
46             たします。 (他の言語に移植したものを配布する場合にも適用いたしま
47             す。)
48              
49             iii 他の言語に移植したり、 本スクリプトの一部または全部を引用して作成
50             し、これを配布する場合には、オリジナルのスクリプトと本説明書を必ず同
51             梱して下さい。
52             その場合の著作権につきましては、引用した部分のみ著者に帰属し、その外
53             は製作者に帰属します。
54              
55             iv 配布によって著作者が一切の制限を受ける可能性がないようにして下さ
56             い。
57              
58             なお、 いづれの場合におきましても、承諾・転載の報告など一切不要といたしま
59             す。
60              
61             Translation:
62              
63             19 Conditions for redistribution
64              
65             I would prefer to release this under the conditions of "whatever
66             normal common sense allows", but since there are a variety of people
67             in the world, unfortunately I think some form of framework is
68             necessary. My wishes are as follows
69              
70             i. If this script is redistributed, please also include all the
71             original scripts, and do not modify the original script and its
72             documentation. This also applies if the archive format (.arc, .zip,
73             .zoo, etc.) is changed.
74              
75             ii. I forbid any resale of this program beyond the cost of
76             distribution media. (This also applies if the program is translated to
77             a different programming language).
78              
79             iii. If this is translated to a different programming language, or if
80             part or all of this script is used as part of another program, please
81             be sure to include the original script and this explanation with
82             it. If part of this program is used, I retain the copyright of the
83             quoted material only and the remaining program remains copyrighted by
84             its author.
85              
86             iv. Please do not allow the author of this software to be placed under
87             any restrictions by your redistribution.
88              
89             In any case, there is absolutely no need to obtain the author's
90             consent or notify the author.
91              
92             End of artistic translation.
93              
94             The original Awk script and its documentation are in F in
95             the distribution.
96              
97             =head1 AUTHOR
98              
99             Original Awk script by H. Takano. Perl conversion by N. Ueno. This
100             CPAN-ification of N. Ueno's Perl script was performed by Ben Bullock.
101              
102             For enquiries about this Perl module, please contact Ben Bullock
103             .
104              
105             =cut
106              
107             package Date::Qreki;
108             require Exporter;
109             @ISA = qw(Exporter);
110             @EXPORT_OK = qw/calc_kyureki get_rokuyou/;
111 1     1   123452 use warnings;
  1         3  
  1         129  
112 1     1   6 use strict;
  1         2  
  1         87  
113             our $VERSION = 0.05;
114              
115             #=========================================================================
116             # 旧暦計算サンプルプログラム $Revision: 1.1 $
117             # Coded by H.Takano 1993,1994
118             #
119             # Arranged for Perl Script by N.Ueno
120             #
121             #
122             # オリジナルのスクリプトは高野氏のAWKです。下記より入手できます。
123             # http://www.vector.co.jp/soft/dos/personal/se016093.html
124             #
125             #
126             #========================================================================
127              
128             #-----------------------------------------------------------------------
129             # 円周率の定義と(角度の)度からラジアンに変換する係数の定義
130             #-----------------------------------------------------------------------
131 1     1   15 use constant PI => 3.141592653589793238462;
  1         7  
  1         152  
132 1     1   6 use constant k => PI/180.0;
  1         2  
  1         17551  
133              
134             sub deg_cos
135             {
136 22348     22348 0 42970 my ($angle) = @_;
137 22348         61192 return cos ($angle * k);
138             }
139              
140             #=========================================================================
141             # 六曜算出関数
142             #
143             # 引数:新暦年月日
144             # 戻値:0:大安 1:赤口 2:先勝 3:友引 4:先負 5:仏滅
145             #
146             #=========================================================================
147             sub get_rokuyou
148             {
149              
150 4     4 1 6340 my ($year,$mon,$day) = @_;
151 4         8 my ($tm0,$q_year,$q_mon,$q_day,$uruu,$q_yaer);
152              
153 4         11 ($q_yaer,$uruu,$q_mon,$q_day) = calc_kyureki($year,$mon,$day);
154              
155 4         32 return(($q_mon + $q_day) % 6);
156             }
157              
158             #=========================================================================
159             # 新暦に対応する、旧暦を求める。
160             #
161             # 呼び出し時にセットする変数
162             # 引 数 year : 計算する日付
163             # mon
164             # day
165             #
166             # 戻り値 kyureki : 答えの格納先(配列に答えをかえす)
167             #    kyureki[0] : 旧暦年
168             #    kyureki[1] : 平月/閏月 flag .... 平月:0 閏月:1
169             #    kyureki[2] : 旧暦月
170             #    kyureki[3] : 旧暦日
171             #
172             #=========================================================================
173             sub calc_kyureki
174             {
175 8     8 1 4127 my ($year,$mon,$day) = @_;
176 8         13 my (@kyureki,$tm,@saku,$lap,@a,$i,@m);
177              
178 8         33 my $tm0 = YMDT2JD($year,$mon,$day,0,0,0);
179              
180             #-----------------------------------------------------------------------
181             # 計算対象の直前にあたる二分二至の時刻を求める
182             # chu[0,0]:二分二至の時刻 chu[0,1]:その時の太陽黄経
183             #-----------------------------------------------------------------------
184 8         11 my @chu;
185 8         21 ($chu[0][0],$chu[0][1]) = before_nibun($tm0);
186              
187             #-----------------------------------------------------------------------
188             # 中気の時刻を計算(4回計算する)
189             # chu[i,0]:中気の時刻 chu[i,1]:太陽黄経
190             #-----------------------------------------------------------------------
191 8         27 for($i=1;$i<4;$i++){
192 24         107 ($chu[$i][0],$chu[$i][1]) = calc_chu($chu[$i-1][0]+32.0);
193             }
194              
195             #-----------------------------------------------------------------------
196             # 計算対象の直前にあたる二分二至の直前の朔の時刻を求める
197             #-----------------------------------------------------------------------
198 8         35 $saku[0] = calc_saku($chu[0][0]);
199              
200              
201             #-----------------------------------------------------------------------
202             # 朔の時刻を求める
203             #-----------------------------------------------------------------------
204 8         53 for($i=1;$i<5;$i++){
205 32         57 $tm=$saku[$i-1];
206 32         30 $tm += 30.0;
207 32         910 $saku[$i]=calc_saku($tm);
208              
209             # 前と同じ時刻を計算した場合(両者の差が26日以内)には、初期値を
210             # +33日にして再実行させる。
211 32 50       318 if( abs( int($saku[$i-1])-int($saku[$i]) ) <= 26.0 ){
212 0         0 $saku[$i]=calc_saku($saku[$i-1]+35.0);
213             }
214             }
215              
216             #-----------------------------------------------------------------------
217             # saku[1]が二分二至の時刻以前になってしまった場合には、朔をさかのぼり過ぎ
218             # たと考えて、朔の時刻を繰り下げて修正する。
219             # その際、計算もれ(saku[4])になっている部分を補うため、朔の時刻を計算
220             # する。(近日点通過の近辺で朔があると起こる事があるようだ...?)
221             #-----------------------------------------------------------------------
222 8 50       68 if( int($saku[1]) <= int($chu[0][0]) ){
    50          
223 0         0 for($i=0;$i<5;$i++){
224 0         0 $saku[$i]=$saku[$i+1];
225             }
226 0         0 $saku[4] = calc_saku($saku[3]+35.0);
227             }
228              
229             #-----------------------------------------------------------------------
230             # saku[0]が二分二至の時刻以後になってしまった場合には、朔をさかのぼり足
231             # りないと見て、朔の時刻を繰り上げて修正する。
232             # その際、計算もれ(saku[0])になっている部分を補うため、朔の時刻を計算
233             # する。(春分点の近辺で朔があると起こる事があるようだ...?)
234             #-----------------------------------------------------------------------
235             elsif( int($saku[0]) > int($chu[0][0]) ){
236 0         0 for($i=4;$i>0;$i--){
237 0         0 $saku[$i] = $saku[$i-1];
238             }
239 0         0 $saku[0] = calc_saku($saku[0]-27.0);
240             }
241              
242             #-----------------------------------------------------------------------
243             # 閏月検索Flagセット
244             # (節月で4ヶ月の間に朔が5回あると、閏月がある可能性がある。)
245             # lap=0:平月 lap=1:閏月
246             #-----------------------------------------------------------------------
247 8 50       32 if(int($saku[4]) <= int($chu[3][0]) ){
248 0         0 $lap=1;
249             }else{
250 8         13 $lap=0;
251             }
252              
253             #-----------------------------------------------------------------------
254             # 朔日行列の作成
255             # m[i,0] ... 月名(1:正月 2:2月 3:3月 ....)
256             # m[i,1] ... 閏フラグ(0:平月 1:閏月)
257             # m[i,2] ... 朔日のjd
258             #-----------------------------------------------------------------------
259 8         60 $m[0][0]=int($chu[0][1]/30.0) + 2;
260 8 50 33     57 if(defined $m[0][1] && $m[0][1] > 12 ){
261 0         0 $m[0][0]-=12;
262             }
263 8         20 $m[0][2]=int($saku[0]);
264 8         15 $m[0][1]=0;
265              
266 8         25 for($i=1;$i<5;$i++){
267 32 50 33     75 if($lap == 1 && $i !=1 ){
268 0 0 0     0 if( int($chu[$i-1][0]) <= int($saku[$i-1]) || int($chu[$i-1][0]) >= int($saku[$i]) ){
269 0         0 $m[$i-1][0] = $m[$i-2][0];
270 0         0 $m[$i-1][1] = 1;
271 0         0 $m[$i-1][2] = int($saku[$i-1]);
272 0         0 $lap=0;
273             }
274             }
275 32         89 $m[$i][0] = $m[$i-1][0]+1;
276 32 100       65 if( $m[$i][0] > 12 ){
277 6         12 $m[$i][0]-=12;
278             }
279 32         53 $m[$i][2]=int($saku[$i]);
280 32         150 $m[$i][1]=0;
281             }
282              
283             #-----------------------------------------------------------------------
284             # 朔日行列から旧暦を求める。
285             #-----------------------------------------------------------------------
286 8         12 my $state=0;
287 8         25 for($i=0;$i<5;$i++){
288 28 100       126 if(int($tm0) < int($m[$i][2])){
    50          
289 8         10 $state=1;
290 8         22 last;
291             }elsif(int($tm0) == int($m[$i][2])){
292 0         0 $state=2;
293 0         0 last;
294             }
295             }
296 8 50 33     65 if($state==0||$state==1){
297 8         11 $i--;
298             }
299              
300 8         17 $kyureki[1]=$m[$i][1];
301 8         16 $kyureki[2]=$m[$i][0];
302 8         24 $kyureki[3]=int($tm0)-int($m[$i][2])+1;
303              
304             #-----------------------------------------------------------------------
305             # 旧暦年の計算
306             # (旧暦月が10以上でかつ新暦月より大きい場合には、
307             # まだ年を越していないはず...)
308             #-----------------------------------------------------------------------
309              
310 8         27 @a = JD2YMDT($tm0);
311 8         18 $kyureki[0] = $a[0];
312 8 100 66     366 if($kyureki[2] > 9 && $kyureki[2] > $a[1]){
313 4         7 $kyureki[0]--;
314             }
315              
316 8         88 return($kyureki[0],$kyureki[1],$kyureki[2],$kyureki[3]);
317              
318             }
319              
320             #=========================================================================
321             # 中気の時刻を求める
322             #
323             # 呼び出し時にセットする変数
324             # tm ........ 計算対象となる時刻(ユリウス日)
325             # chu ....... 戻り値を格納する配列のポインター
326             # i ......... 戻り値を格納する配列の要素番号
327             # 戻り値 .... 中気の時刻、その時の黄経を配列で渡す
328             #
329             #=========================================================================
330             sub calc_chu
331             {
332 24     24 0 30 my ($tm) = @_;
333 24         30 my ($tm1,$tm2,$t,$rm_sun0,$rm_sun,$delta_t1,$delta_t2,$delta_rm);
334 0         0 my (@temp);
335             #-----------------------------------------------------------------------
336             #時刻引数を分解する
337             #-----------------------------------------------------------------------
338 24         29 $tm1 = int( $tm );
339 24         25 $tm2 = $tm - $tm1;
340              
341             #-----------------------------------------------------------------------
342             # JST ==> DT (補正時刻=0.0sec と仮定して計算)
343             #-----------------------------------------------------------------------
344 24         30 $tm2-=9.0/24.0;
345              
346             #-----------------------------------------------------------------------
347             # 中気の黄経 λsun0 を求める
348             #-----------------------------------------------------------------------
349 24         30 $t=($tm2+0.5) / 36525.0;
350 24         35 $t=$t + ($tm1-2451545.0) / 36525.0;
351 24         48 $rm_sun = LONGITUDE_SUN( $t );
352              
353 24         44 $rm_sun0 = 30.0*int($rm_sun/30.0);
354              
355             #-----------------------------------------------------------------------
356             # 繰り返し計算によって中気の時刻を計算する
357             # (誤差が±1.0 sec以内になったら打ち切る。)
358             #-----------------------------------------------------------------------
359 24         29 $delta_t1 = 0;
360 24         83 for( $delta_t2 = 1.0 ; abs( $delta_t1 + $delta_t2 ) > ( 1.0 / 86400.0 ) ; ){
361              
362             #-----------------------------------------------------------------------
363             # λsun を計算
364             #-----------------------------------------------------------------------
365 108         130 $t =($tm2+0.5) / 36525.0;
366 108         222 $t =$t + ($tm1-2451545.0) / 36525.0;
367 108         344 $rm_sun=LONGITUDE_SUN( $t );
368              
369             #-----------------------------------------------------------------------
370             # 黄経差 Δλ=λsun −λsun0
371             #-----------------------------------------------------------------------
372 108         138 $delta_rm = $rm_sun - $rm_sun0 ;
373              
374             #-----------------------------------------------------------------------
375             # Δλの引き込み範囲(±180°)を逸脱した場合には、補正を行う
376             #-----------------------------------------------------------------------
377 108 100       362 if( $delta_rm > 180.0 ){
    50          
378 8         14 $delta_rm-=360.0;
379             }elsif( $delta_rm < -180.0 ){
380 0         0 $delta_rm+=360.0;
381             }
382              
383             #-----------------------------------------------------------------------
384             # 時刻引数の補正値 Δt
385             # delta_t = delta_rm * 365.2 / 360.0;
386             #-----------------------------------------------------------------------
387 108         150 $delta_t1 = int($delta_rm * 365.2 / 360.0);
388 108         368 $delta_t2 = $delta_rm * 365.2 / 360.0;
389 108         126 $delta_t2 -= $delta_t1;
390              
391             #-----------------------------------------------------------------------
392             # 時刻引数の補正
393             # tm -= delta_t;
394             #-----------------------------------------------------------------------
395 108         108 $tm1 = $tm1 - $delta_t1;
396 108         117 $tm2 = $tm2 - $delta_t2;
397 108 100       440 if($tm2 < 0){
398 18         22 $tm2+=1.0;$tm1-=1.0;
  18         43  
399             }
400             }
401              
402             #-----------------------------------------------------------------------
403             # 戻り値の作成
404             # chu[i,0]:時刻引数を合成するのと、DT ==> JST 変換を行い、戻り値とする
405             # (補正時刻=0.0sec と仮定して計算)
406             # chu[i,1]:黄経
407             #-----------------------------------------------------------------------
408 24         100 $temp[0] = $tm2+9.0/24.0;
409 24         40 $temp[0] += $tm1;
410 24         33 $temp[1] = $rm_sun0;
411              
412 24         201 return(@temp);
413             }
414              
415             #=========================================================================
416             # 直前の二分二至の時刻を求める
417             #
418             # 呼び出し時にセットする変数
419             # tm ........ 計算対象となる時刻(ユリウス日)
420             # nibun ..... 戻り値を格納する配列のポインター
421             # 戻り値 .... 二分二至の時刻、その時の黄経を配列で渡す
422             # (戻り値の渡し方がちょっと気にくわないがまぁいいや。)
423             #=========================================================================
424             sub before_nibun
425             {
426 8     8 0 16 my ($tm) = @_;
427 8         12 my (@nibun,$tm1,$tm2,$t,$rm_sun0,$rm_sun,$delta_t1,$delta_t2,$delta_rm);
428              
429             #-----------------------------------------------------------------------
430             #時刻引数を分解する
431             #-----------------------------------------------------------------------
432 8         11 $tm1 = int( $tm );
433 8         10 $tm2 = $tm - $tm1;
434              
435             #-----------------------------------------------------------------------
436             # JST ==> DT (補正時刻=0.0sec と仮定して計算)
437             #-----------------------------------------------------------------------
438 8         12 $tm2-=9.0/24.0;
439              
440             #-----------------------------------------------------------------------
441             # 直前の二分二至の黄経 λsun0 を求める
442             #-----------------------------------------------------------------------
443 8         46 $t=($tm2+0.5) / 36525.0;
444 8         16 $t=$t + ($tm1-2451545.0) / 36525.0;
445 8         15 $rm_sun=LONGITUDE_SUN( $t );
446 8         15 $rm_sun0=90*int($rm_sun/90.0);
447              
448             #-----------------------------------------------------------------------
449             # 繰り返し計算によって直前の二分二至の時刻を計算する
450             # (誤差が±1.0 sec以内になったら打ち切る。)
451             #-----------------------------------------------------------------------
452 8         547 $delta_t1 = 0;
453 8         31 for( $delta_t2 = 1.0 ; abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ; ){
454              
455             #-----------------------------------------------------------------------
456             # λsun を計算
457             #-----------------------------------------------------------------------
458 44         50 $t=($tm2+0.5) / 36525.0;
459 44         55 $t=$t + ($tm1-2451545.0) / 36525.0;
460 44         75 $rm_sun=LONGITUDE_SUN( $t );
461              
462             #-----------------------------------------------------------------------
463             # 黄経差 Δλ=λsun −λsun0
464             #-----------------------------------------------------------------------
465 44         57 $delta_rm = $rm_sun - $rm_sun0 ;
466              
467             #-----------------------------------------------------------------------
468             # Δλの引き込み範囲(±180°)を逸脱した場合には、補正を行う
469             #-----------------------------------------------------------------------
470 44 50       180 if( $delta_rm > 180.0 ){
    50          
471 0         0 $delta_rm-=360.0;
472             }elsif( $delta_rm < -180.0){
473 0         0 $delta_rm+=360.0;
474             }
475              
476             #-----------------------------------------------------------------------
477             # 時刻引数の補正値 Δt
478             # delta_t = delta_rm * 365.2 / 360.0;
479             #-----------------------------------------------------------------------
480 44         65 $delta_t1 = int($delta_rm * 365.2 / 360.0);
481 44         56 $delta_t2 = $delta_rm * 365.2 / 360.0;
482 44         43 $delta_t2 -= $delta_t1;
483              
484             #-----------------------------------------------------------------------
485             # 時刻引数の補正
486             # tm -= delta_t;
487             #-----------------------------------------------------------------------
488 44         44 $tm1 = $tm1 - $delta_t1;
489 44         46 $tm2 = $tm2 - $delta_t2;
490 44 100       265 if($tm2 < 0){
491 10         8 $tm2+=1.0;$tm1-=1.0;
  10         25  
492             }
493              
494             }
495              
496             #-----------------------------------------------------------------------
497             # 戻り値の作成
498             # nibun[0,0]:時刻引数を合成するのと、DT ==> JST 変換を行い、戻り値とする
499             # (補正時刻=0.0sec と仮定して計算)
500             # nibun[0,1]:黄経
501             #-----------------------------------------------------------------------
502 8         16 $nibun[0] = $tm2+9.0/24.0;
503 8         16 $nibun[0] += $tm1;
504 8         55 $nibun[1] = $rm_sun0;
505              
506 8         56 return(@nibun);
507              
508             }
509              
510             #=========================================================================
511             # 朔の計算
512             # 与えられた時刻の直近の朔の時刻(JST)を求める
513             #
514             # 呼び出し時にセットする変数
515             # tm ........ 計算対象となる時刻(ユリウス日)
516             # 戻り値 .... 朔の時刻
517             #
518             # ※ 引数、戻り値ともユリウス日で表し、時分秒は日の小数で表す。
519             #
520             #=========================================================================
521             sub calc_saku
522             {
523 40     40 0 59 my ($tm) = @_;
524 40         52 my ($lc,$t,$tm1,$tm2,$rm_sun,$rm_moon,$delta_rm,$delta_t1,$delta_t2);
525              
526             #-----------------------------------------------------------------------
527             # ループカウンタのセット
528             #-----------------------------------------------------------------------
529 40         346 $lc=1;
530              
531             #-----------------------------------------------------------------------
532             #時刻引数を分解する
533             #-----------------------------------------------------------------------
534 40         53 $tm1 = int( $tm );
535 40         119 $tm2 = $tm - $tm1;
536              
537             #-----------------------------------------------------------------------
538             # JST ==> DT (補正時刻=0.0sec と仮定して計算)
539             #-----------------------------------------------------------------------
540 40         47 $tm2-=9.0/24.0;
541              
542             #-----------------------------------------------------------------------
543             # 繰り返し計算によって朔の時刻を計算する
544             # (誤差が±1.0 sec以内になったら打ち切る。)
545             #-----------------------------------------------------------------------
546 40         42 $delta_t1 = 0;
547 40         196 for( $delta_t2 = 1.0 ; abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ; $lc++){
548              
549             #-----------------------------------------------------------------------
550             # 太陽の黄経λsun ,月の黄経λmoon を計算
551             # t = (tm - 2451548.0 + 0.5)/36525.0;
552             #-----------------------------------------------------------------------
553 252         341 $t=($tm2+0.5) / 36525.0;
554 252         494 $t=$t + ($tm1-2451545.0) / 36525.0;
555 252         467 $rm_sun=LONGITUDE_SUN( $t );
556 252         490 $rm_moon=LONGITUDE_MOON( $t );
557              
558             #-----------------------------------------------------------------------
559             # 月と太陽の黄経差Δλ
560             # Δλ=λmoon−λsun
561             #-----------------------------------------------------------------------
562 252         434 $delta_rm = $rm_moon - $rm_sun ;
563              
564             #-----------------------------------------------------------------------
565             # ループの1回目(lc=1)で delta_rm < 0.0 の場合には引き込み範囲に
566             # 入るように補正する
567             #-----------------------------------------------------------------------
568 252 100 100     14517 if( $lc==1 && $delta_rm < 0.0 ){
    50 66        
    100 66        
569 6         16 $delta_rm = NORMALIZATION_ANGLE( $delta_rm );
570             }
571             #-----------------------------------------------------------------------
572             # 春分の近くで朔がある場合(0 ≦λsun≦ 20)で、月の黄経λmoon≧300 の
573             # 場合には、Δλ= 360.0 − Δλ と計算して補正する
574             #-----------------------------------------------------------------------
575             elsif( $rm_sun >= 0 && $rm_sun <= 20 && $rm_moon >= 300 ){
576 0         0 $delta_rm = NORMALIZATION_ANGLE( $delta_rm );
577 0         0 $delta_rm = 360.0 - $delta_rm;
578             }
579             #-----------------------------------------------------------------------
580             # Δλの引き込み範囲(±40°)を逸脱した場合には、補正を行う
581             #-----------------------------------------------------------------------
582             elsif( abs( $delta_rm ) > 40.0 ) {
583 2         5 $delta_rm = NORMALIZATION_ANGLE( $delta_rm );
584             }
585              
586             #-----------------------------------------------------------------------
587             # 時刻引数の補正値 Δt
588             # delta_t = delta_rm * 29.530589 / 360.0;
589             #-----------------------------------------------------------------------
590 252         404 $delta_t1 = int($delta_rm * 29.530589 / 360.0);
591 252         981 $delta_t2 = $delta_rm * 29.530589 / 360.0;
592 252         470 $delta_t2 -= $delta_t1;
593              
594             #-----------------------------------------------------------------------
595             # 時刻引数の補正
596             # tm -= delta_t;
597             #-----------------------------------------------------------------------
598 252         542 $tm1 = $tm1 - $delta_t1;
599 252         350 $tm2 = $tm2 - $delta_t2;
600 252 100       522 if($tm2 < 0.0){
601 38         46 $tm2+=1.0;$tm1-=1.0;
  38         150  
602             }
603              
604             #-----------------------------------------------------------------------
605             # ループ回数が15回になったら、初期値 tm を tm-26 とする。
606             #-----------------------------------------------------------------------
607 252 50 33     1599 if($lc == 15 && abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ){
    50 33        
608 0         0 $tm1 = int( $tm-26 );
609 0         0 $tm2 = 0;
610             }
611              
612             #-----------------------------------------------------------------------
613             # 初期値を補正したにも関わらず、振動を続ける場合には初期値を答えとして
614             # 返して強制的にループを抜け出して異常終了させる。
615             #-----------------------------------------------------------------------
616             elsif( $lc > 30 && abs( $delta_t1+$delta_t2 ) > ( 1.0 / 86400.0 ) ){
617 0         0 $tm1=$tm;$tm2=0;
  0         0  
618 0         0 last;
619             }
620             }
621              
622             #-----------------------------------------------------------------------
623             # 時刻引数を合成するのと、DT ==> JST 変換を行い、戻り値とする
624             # (補正時刻=0.0sec と仮定して計算)
625             #-----------------------------------------------------------------------
626              
627 40         150 return($tm2+$tm1+9.0/24.0);
628             }
629              
630             #=========================================================================
631             # 角度の正規化を行う。すなわち引数の範囲を 0≦θ<360 にする。
632             #=========================================================================
633             sub NORMALIZATION_ANGLE
634             {
635 23984     23984 0 36840 my ($angle) = @_;
636 23984         43158 my ($angle1,$angle2);
637              
638 23984 100       70578 if( $angle < 0.0 ){
639 21756         33072 $angle1 = -$angle;
640 21756         29479 $angle2 = int( $angle1 / 360.0 );
641 21756         38103 $angle1 -= 360.0 * $angle2;
642 21756         32919 $angle1 = 360.0 - $angle1;
643             }else{
644 2228         2975 $angle1 = int( $angle / 360.0 );
645 2228         3075 $angle1 = $angle - 360.0 * $angle1;
646             }
647              
648 23984         48699 return($angle1);
649             }
650              
651             #=========================================================================
652             # 太陽の黄経 λsun を計算する
653             #=========================================================================
654             sub LONGITUDE_SUN
655             {
656 436     436 0 625 my ($t) = @_;
657 436         574 my ($th,$ang);
658              
659             #-----------------------------------------------------------------------
660             # 摂動項の計算
661             #-----------------------------------------------------------------------
662 436         1147 $ang = NORMALIZATION_ANGLE( 31557.0 * $t + 161.0 );
663 436         1067 $th = .0004 * deg_cos( $ang );
664 436         1530 $ang = NORMALIZATION_ANGLE( 29930.0 * $t + 48.0 );
665 436         1276 $th = $th + .0004 * deg_cos ($ang );
666 436         1154 $ang = NORMALIZATION_ANGLE( 2281.0 * $t + 221.0 );
667 436         927 $th = $th + .0005 * deg_cos ($ang );
668 436         1091 $ang = NORMALIZATION_ANGLE( 155.0 * $t + 118.0 );
669 436         1498 $th = $th + .0005 * deg_cos ($ang );
670 436         858 $ang = NORMALIZATION_ANGLE( 33718.0 * $t + 316.0 );
671 436         945 $th = $th + .0006 * deg_cos ($ang );
672 436         1343 $ang = NORMALIZATION_ANGLE( 9038.0 * $t + 64.0 );
673 436         1276 $th = $th + .0007 * deg_cos ($ang );
674 436         1704 $ang = NORMALIZATION_ANGLE( 3035.0 * $t + 110.0 );
675 436         860 $th = $th + .0007 * deg_cos ($ang );
676 436         8365 $ang = NORMALIZATION_ANGLE( 65929.0 * $t + 45.0 );
677 436         877 $th = $th + .0007 * deg_cos ($ang );
678 436         1207 $ang = NORMALIZATION_ANGLE( 22519.0 * $t + 352.0 );
679 436         917 $th = $th + .0013 * deg_cos ($ang );
680 436         1049 $ang = NORMALIZATION_ANGLE( 45038.0 * $t + 254.0 );
681 436         945 $th = $th + .0015 * deg_cos ($ang );
682 436         871 $ang = NORMALIZATION_ANGLE( 445267.0 * $t + 208.0 );
683 436         862 $th = $th + .0018 * deg_cos ($ang );
684 436         1370 $ang = NORMALIZATION_ANGLE( 19.0 * $t + 159.0 );
685 436         879 $th = $th + .0018 * deg_cos ($ang );
686 436         1145 $ang = NORMALIZATION_ANGLE( 32964.0 * $t + 158.0 );
687 436         1028 $th = $th + .0020 * deg_cos ($ang );
688 436         1156 $ang = NORMALIZATION_ANGLE( 71998.1 * $t + 265.1 );
689 436         882 $th = $th + .0200 * deg_cos ($ang );
690 436         1309 $ang = NORMALIZATION_ANGLE( 35999.05 * $t + 267.52 );
691 436         1195 $th = $th - 0.0048 * $t * deg_cos ($ang ) ;
692 436         669 $th = $th + 1.9147 * deg_cos ($ang ) ;
693              
694             #-----------------------------------------------------------------------
695             # 比例項の計算
696             #-----------------------------------------------------------------------
697 436         1304 $ang = NORMALIZATION_ANGLE( 36000.7695 * $t );
698 436         1106 $ang = NORMALIZATION_ANGLE( $ang + 280.4659 );
699 436         1421 $th = NORMALIZATION_ANGLE( $th + $ang );
700              
701 436         843 return($th);
702             }
703              
704             #=========================================================================
705             # 月の黄経 λmoon を計算する
706             #=========================================================================
707             sub LONGITUDE_MOON
708             {
709 252     252 0 507 my ($t) = @_;
710 252         255 my ($th,$ang);
711              
712             #-----------------------------------------------------------------------
713             # 摂動項の計算
714             #-----------------------------------------------------------------------
715 252         537 $ang = NORMALIZATION_ANGLE( 2322131.0 * $t + 191.0 );
716 252         727 $th = .0003 * deg_cos ($ang );
717 252         851 $ang = NORMALIZATION_ANGLE( 4067.0 * $t + 70.0 );
718 252         525 $th = $th + .0003 * deg_cos ($ang );
719 252         758 $ang = NORMALIZATION_ANGLE( 549197.0 * $t + 220.0 );
720 252         500 $th = $th + .0003 * deg_cos ($ang );
721 252         477 $ang = NORMALIZATION_ANGLE( 1808933.0 * $t + 58.0 );
722 252         524 $th = $th + .0003 * deg_cos ($ang );
723 252         626 $ang = NORMALIZATION_ANGLE( 349472.0 * $t + 337.0 );
724 252         515 $th = $th + .0003 * deg_cos ($ang );
725 252         862 $ang = NORMALIZATION_ANGLE( 381404.0 * $t + 354.0 );
726 252         460 $th = $th + .0003 * deg_cos ($ang );
727 252         645 $ang = NORMALIZATION_ANGLE( 958465.0 * $t + 340.0 );
728 252         575 $th = $th + .0003 * deg_cos ($ang );
729 252         529 $ang = NORMALIZATION_ANGLE( 12006.0 * $t + 187.0 );
730 252         549 $th = $th + .0004 * deg_cos ($ang );
731 252         957 $ang = NORMALIZATION_ANGLE( 39871.0 * $t + 223.0 );
732 252         586 $th = $th + .0004 * deg_cos ($ang );
733 252         522 $ang = NORMALIZATION_ANGLE( 509131.0 * $t + 242.0 );
734 252         419 $th = $th + .0005 * deg_cos ($ang );
735 252         978 $ang = NORMALIZATION_ANGLE( 1745069.0 * $t + 24.0 );
736 252         551 $th = $th + .0005 * deg_cos ($ang );
737 252         675 $ang = NORMALIZATION_ANGLE( 1908795.0 * $t + 90.0 );
738 252         1018 $th = $th + .0005 * deg_cos ($ang );
739 252         564 $ang = NORMALIZATION_ANGLE( 2258267.0 * $t + 156.0 );
740 252         527 $th = $th + .0006 * deg_cos ($ang );
741 252         494 $ang = NORMALIZATION_ANGLE( 111869.0 * $t + 38.0 );
742 252         677 $th = $th + .0006 * deg_cos ($ang );
743 252         715 $ang = NORMALIZATION_ANGLE( 27864.0 * $t + 127.0 );
744 252         417 $th = $th + .0007 * deg_cos ($ang );
745 252         871 $ang = NORMALIZATION_ANGLE( 485333.0 * $t + 186.0 );
746 252         529 $th = $th + .0007 * deg_cos ($ang );
747 252         583 $ang = NORMALIZATION_ANGLE( 405201.0 * $t + 50.0 );
748 252         466 $th = $th + .0007 * deg_cos ($ang );
749 252         836 $ang = NORMALIZATION_ANGLE( 790672.0 * $t + 114.0 );
750 252         428 $th = $th + .0007 * deg_cos ($ang );
751 252         503 $ang = NORMALIZATION_ANGLE( 1403732.0 * $t + 98.0 );
752 252         530 $th = $th + .0008 * deg_cos ($ang );
753 252         944 $ang = NORMALIZATION_ANGLE( 858602.0 * $t + 129.0 );
754 252         803 $th = $th + .0009 * deg_cos ($ang );
755 252         816 $ang = NORMALIZATION_ANGLE( 1920802.0 * $t + 186.0 );
756 252         520 $th = $th + .0011 * deg_cos ($ang );
757 252         691 $ang = NORMALIZATION_ANGLE( 1267871.0 * $t + 249.0 );
758 252         610 $th = $th + .0012 * deg_cos ($ang );
759 252         1154 $ang = NORMALIZATION_ANGLE( 1856938.0 * $t + 152.0 );
760 252         455 $th = $th + .0016 * deg_cos ($ang );
761 252         486 $ang = NORMALIZATION_ANGLE( 401329.0 * $t + 274.0 );
762 252         545 $th = $th + .0018 * deg_cos ($ang );
763 252         474 $ang = NORMALIZATION_ANGLE( 341337.0 * $t + 16.0 );
764 252         514 $th = $th + .0021 * deg_cos ($ang );
765 252         814 $ang = NORMALIZATION_ANGLE( 71998.0 * $t + 85.0 );
766 252         512 $th = $th + .0021 * deg_cos ($ang );
767 252         797 $ang = NORMALIZATION_ANGLE( 990397.0 * $t + 357.0 );
768 252         502 $th = $th + .0021 * deg_cos ($ang );
769 252         541 $ang = NORMALIZATION_ANGLE( 818536.0 * $t + 151.0 );
770 252         561 $th = $th + .0022 * deg_cos ($ang );
771 252         706 $ang = NORMALIZATION_ANGLE( 922466.0 * $t + 163.0 );
772 252         663 $th = $th + .0023 * deg_cos ($ang );
773 252         929 $ang = NORMALIZATION_ANGLE( 99863.0 * $t + 122.0 );
774 252         511 $th = $th + .0024 * deg_cos ($ang );
775 252         1050 $ang = NORMALIZATION_ANGLE( 1379739.0 * $t + 17.0 );
776 252         558 $th = $th + .0026 * deg_cos ($ang );
777 252         569 $ang = NORMALIZATION_ANGLE( 918399.0 * $t + 182.0 );
778 252         617 $th = $th + .0027 * deg_cos ($ang );
779 252         599 $ang = NORMALIZATION_ANGLE( 1934.0 * $t + 145.0 );
780 252         626 $th = $th + .0028 * deg_cos ($ang );
781 252         755 $ang = NORMALIZATION_ANGLE( 541062.0 * $t + 259.0 );
782 252         467 $th = $th + .0037 * deg_cos ($ang );
783 252         597 $ang = NORMALIZATION_ANGLE( 1781068.0 * $t + 21.0 );
784 252         687 $th = $th + .0038 * deg_cos ($ang );
785 252         569 $ang = NORMALIZATION_ANGLE( 133.0 * $t + 29.0 );
786 252         856 $th = $th + .0040 * deg_cos ($ang );
787 252         493 $ang = NORMALIZATION_ANGLE( 1844932.0 * $t + 56.0 );
788 252         515 $th = $th + .0040 * deg_cos ($ang );
789 252         685 $ang = NORMALIZATION_ANGLE( 1331734.0 * $t + 283.0 );
790 252         616 $th = $th + .0040 * deg_cos ($ang );
791 252         501 $ang = NORMALIZATION_ANGLE( 481266.0 * $t + 205.0 );
792 252         620 $th = $th + .0050 * deg_cos ($ang );
793 252         482 $ang = NORMALIZATION_ANGLE( 31932.0 * $t + 107.0 );
794 252         634 $th = $th + .0052 * deg_cos ($ang );
795 252         914 $ang = NORMALIZATION_ANGLE( 926533.0 * $t + 323.0 );
796 252         520 $th = $th + .0068 * deg_cos ($ang );
797 252         718 $ang = NORMALIZATION_ANGLE( 449334.0 * $t + 188.0 );
798 252         532 $th = $th + .0079 * deg_cos ($ang );
799 252         684 $ang = NORMALIZATION_ANGLE( 826671.0 * $t + 111.0 );
800 252         597 $th = $th + .0085 * deg_cos ($ang );
801 252         477 $ang = NORMALIZATION_ANGLE( 1431597.0 * $t + 315.0 );
802 252         428 $th = $th + .0100 * deg_cos ($ang );
803 252         1214 $ang = NORMALIZATION_ANGLE( 1303870.0 * $t + 246.0 );
804 252         669 $th = $th + .0107 * deg_cos ($ang );
805 252         770 $ang = NORMALIZATION_ANGLE( 489205.0 * $t + 142.0 );
806 252         473 $th = $th + .0110 * deg_cos ($ang );
807 252         901 $ang = NORMALIZATION_ANGLE( 1443603.0 * $t + 52.0 );
808 252         437 $th = $th + .0125 * deg_cos ($ang );
809 252         427 $ang = NORMALIZATION_ANGLE( 75870.0 * $t + 41.0 );
810 252         662 $th = $th + .0154 * deg_cos ($ang );
811 252         859 $ang = NORMALIZATION_ANGLE( 513197.9 * $t + 222.5 );
812 252         735 $th = $th + .0304 * deg_cos ($ang );
813 252         659 $ang = NORMALIZATION_ANGLE( 445267.1 * $t + 27.9 );
814 252         449 $th = $th + .0347 * deg_cos ($ang );
815 252         741 $ang = NORMALIZATION_ANGLE( 441199.8 * $t + 47.4 );
816 252         511 $th = $th + .0409 * deg_cos ($ang );
817 252         748 $ang = NORMALIZATION_ANGLE( 854535.2 * $t + 148.2 );
818 252         649 $th = $th + .0458 * deg_cos ($ang );
819 252         587 $ang = NORMALIZATION_ANGLE( 1367733.1 * $t + 280.7 );
820 252         428 $th = $th + .0533 * deg_cos ($ang );
821 252         527 $ang = NORMALIZATION_ANGLE( 377336.3 * $t + 13.2 );
822 252         670 $th = $th + .0571 * deg_cos ($ang );
823 252         584 $ang = NORMALIZATION_ANGLE( 63863.5 * $t + 124.2 );
824 252         638 $th = $th + .0588 * deg_cos ($ang );
825 252         435 $ang = NORMALIZATION_ANGLE( 966404.0 * $t + 276.5 );
826 252         712 $th = $th + .1144 * deg_cos ($ang );
827 252         1475 $ang = NORMALIZATION_ANGLE( 35999.05 * $t + 87.53 );
828 252         926 $th = $th + .1851 * deg_cos ($ang );
829 252         902 $ang = NORMALIZATION_ANGLE( 954397.74 * $t + 179.93 );
830 252         497 $th = $th + .2136 * deg_cos ($ang );
831 252         703 $ang = NORMALIZATION_ANGLE( 890534.22 * $t + 145.7 );
832 252         771 $th = $th + .6583 * deg_cos ($ang );
833 252         793 $ang = NORMALIZATION_ANGLE( 413335.35 * $t + 10.74 );
834 252         1146 $th = $th + 1.2740 * deg_cos ($ang );
835 252         578 $ang = NORMALIZATION_ANGLE( 477198.868 * $t + 44.963 );
836 252         464 $th = $th + 6.2888 * deg_cos ($ang );
837              
838             #-----------------------------------------------------------------------
839             # 比例項の計算
840             #-----------------------------------------------------------------------
841 252         462 $ang = NORMALIZATION_ANGLE( 481267.8809 * $t );
842 252         759 $ang = NORMALIZATION_ANGLE( $ang + 218.3162 );
843 252         656 $th = NORMALIZATION_ANGLE( $th + $ang );
844              
845 252         395 return($th);
846             }
847              
848             #=========================================================================
849             # 年月日、時分秒(世界時)からユリウス日(JD)を計算する
850             #
851             # ※ この関数では、グレゴリオ暦法による年月日から求めるものである。
852             # (ユリウス暦法による年月日から求める場合には使用できない。)
853             #=========================================================================
854             sub YMDT2JD
855             {
856 8     8 0 17 my ($year,$month,$day,$hour,$min,$sec) = @_;
857 8         16 my ($jd,$t);
858              
859 8 100       33 if( $month < 3.0 ){
860 4         8 $year -= 1.0;
861 4         12 $month += 12.0;
862             }
863              
864 8         23 $jd = int( 365.25 * $year );
865 8         17 $jd += int( $year / 400.0 );
866 8         16 $jd -= int( $year / 100.0 );
867 8         17 $jd += int( 30.59 * ( $month-2.0 ) );
868 8         11 $jd += 1721088;
869 8         11 $jd += $day;
870              
871 8         10 $t = $sec / 3600.0;
872 8         13 $t += $min /60.0;
873 8         11 $t += $hour;
874 8         11 $t = $t / 24.0;
875              
876 8         8 $jd += $t;
877              
878 8         69 return( $jd );
879              
880             }
881              
882             #=========================================================================
883             # ユリウス日(JD)から年月日、時分秒(世界時)を計算する
884             #
885             # 戻り値の配列TIME[]の内訳
886             # TIME[0] ... 年 TIME[1] ... 月 TIME[2] ... 日
887             # TIME[3] ... 時 TIME[4] ... 分 TIME[5] ... 秒
888             #
889             # ※ この関数で求めた年月日は、グレゴリオ暦法によって表されている。
890             #
891             #=========================================================================
892             sub JD2YMDT
893             {
894              
895 8     8 0 16 my ($JD) = @_;
896 8         10 my (@TIME,$x0,$x1,$x2,$x3,$x4,$x5,$x6,$tm);
897              
898 8         14 $x0 = int( $JD+68570.0);
899 8         14 $x1 = int( $x0/36524.25 );
900 8         15 $x2 = $x0 - int( 36524.25*$x1 + 0.75 );
901 8         100 $x3 = int( ( $x2+1 )/365.2425 );
902 8         13 $x4 = $x2 - int( 365.25*$x3 )+31.0;
903 8         17 $x5 = int( int($x4) / 30.59 );
904 8         16 $x6 = int( int($x5) / 11.0 );
905              
906 8         15 $TIME[2] = $x4 - int( 30.59*$x5 );
907 8         17 $TIME[1] = $x5 - 12*$x6 + 2;
908 8         18 $TIME[0] = 100*( $x1-49 ) + $x3 + $x6;
909              
910             # 2月30日の補正
911 8 50 33     28 if($TIME[1]==2 && $TIME[2] > 28){
912 0 0 0     0 if($TIME[0] % 100 == 0 && $TIME[0] % 400 == 0){
    0          
913 0         0 $TIME[2]=29;
914             }elsif($TIME[0] % 4 ==0){
915 0         0 $TIME[2]=29;
916             }else{
917 0         0 $TIME[2]=28;
918             }
919             }
920              
921 8         15 $tm=86400.0*( $JD - int( $JD ) );
922 8         19 $TIME[3] = int( $tm/3600.0 );
923 8         18 $TIME[4] = int( ($tm - 3600.0*$TIME[3])/60.0 );
924 8         35 $TIME[5] = int( $tm - 3600.0*$TIME[3] - 60*$TIME[4] );
925              
926 8         42 return(@TIME);
927             }
928              
929             #=========================================================================
930             # 今日が24節気かどうか調べる
931             #
932             # 引数  .... 計算対象となる年月日 $year $mon $day
933             #
934             # 戻り値 .... 24節気の名称
935             #
936             #=========================================================================
937             sub check_24sekki
938             {
939 0     0 0   my ($year,$mon,$day) = @_;
940 0           my ($tm1,$tm2,$t,$rm_sun_today,$rm_sun_today0,$rm_sun_tommorow,$rm_sun_tommorow0);
941              
942             #-----------------------------------------------------------------------
943             # 24節気の定義
944             #-----------------------------------------------------------------------
945 0           my (@sekki24) = ("春分","清明","穀雨","立夏","小満","芒種","夏至","小暑","大暑","立秋","処暑","白露",
946             "秋分","寒露","霜降","立冬","小雪","大雪","冬至","小寒","大寒","立春","雨水","啓蟄");
947              
948 0           my $tm = YMDT2JD($year,$mon,$day,0,0,0);
949              
950             #-----------------------------------------------------------------------
951             #時刻引数を分解する
952             #-----------------------------------------------------------------------
953 0           $tm1 = int( $tm );
954 0           $tm2 = $tm - $tm1;
955 0           $tm2-=9.0/24.0;
956 0           $t=($tm2+0.5) / 36525.0;
957 0           $t=$t + ($tm1-2451545.0) / 36525.0;
958              
959             #今日の太陽の黄経
960 0           $rm_sun_today = LONGITUDE_SUN( $t );
961              
962 0           $tm++;
963 0           $tm1 = int($tm);
964 0           $tm2 = $tm - $tm1;
965 0           $tm2-=9.0/24.0;
966 0           $t=($tm2+0.5) / 36525.0;
967 0           $t=$t + ($tm1-2451545.0) / 36525.0;
968              
969             #明日の太陽の黄経
970 0           $rm_sun_tommorow = LONGITUDE_SUN($t);
971              
972             #
973 0           $rm_sun_today0 = 15.0 * int($rm_sun_today / 15.0);
974 0           $rm_sun_tommorow0 = 15.0 * int($rm_sun_tommorow / 15.0);
975              
976 0 0         if($rm_sun_today0 != $rm_sun_tommorow0){
977 0           return($sekki24[$rm_sun_tommorow0 / 15]);
978             }else{
979 0           return('');
980             }
981             }
982              
983             1;