#!/usr/bin/perl # Name: sunrise.pl Author: Joe Smith 2-Feb-99 # Purpose: Returns time of sunrise and sunset for the Chez Inwap webcam sub MINUTES {60;} sub HOURS {(60 * MINUTES);} sub DAYS {(24 * HOURS);} $solstice_sunrise = (5*HOURS) + (49*MINUTES); # June 21st, daylight savings $solstice_sunset = (20*HOURS) + (33*MINUTES); # San Francisco, California $later_than_GMT = (8*HOURS); # Pacific time zone $standard_sunrise = $solstice_sunrise - (1*HOURS); # Undo daylight saving $standard_sunset = $solstice_sunset - (1*HOURS); $sundial_noon = ($standard_sunrise + $standard_sunset) / 2; # 12:11pm PST # The value of $offset the difference between sundial noon and legal noon. # San Francisco is about 11 minutes west of the middle of the Pacific zone. $offset = $later_than_GMT + $sundial_noon - (12*HOURS); # Sunrise on the summer solstice (June 21st) occurs about 82 minutes before # 6:00am sundial time. Likewise, sunset occurs that many minutes after # 6:00pm sundial time. The formulas below assume that the difference # varies sinusoidally throughout the year, with a zero difference at the # vernal equinox (March 21st). $early = $sundial_noon - (6*HOURS) - $standard_sunrise; sub suns { # Returns time of local sunrise and local sunset my ($time) = @_; # Uses $offset and $early $time -= $offset; # Do this to calculate right day my ($sec,$min,$hour,$yday) = (gmtime $time)[0,1,2,7]; # Local sundial time my $noon = $time - $sec - ($min*MINUTES) - ($hour*HOURS) + (12*HOURS); $noon += $offset; # Local time, excluding DST adjustment my $year_frac = ($yday - 31 - 28.24 - 21) / 365.24; # 0 = March 21st my $add = (6*HOURS) + $early * sin(2 * 3.141592653 * $year_frac); $add = int $add; ($noon-$add, $noon+$add); # Sunrise, sunset at this longitude } # The following blocks are not executed when this file is "require"d. # They can be invoked from the command line to test the logic. if (defined $test_day) { # Use "perl -s sunrise.pl -test_day" to run this test printf "sundial_noon = %02d:%02d\n",($sundial_noon/HOURS), ($sundial_noon - (HOURS)*int($sundial_noon/HOURS))/60; for ($i=-24; $i<28; $i+=1) { $date = $^T + ($i*HOURS); ($rise,$set) = suns($date); ($sec,$min,$hour) = localtime($date); $_ = sprintf "%02d:%02d:%02d ",$hour,$min,$sec; print $_ . localtime($rise) . " - " . localtime($set) . "\n"; } } if (defined $test_year) { # Use "perl -s sunrise.pl -test_year" to run this for ($i=-180; $i<189; $i+=10) { $date = $^T + $i*DAYS; ($rise,$set) = suns($date); $light = $rise - 20*MINUTES; # Gets light 20 minutes before sunrise $dark = $set + 20*MINUTES; # Gets dark 20 minutes after sunset print "\n" unless $i; print "$i\t" . localtime($light) . " - " . localtime($dark) . "\n"; print "\n" unless $i; } } 1;