
NavList:
A Community Devoted to the Preservation and Practice of Celestial Navigation and Other Methods of Traditional Wayfinding
Long-Term Sun Almanac - Perl version
From: Dan Allen
Date: 2000 Dec 09, 11:51 AM
From: Dan Allen
Date: 2000 Dec 09, 11:51 AM
Here is a program that I wrote using Perl (www.perl.org, www.perl.com) that will calculate the position of the sun given a date, time, latitude, longitude, and timezone correction. If you are not a Perl programmer, don't try and understand it, as Perl has a terrible syntax. --- # s2k.pl - Sun 2000 from Meeus Astronomical Algorithms # s2k is Copyright Daniel K. Allen, 2000. # All rights reserved. # # 6 Dec 2000 - Created by Dan Allen. # # Usage: perl s2k.pl mm.ddyyyy hh:mm:ss # # all arguments and results are in decimal degrees $, = " "; $\ = "\n"; $PI = 4*atan2(1,1); $D2R = $PI/180; $R2D = 180/$PI; $lat = 47.4807666667; $lon = 121.797433333; $tz = 8; $t = J2000($ARGV[0],$ARGV[1] ? $ARGV[1] : 12); $l = Mod(280.46645 + 36000.76983*$t + 0.0003032*$t*$t,360); $m = Mod(357.5291 + 35999.0503*$t + -0.0001559*$t*$t + -0.00000048*$t*$t*$t,360); $e = (0.016708617 + -0.000042037*$t + -0.0000001236*$t*$t); $c = (1.9146 + -0.004817*$t + -0.000014*$t*$t) * Sin($m); $c += (0.019993 + -0.000101*$t) * Sin($m*2) + (0.00029) * Sin($m*3); $sunLong = $l + $c; $ecc = (84381.448 + -46.815*$t - 0.00059*$t*$t + 0.001813*$t*$t*$t) / 3600; $ra = Mod(ATan2(Cos($ecc)*Sin($sunLong),Cos($sunLong)),360); $dec = ASin(Sin($ecc)*Sin($sunLong)); $gst = (280.46061837 + 0.000387933*$t*$t + -2.58331180573E-8*$t*$t*$t); $gst += $t*36525*360.985647366; $gst = Mod($gst,360); $lha = $gst - $lon - $ra; $alt = ASin(Sin($lat) * Sin($dec) + Cos($lat) * Cos($dec) * Cos($lha)); $az = 180 + ATan(Sin($lha) / (Cos($lha) * Sin($lat) - Cos($lat)*Tan($dec))); $# = "%10.6f"; print " Lon:",$lon," Lat:",$lat; print " RA:",$ra, " Dec:",$dec; print " AZ:",$az, " Alt:",$alt; sub Floor { my $x = shift; return $x < 0 ? int($x) - 1 : int($x) } sub Mod { my ($x,$y) = @_; return $x - $y * Floor($x/$y) } sub Sin { my $x = shift; return sin($x*$D2R) } sub Cos { my $x = shift; return cos($x*$D2R) } sub Tan { my $x = shift; return Sin($x)/Cos($x) } sub ASin { my $x = shift; return atan2($x,sqrt(1 - $x * $x))*$R2D } sub ATan { my $x = shift; return atan2($x,1)*$R2D } sub ATan2 { my ($y,$x) = @_; return atan2($y,$x)*$R2D } sub J2000 { my ($date,$t) = @_; my ($m,$dy,$y,@a); if (index($date,"/") > 0) { # mm/dd/yy or mm/dd/yyyy - Y2K compatible @a = split /\//,$date; $m = $a[0]; $d = $a[1]; $y = $a[2] < 50 ? 2000 + $a[2] : $a[2] < 100 ? 1900 + $a[2] : $a[2]; @a = (); } else { # mm.ddyyyy - HP calculator compatible $m = int($date); $d = int(($date - $m)*100); $y = int(1000000*($date - int($date) - $d/100)+0.5); } @a = split /\:/,$t; print "Time:",$y,$m,$d,$a[0],$a[1],$a[2]," TZ:",$tz; return (Julian($y,$m,$d,$a[0]+$tz,$a[1],$a[2]) - Julian(2000,1,1,12,0,0))/36525; } sub Julian { my ($year,$month,$day,$hr,$min,$sec) = @_; my ($m,$y,$t,$jd); if ($month <= 2) { $y = $year - 1; $m = $month + 12; } else { $y = $year; $m = $month; } if ($year < 1582) { $t = -2; } elsif ($year == 1582 && ($month < 10 || $month == 10 && $day <= 4)) { $t = -2; } else { $t = int($y/400) - int($y/100); } $jd = int(365.25*$y) + int(30.6001*($m+1)) + $t + 1720996.5 + $day; $jd += $hr/24.0 + $min/(24.0*60) + $sec/(24.0*3600); return $jd; }