Mondphasenberechnung für Programmierer


Auf meiner Internetseite www.schiefer-abc.deMeine Haupt-Homepage: Dies und das von A bis Z... habe ich eine Mondphasenanzeige in den Titel eingebaut. Daraufhin erhielt ich mehrere Anfragen, wie sich so etwas realisieren lässt. Hier möchte ich allen Interessierten ganz ausführlich zeigen, dass das eigentlich ganz einfach ist.

Allerdings werde ich etwas weiter ausholen und erst mal demonstrieren, wie die Mondphasen am Himmel überhaupt zustande kommen. Das ist wichtig, um den Programmablauf später zu verstehen.

Grundsätzlich entstehen die Mondphasen dadurch, dass sich der Mond um die Erde dreht und dabei aus unterschiedlichen Richtungen von der Sonne beleuchtet wird.


 Nachfolgend können Sie selbst ausprobieren, wie es funktioniert:

Angezeigte Konstellation: Vollmond (2. Viertel)

Fahren Sie im Bild mit dem Mauspfeil über die Mondbahn, dann sehen
Sie rechts die jeweilige Mondphase aus der Sicht von uns Erdlingen.

Das Sonnenlicht kommt von links, Größe und Abstand von Erde und Mond entsprechen natürlich nicht dem Maßstab.


Theoretisch wäre die Berechnung der aktuellen Mondphase ganz schnell erledigt, denn wie man am Beispiel oben erkennen kann, entspricht die Zeit von einem Vollmond zum nächsten genau einer Runde des Mondes um die Erde. Dazu benötigt der Mond 27,321 Tage. Wer das überprüfen möchte, muss lediglich beobachten, vor welchem Stern der Mond sich gerade befindet. Dann muss man nur noch die Zeit messen, bis der Mond diesen Stern erneut bedeckt. Astronomen bezeichnen dies als "siderischen Mondmonat".

Für unser Programm müssten wir jetzt eigentlich nur diese rund 27 Tage zum Zeitpunkt des letzten in der Vergangenheit liegenden Vollmondes hinzurechnen und schon wüssten wir den Termin des nächsten Vollmondes.

Doch wenn man diesen Wert als Berechnungsgrundlage nimmt, erlebt man eine Überraschung! Bereits nach einem Mondumlauf würde die tatsächliche Mondphase unserem Programm um zwei Tage hinterherhinken, am Rechner wird uns der Vollmond rund zwei Tage zu früh angezeigt. Beim nächsten Umlauf wären es schon über vier Tage! Und so ginge es immer weiter.

Das liegt daran, dass sich die Erde während eines Mondumlaufs weiter um die Sonne gedreht hat, dadurch scheint die Sonne von uns aus gesehen aus einem etwas anderen Winkel auf den Mond. Wir benötigen je Umlauf rund zwei zusätzliche Tage, bis tatsächlich wieder Vollmond ist.

Die durchschnittliche Dauer von einem Vollmond zum nächsten entspricht exakt 29,530589 Tagen, was Astronomen als "synodischen Mondmonat" bezeichnen. Und genau diesen Wert benötigen wir für unser Programm.


 Das folgende Bild verdeutlicht das Problem:

  1. Ausgangspunkt: Vollmond (Mond von der Erde aus gesehen gegenüber der Sonne, "Opposition")
  2. Siderischer Mondmonat: Eine komplette Umrundung der Erde, jedoch noch kein Vollmond
  3. Synodischer Mondmonat: Rund zwei Tage zusätzlich, dann ist wieder Vollmond

Der oben angegebene Wert für den synodischen Mondmonat ist wirklich nur der Durchschnitt, da sich der Mond nicht kreisförmig um die Erde und die Erde nicht kreisförmig um die Sonne bewegt. Für unser Programm sollen die dadurch entstehenden Abweichungen aber mal unberücksichtigt bleiben.


 Weitere Veränderungen, die sich nur langfristig bemerkbar machen:

