use strict;
use warnings;
use Math::Trig;

my $day = 41;      # 10. Februar
my $zeitzone = 1;  # MEZ (Sommer: 2)
# Muenchen
my $breite = 48.1;
my $laenge = 11.6;

my ($a, $u) = Sonnenaufgang($breite, $laenge, $day);

print 'Aufgang:   ', Uhrzeit($a), "\n";
print 'Untergang: '. Uhrzeit($u), "\n";

sub Sonnenaufgang 
  { 
  # Berechnet Zeitpunkt des Sonnenauf- und untergangs fuer einen
  # bestimmten Tag des Jahres.
  # breite: geographische Breite in Grad
  # laenge: geographische Länge in Grad
  # day: Tag des Jahres.
  # returns (Aufgang, Untergang) als Timestamp
  # fuer den Referenzbreitengrad 15 Grad Ost (MEZ)
  my ($breite, $laenge, $day) = @_;


  $breite = $breite*pi/180.0;
  my $zeitgleichung = -0.171 * sin(0.0337 * $day + 0.465) 
                      - 0.1299 * sin(0.01787 * $day - 0.168);
  my $deklination = 0.4095 * sin(0.016906 * ($day - 80.086));

  # daemmerung, wenn sonne 50 bogenminuten unterhalb des horizonts 
  my $tmp = (sin(-0.0145) - sin($breite)*sin($deklination))
            / (cos($breite)*cos($deklination));
  my $zeitdifferenz = 12*acos($tmp)/pi;

  # Mittlere Ortszeit:
  my $aort = 12 - $zeitdifferenz - $zeitgleichung;
  my $uort = 12 + $zeitdifferenz - $zeitgleichung;

  # 15. Breitengrad fuer MEZ.
  my $auf   = $aort - $laenge/15 + $zeitzone;
  my $unter = $uort - $laenge/15 + $zeitzone;
  return ($auf, $unter);
  }

sub Uhrzeit
  {
  my $time = shift;
  my $stunde = int($time);
  my $minuten = ($time - int($time)) * 60;
  my $sekunden = int(($minuten - int($minuten)) * 60);
  $minuten = int($minuten);
  return sprintf("%2d:%02d:%02d", $stunde, $minuten, $sekunden);
  }