3 # The subroutines "julian_day" and "riseset" written by
4 # Steve Franke, November 1999.
6 # The formulas used to calculate sunrise and sunset times
7 # are described in Chapters 7, 12, 15, and 25 of
8 # Astronomical Algorithms, Second Edition
10 # Published by Willmann-Bell, Inc.
11 # P.O. Box 35025, Richmond, Virginia 23235
19 @EXPORT = qw($pi $d2r $r2d );
22 use vars qw($pi $d2r $r2d );
35 $year=$year-1 if( $month <= 2 );
36 $month=$month+12 if( $month <= 2);
38 $julianday = int(365.25*($year+4716)+int(30.6001*($month+1)))+$day-13-1524.5;
51 $julianday=julian_day($year,$month,$day);
53 my $tt = ($julianday-2451545)/36525.;
55 my $theta0=280.46061837+360.98564736629*($julianday-2451545.0)+
56 0.000387933*($tt^2)-($tt^3)/38710000;
57 $theta0=$theta0-int($theta0/360)*360;
58 $theta0=$theta0+360 if( $theta0 < 0 );
60 my $L0 = 280.46646+36000.76983*$tt+0.0003032*($tt^2);
61 $L0=$L0-int($L0/360)*360;
62 $L0=$L0+360 if( $L0 < 0 );
64 my $M = 357.52911 + 35999.05029*$tt-0.0001537*($tt^2);
65 $M=$M-int($M/360)*360;
66 $M=$M+360 if( $M < 0 );
68 my $C = (1.914602 - 0.004817*$tt-0.000014*($tt^2))*sin($M*$d2r) +
69 (0.019993 - 0.000101*$tt)*sin(2*$M*$d2r) +
70 0.000289*sin(3*$M*$d2r);
72 my $OMEGA = 125.04 - 1934.136*$tt;
74 my $lambda=$L0+$C-0.00569-0.00478*sin($OMEGA*$d2r);
76 my $epsilon = 23+26./60.+21.448/(60.*60.);
78 my $alpha=atan2(cos($epsilon*$d2r)*sin($lambda*$d2r),cos($lambda*$d2r))*$r2d;
79 $alpha = $alpha-int($alpha/360)*360;
80 $alpha=$alpha+360 if ( $alpha < 0 );
82 my $delta=asin(sin($epsilon*$d2r)*sin($lambda*$d2r))*$r2d;
83 $delta = $delta-int($delta/360)*360;
84 $delta = $delta+360 if ( $delta < 0 );
86 my $arg = (sin(-.8333*$d2r)-sin($lat)*sin($delta*$d2r))/(cos($lat)*cos($delta*$d2r));
87 my $argtest = tan($lat)*tan($delta*$d2r);
89 if ( $argtest < -1. ) {
90 return sprintf("Sun doesn't rise.");
92 if ( $argtest > 1. ) {
93 return sprintf("Sun doesn't set.");
96 my $H0 = acos($arg)*$r2d;
98 my $transit = ($alpha + $lon*$r2d - $theta0)/360.;
99 $transit=$transit+1 if( $transit < 0 );
100 $transit=$transit-1 if( $transit > 1 );
102 my $rise = $transit - $H0/360.;
103 $rise=$rise+1 if( $rise < 0 );
104 $rise=$rise-1 if( $rise > 1 );
106 my $set = $transit + $H0/360.;
107 $set=$set+1 if( $set < 0 );
108 $set=$set-1 if( $set > 1 );
110 return sprintf("Sunrise: %2.2d%2.2dZ Sunset: %2.2d%2.2dZ",int($rise*24),
111 ($rise*24-int($rise*24))*60.,
112 int($set*24),($set*24-int($set*24))*60.);