Durch die Drehbewegung der Erde wird der Mond auf seiner Umlaufbahn immer weiter beschleunigt, was zur Folge hat, dass er sich langsam aber sicher immer weiter von der Erde entfernt. Mittels Laserspiegeln, die damals von den Apollo-Astronauten auf dem Mond abgestellt wurden, konnte man eine Differenz von rund 3,8 cm pro Jahr feststellen. In Zukunft wird der Mond also immer mehr Zeit für einen Umlauf um die Erde benötigen.

Innerhalb unserer Lebensspanne kehren die Phasen in nahezu gleichbleibenden Abständen regelmäßig wieder. Erst in sehr viel längeren Zeiträumen werden sich Abweichungen bemerkbar machen. Für unser Programm müssen wir das nicht berücksichtigen, denn ich glaube nicht, dass es einen Homepage-Bastler gibt, der seine Seite ernsthaft für eine Lebensdauer von mehreren tausend Jahren plant.


Nun kommen wir zum Programm, das aus drei Teilen besteht:


 Teil 1: Die Mondphasenbilder

Da ich im Internet keine guten Mondphasenbilder für meine Programmierungen finden konnte, habe ich sie mir kurzerhand mit Hilfe des kostenlosen Astronomie-Programms CelestiaHomepage der deutschen Version
von Celestia
und etwas Photoshop-Nacharbeit selbst erstellt. Es handelt sich um insgesamt 100 Bilder in hoher Qualität, die den Ablauf einer kompletten Lunation (d.h. Phasenperiode) zeigen.

Folgende Einflüsse habe ich nicht berücksichtigt:
  1. Distanz: Durch die ellipsenförmige Umlaufbahn des Mondes um die Erde ist der Mond mal näher an der Erde und mal weiter entfernt, dadurch erscheint er unterschiedlich groß.
  2. Libration: Als Libration bezeichnet man das scheinbare "Torkeln" des Mondes, welches durch die unterschiedliche Entfernung während eines Erdumlaufs zustande kommt.
Rechts kann man die Auswirkung der Distanzänderung und der Libration erkennen. Dagegen ist der Mond in meinem Set auf allen Bildern gleich groß.

Lunare LibrationQuelle:
Wikimedia Commons

Bei der Durchnummerierung der Lunation beginnen Astronomen normalerweise mit dem Neumond. Ich habe hier anders angefangen, da wir eine andere Durchnummerierung für unser Programm benötigen. Neumond ist Bild Nummer 50 und Vollmond ist Bild Nummer 100. Zwischen den einzelnen Bildern liegen jeweils etwas über sieben Stunden.

Die Bilder im PNG-Format haben einen transparenten Hintergrund und können daher sehr gut in eigene Homepages oder Programme eingebunden werden.


Bildvorschau:

Set mit 100 Bildern als gepackte ZIP-Dateiphasenbilder.zip
Größe: 28.34 MB
©: Gerd Schiefer
Lizenz: Freeware
Stand: 02.05.2011
(x heruntergeladen).


Falls Sie die Bilder in einem kleineren Format benötigen, empfehle ich die Verwendung des kostenlosen Bildbetrachters Irfan ViewKostenloser Bildbetrachter Irfan View, mit dem auch Batchkonvertierungen vieler Bilder in einem Rutsch möglich sind.

Nach dem Download der Bilder erstellen Sie sich zunächst einen neuen Ordner, der zum Beispiel "Mondphasen" heißen kann. In diesen verschieben Sie den entpackten Ordner "phasenbilder".


 Teil 2: Die HTML-Datei

Erstellen Sie in Ihrem Ordner "Mondphasen" eine neue Textdatei. Der Name ist zunächst egal, die Datei wird später umbenannt. Windows-Benutzer sollten sich unbedingt die Dateiendungen anzeigen lassen, damit die Umbenennung funktioniert.

Jetzt markieren Sie den nachfolgenden Quellcode und kopieren ihn in die neue Textdatei:


<html>

<head>
  <title>Anzeige der aktuellen Mondphase</title>
  <script language="javascript" type="text/javascript" src="mond.js"></script>
</head>

<body bgcolor="#000000" onLoad="phasenberechnung();">
  <div style="color: #ffffff;" id="mondtext"></div>
  <img src="./phasenbilder/1.png" />
</body>

</html>

Diese Datei wird das Grundgerüst sein, das später das JavaScript-Programm startet und als Ergebnis das richtige Bild und den entsprechenden Text darstellt. Um den Quellcode auch für Anfänger so verständlich wie möglich zu gestalten, habe ich bis auf den schwarzen Hintergrund (das ist der hexadezimale Farbwert #000000) und die weiße Schrift (#ffffff) auf zusätzliche Formatierungen verzichtet.

Der SCRIPT-Befehl ruft eine Datei mit dem Namen "mond.js" auf. Die darin enthaltene Funktion "phasenberechnung()" wird vom BODY-Befehl aus gestartet, sowie das HTML-Dokument vom Browser komplett geladen wurde.

Vor dem Bildaufruf habe ich einen DIV-Container mit der ID "mondtext" platziert. Durch die ID kann ich später vom JavaScript-Programm aus einen Text an diesen Container senden.

Natürlich hätte ich die HTML- und die JavaScript-Datei schon fertigstellen und ebenfalls zum Download anbieten können. Aber ich möchte ja, dass Sie sich mit dem Code beschäftigen und ihn sich zumindest einmal genauer ansehen.

Nachdem Sie den Code in die Textdatei kopiert und die Änderung gespeichert haben, benennen Sie die Textdatei in "index.htm" um.


 Teil 3: Das JavaScript-Programm

Erstellen Sie in Ihrem Ordner "Mondphasen" eine weitere Textdatei und kopieren Sie den nachfolgenden Quellcode dort hinein.

Der Code erscheint zunächst gewaltig, besteht aber überwiegend aus erklärenden Kommentaren (das sind die Zeilen, die mit einem doppelten Schrägstrich beginnen).

Für die Fortgeschrittenen habe ich den Quellcode weiter unten noch einmal etwas optimiert und ohne Kommentare eingefügt. Welche Version Sie jetzt benutzen, das bleibt Ihnen freigestellt. Im Ergebnis gibt es keinen Unterschied.


// Mondphasenberechnung
// www.starpage.de

// Das HTML-Dokument ruft die nachfolgende Funktion mit dem Namen
// "phasenberechnung()" auf.

function phasenberechnung()
  {

  // Die benoetigten Variablen werden deklariert (d.h. angekuendigt
  // und damit der Speicher reserviert), weiterhin werden einigen der
  // Variablen Standardwerte zugewiesen.

  var jetzt, jahr, letzter_vollmond, differenz, anzahl_vollmonde;

  var bildpfad = "./phasenbilder/";
  var synodischer_mondmonat = 29.530588;
  var ausgabetext = "Falsche Systemzeit, Berechnung nicht aktiv!";
  var phase = 1;

  // Die aktuelle Systemzeit wird ausgelesen. Dazu wird ein
  // Zeitstempel mit dem Namen "jetzt" erzeugt, der die Anzahl
  // Millisekunden seit dem 01.01.1970 um 00:00 Uhr (Beginn der
  // UNIX-Zeitrechnung) bis zum jetzigen Zeitpunkt enthaelt.

  jetzt = new Date();

  // Aus diesem Zeitstempel wird die Jahreszahl extrahiert.

  jahr = jetzt.getYear();

  // Manche Browser (darunter bestimmte Netscape-Versionen) ermitteln
  // eine um 1900 Jahre zu geringe Jahreszahl. Um diesen Fehler zu
  // korrigieren, wird der Variablen "jahr" der Wert 1900
  // hinzuaddiert, falls der Wert zu klein ist.
  // Die Schreibweise "jahr = jahr + 1900;" koennte auch mit der
  // Schreibweise "jahr += 1900;" abgekuerzt werden.

  if(jahr < 1900)
    {
    jahr = jahr + 1900;
    }

  // Wir benoetigen fuer unsere Mondphasenberechnung einen in der
  // Vergangenheit liegenden Vollmondzeitpunkt. Ich habe mich fuer
  // das Datum des letzten Vollmondes aus dem Jahr 2009 entschieden.
  // Den Zeitpunkt kann man astronomischen Jahrbuechern oder
  // entsprechenden (serioesen!) Quellen aus dem Internet
  // entnehmen. Ich persoenlich bevorzuge das KOSMOS-Himmelsjahr,
  // um wichtige astronomische Daten herauszufinden.
  // Der nachfolgende Code wird nur dann ausgefuehrt, wenn der
  // Besucher eine Systemzeit ab dem Jahr 2010 eingestellt hat.
  // Jahreszahlen vor 2010 wuerden die Ausgabe des oben definierten
  // Standardtextes zur Folge haben.

  if(jahr >= 2010)
    {

    // Der Zeitpunkt des letzten Vollmondes aus 2009 war der
    // 31.12.2009 um 20:12:36 Uhr. Dies ist die Berechnungsgrundlage
    // fuer unser Programm. Dieser Zeitpunkt wird in einen
    // Zeitstempel mit dem Namen "letzter_vollmond" umgewandelt, der
    // ebenfalls die Anzahl Millisekunden seit dem 01.01.1970 um
    // 00:00 Uhr enthaelt. Bei der Datumsangabe ist zu beachten, dass
    // die Monatsangaben in JavaScript immer mit 0 beginnen
    // (0 = Januar bis 11 = Dezember).

    letzter_vollmond = new Date(2009, 11, 31, 20, 12, 36);

    // Im naechsten Schritt werden die beiden Zeitstempel in Tage
    // (mit Nachkommastellen) umgewandelt, damit wir diese Werte
    // spaeter mit dem synodischen Mondmonat verrechnen koennen, der
    // ja ebenfalls in Tagen angegeben ist.
    // Um aus dem Zeitstempel in Millisekunden einen Zeitstempel in
    // Tagen zu erhalten, teilen wir die Variablen nacheinander
    // - durch 1000 Millisekunden
    // - durch 60 Sekunden
    // - durch 60 Minuten
    // - durch 24 Stunden
    // Insgesamt teilen wir also durch den Wert 86400000.

    jetzt = jetzt / 86400000;
    letzter_vollmond = letzter_vollmond / 86400000;

    // Die Variable "differenz" berechnet die Anzahl Tage, die seit
    // dem als Berechnungsgrundlage angegebenen Vollmond vergangen
    // sind.

    differenz = jetzt - letzter_vollmond;

    // Die Anzahl der bisher vergangen Vollmonde wird errechnet,
    // indem diese Differenz (in Tagen) durch den synodischen
    // Mondmonat (ebenfalls in Tagen) geteilt wird.
    // Heraus kommt ein Wert, an dessen Nachkommastellen bereits die
    // aktuelle Mondphase erkannt werden kann.
    // Beispiel: Sind seit dem ersten angegebenen Vollmond exakt
    // 43,00 Vollmonde vergangen, muss jetzt wieder Vollmond sein.
    // Sind 43,50 Vollmonde vergangen, ist jetzt Neumond.
    // Der Wert vor dem Komma ist also vollkommen unerheblich.

    anzahl_vollmonde = differenz / synodischer_mondmonat;

    // Um aus den Nachkommastellen einen vernuenftigen Wert von 1
    // bis 100 zu erhalten, runden wir zunaechst einmal den Wert
    // fuer die Anzahl der vergangenen Vollmonde auf genau zwei
    // Nachkommastellen und weisen diesen Wert der neuen Variablen
    // "phase" zu.
    // Das Runden auf zwei Nachkommastellen geschieht in drei
    // Schritten:
    // - Wert mit 100 multiplizieren (Bsp.: aus 4,3742 wir 437,42)
    // - Wert wird ganzzahlig kaufmaennisch gerundet (aus 437,42
    //   wird 437)
    // - Wert wird durch 100 dividiert (aus 437 wird 4,37)

    phase = anzahl_vollmonde * 100;
    phase = Math.round(phase);
    phase = phase / 100;

    // Da die Zahl vor dem Komma unerheblich ist, muessen wir sie
    // entfernen. Das funktioniert, indem wir von dem Wert selbst
    // den ganzzahlig abgerundeten Wert abziehen.
    // Beispiel: 4,37 ist der Wert. Dann wird davon der selbe Wert
    // abgerundet (also 4) abgezogen. Uebrig bleibt 0,37.

    phase = phase - Math.floor(phase);

    // Wir erhalten als Ergebnis einen Wert von 0,00 bis 0,99. Wir
    // multiplizieren diesen Wert mit 100, um eine Ganzzahl von 0 bis
    // 99 zu erhalten. Dieser Wert sollte zur Sicherheit noch einmal
    // ganzzahlig abgerundet werden.

    phase = phase * 100;
    phase = Math.floor(phase);

    // Da wir bei den Bildern mit den Werten von 1 bis 100 arbeiten
    // (wobei 100 Vollmond ist), hier aber 0 bis 99 (0 ist Vollmond)
    // herauskommen kann, muessen wir im Falle der 0 eine 100 daraus
    // machen.

    if(phase == 0)
      {
      phase = 100;
      }

    // Abhaengig vom Phasenwert wird ein Text zugeordnet.

    if(phase < 25)
      {
      ausgabetext = "Abnehmender Mond";
      }
    if(phase == 25)
      {
      ausgabetext = "Halbmond (3. Viertel)";
      }
    if(phase > 25 && phase < 50)
      {
      ausgabetext = "Abnehmender Mond";
      }
    if(phase == 50)
      {
      ausgabetext = "Neumond (4. Viertel)";
      }
    if(phase > 50 && phase < 75)
      {
      ausgabetext = "Zunehmender Mond";
      }
    if(phase == 75)
      {
      ausgabetext = "Halbmond (1. Viertel)";
      }
    if(phase > 75 && phase < 100)
      {
      ausgabetext = "Zunehmender Mond";
      }
    if(phase == 100)
      {
      ausgabetext = "Vollmond (2. Viertel)";
      }

    }

  // Der Text aus der Variablen "ausgabetext" wird an den
  // DIV-Container mit der ID "mondtext" im HTML-Dokument gesendet.

  document.getElementById("mondtext").innerHTML = ausgabetext;

  // Da wir jetzt einen Wert von 1 bis 100 vorliegen haben (wobei
  // 100 einen Vollmond bedeutet), koennen wir jetzt die Bilder
  // zuordnen, die ja bereits richtig durchnummeriert sind.
  // Der Zahlenwert in den eckigen Klammern gibt den Index des Bildes
  // auf der Seite wieder, welches ausgetauscht werden soll. Es wird
  // immer nur das Vorkommen des IMG-Befehls im HTML-Dokument
  // gezaehlt, begonnen wird wie ueblich mit dem Wert 0 fuer das
  // erste Bild.

  window.document.images[0].src = bildpfad + phase + ".png";

  }

Haben Sie die Änderung gespeichert, benennen Sie die Textdatei in "mond.js" um.

Das war es auch schon!

Wenn Sie jetzt die Datei "index.htm" mit einem Doppelklick aufrufen, sollte Ihr Internetbrowser starten und Ihnen die aktuelle Mondphase anzeigen.


 Eine optimierte Version:

Und nun folgt - wie oben angekündigt - zum Vergleich ein etwas optimierter Quellcode ohne Kommentare. Daran kann man erkennen, dass das Programm wirklich nicht sehr umfangreich ist:


function phasenberechnung()
  {
  var jetzt, jahr, vm, diff, anz;
  var pfad = "./phasenbilder/";
  var syn = 29.530588;
  var text = "Falsche Systemzeit, Berechnung nicht aktiv!";
  var phase = 1;
  jetzt = new Date();
  jahr = jetzt.getYear();
  if(jahr < 1900) { jahr += 1900; }
  if(jahr >= 2010)
    {
    vm = new Date(2009, 11, 31, 20, 12, 36) / 86400000;
    jetzt = jetzt / 86400000;
    diff = jetzt - vm;
    anz = diff / syn;
    phase = Math.round(anz * 100) / 100;
    phase = Math.floor((phase - Math.floor(phase)) * 100);
    if(phase == 0)
      {
      phase = 100;
      text = "Vollmond (2. Viertel)";
      }
    else if(phase < 25 || (phase > 25 && phase < 50))
      { text = "Abnehmender Mond"; }
    else if(phase == 25) { text = "Halbmond (3. Viertel)"; }
    else if(phase == 50) { text = "Neumond (4. Viertel)"; }
    else if((phase > 50 && phase < 75) || (phase > 75 && phase < 100))
      { text = "Zunehmender Mond"; }
    else if(phase == 75) { text = "Halbmond (1. Viertel)"; }
    }
  document.getElementById("mondtext").innerHTML = text;
  window.document.images[0].src = pfad + phase + ".png";
  }

Haben Sie die Funktionsweise des Programms erst einmal verstanden, wird eine Anpassung für eigene Anwendungen sicherlich kein Problem mehr sein. Viel Spaß dabei!


 Zum Schluss noch eine Anmerkung:

Das gezeigte Beispiel funktioniert nur, sofern der Besucher der Homepage die JavaScript-Funktion in seinem Browser nicht deaktiviert hat. Es gibt übervorsichtige Internetnutzer, die JavaScript abschalten.

Daran sollte man denken und einen entsprechenden Alternativtext anbieten.

Darüberhinaus gibt es noch einen kleinen Nachteil: JavaScript ist eine clientseitige Programmiersprache. Das heißt, dass das Programm auf dem Rechner des Homepage-Besuchers ausgeführt wird. Und wenn dieser unbewusst oder absichtlich eine falsche Systemzeit eingestellt hat oder in einer anderen Zeitzone lebt, kommt das Programm zu einem falschen Ergebnis.

Man kann die Mondphasenberechnung auch in PHP schreiben, das ist eine serverseitige Programmiersprache. Die Syntax ist nahezu identisch, allerdings wird das Programm bei Aufruf der Seite auf dem Server der Homepage ausgeführt. Erst das Ergebnis der Berechnung wird dann an den Besucher geschickt. Dies hat den Vorteil, dass jedem Besucher auf der Welt eine identische Mondphase angezeigt wird, unabhängig von dessen lokal eingestellter Systemzeit. Nachteil ist, dass sich die Anzeige anders als mit JavaScript nicht ständig selbst aktualisiert. Dies geschieht erst bei erneutem Aufruf der Seite durch den Besucher.

Eine Alternative wäre die Kombination beider Sprachen. Mit PHP wird die Systemzeit des Servers abgegriffen und anschließend an den JavaScript-Code übergeben. Dieser sorgt dann ausgehend von der übernommenen Startzeit für eine fortlaufende Aktualisierung.

Aber so weit will ich hier nicht gehen. Das wäre mal etwas für ein eigenes Tutorial auf meiner anderen Homepage...

© 1996-2017 Gerd Schiefer