Teil von SELFHTML aktuell Teil von Artikel Teil von Programmiertechnik

Programmiertechnik:
Zeitberechnung

nach unten Autoren
nach unten Hinweise zum Thema
nach unten Beispiel und Erläuterungen
nach unten Weiterführende Links

Autoren

Antje Hofmann

E-Mail: E-Mail ah@pc-anfaenger.de
Homepage-URL: deutschsprachige Seite http://pc-anfaenger.de/

Sven Rautenberg

E-Mail: E-Mail sven@rtbg.de
Homepage-URL: deutschsprachige Seite http://www.rtbg.de/

Bei Fragen zu diesem Beitrag bitte die Autoren des Beitrags kontaktieren!

nach obennach unten

Hinweise zum Thema

Zeitberechnungen stellen sowohl für den Menschen als auch für den Computer ein Problem dar. Die Ursache liegt darin, dass Zeitangaben von dem uns gewohnten dezimalen Zahlensystem abweichen. Ein Tag besteht aus 24 Stunden, eine Stunde besteht aus 60 Minuten und eine Minute wiederum aus 60 Sekunden. Diese Darstellungsform der Zeit macht es uns gleichzeitig sehr schwer, größere Zahlenangaben wie z.B. 7835 Sekunden gefühlsmäßig zu erfassen und richtig einzuordnen.

Um mit Zeiträumen mathematisch zu rechnen, ist es sehr praktisch, einfach in Sekunden zu rechnen. Andererseits ist es unabdingbar, die Ergebnisse wieder in das gewohnte Format hh:mm:ss zurückzuwandeln, damit der Benutzer auf den ersten Blick die Information richtig einordnen kann.

Mathematische Grundlagen

Aus einer Tage-Stunden-Minuten-Sekunden-Angabe wie z.B. 2 Tage 04:12:16 die Sekunden auszurechnen ist simpel:

Sekundenzahl = Sekunden + 60 * Minuten + 60 * 60 * Stunden + 60 * 60 * 24 * Tage
Sekundenzahl = 16 sec   + 60 * 12 min  + 60 * 60 * 4 h     + 60 * 60 * 24 * 2 d  = 187936 sec

Wie aber erhält man aus 187.936 Sekunden wieder die eindeutig verständlichere Angabe? Die Marschrichtung ist dabei natürlich klar: Beim Weg hin zur Sekundenzahl wurde multipliziert, also wird auf dem Weg zurück dividiert.

Zum Lösen des Problemes gehen Sie am besten schrittweise vor. Beginnend von der kleinsten Einheit an, ermittelt Sie die Minuten, Stunden und Tage aus der vorhandenen Sekundenzahl.

Eine Minute dauert 60 Sekunden. Da liegt es nahe, die Anzahl der Sekunden durch 60 zu teilen.

Minutenzahl = Sekundenzahl / 60
Minutenzahl = 187936 sec / 60 = 3132,26666666666666666666666666667 min

Die Zahl vor dem Komma entspricht der Minutenzahl. Sie ist einfach zu gewinnen, indem man den Nachkommateil einfach abschneidet. Im Beispiel steht für das Abschneiden der Nachkommastellen jeweils der Ausdruck INT().

Für eine genaue Zeitangabe ist das jedoch nicht ausreichend. Auch die Nachkommastellen, welche die Restsekunden, darstellen müssen verarbeitet werden. Es liegt nahe, die Nachkommastellen mit 60 zu multiplizieren, um die Zahl der Sekunden zu ermitteln.

Sekunden = 0,26666666666666666666666666667 * 60
Sekunden = 16,0000000000000000000000000002 sec

Sie sind überrascht? Mit dieser doch scheinbar so einfachen Rechenoperation erhalten Sie kein richtiges Ergebnis. Exakt 16 Sekunden gingen in die Berechnung ein. Beim Rückwärtsrechnen erhielten Sie jedoch eine größere Zahl. Rechnet der Computer falsch?

Eigentlich nicht. Die Ursache liegt darin, dass das Ergebnis der Berechnung ein unendlicher Dezimalbruch ist. Mit solchen Zahlen kann ein Computer jedoch nicht rechnen. Deshalb werden die Ergebnisse gerundet. Dieser Rundungsfehler führt zur oben sichtbaren Abweichung.

Ist es überhaupt erforderlich, mit Nachkommastellen zu arbeiten? Die allermeisten Programmiersprachen kennen einen Operator names "MODULO", wahlweise abgekürzt als "x MOD y" oder "x % y". Das Ergebnis dieses Operators steht für den Rest bei der "Ganzzahl-Division mit Rest". Wer sich an seine Grundschulzeit erinnert, wird noch wissen, wie man Zahlen dividiert, ohne Nachkommastellen zu benutzen. Das Ergebnis des Modulo-Operators ergibt sich aus folgender stark vereinfachten Rechnung:

x MOD y = x - INT(x/y)* y
Beispiel:
23 MOD 5 = 23 - INT(23/5)*5 = 23 - 4 * 5 = 23 - 20 = 3

Der Modulo-Operator ist ideal zur Lösung des Problemes. Ohne Rundungsfehler erhalten Sie den ganzzahligen Rest der Division einer Zahl und in diesem Beispiel die Anzahl der Restsekunden. Zusammenfassend erhalten Sie:

Minuten  = INT(Sekundenzahl/60) = INT(187936/60) = 3132 min = Minutenzahl
Sekunden = Sekundenzahl MOD 60  = 187936 MOD 60  = 16 sec

Die Anzahl der Minuten ist für den Benutzer nicht sehr viel aufschlußreicher als die Sekundenzahl, da sie immer noch zu groß ist. Jetzt bietet es sich an, zu ermitteln, wieviele Stunden und Restminuten in der ermittelten Minutenzahl enthalten sind. Das Vorgehen ist genau das gleiche: Dividieren Sie die ermittelte Anzahl der Minuten durch die Anzahl der Minuten einer Stunde und schneiden Sie die Nachkommastellen ab. Ermitteln Sie die verbleibenden Restminuten mit Hilfe des Modulu-Operators.

Stunden = INT(Minutenzahl/60) = INT(3132/60)= 52 h   = Stundenzahl
Minuten = Minutenzahl MOD 60  = 3132 MOD 60 = 12 min

Es ist nicht erforderlich, die Minutenzahl wie im Beispiel in einer separaten Variable zu speichern. Stattdessen können Sie einfach die Rechenoperation angeben, welche zur Minutenzahl führte.

Minuten = Sekundenzahl/60 MOD 60  = 187936/60 MOD 60 = 12 min
Stunden = INT(Sekundenzahl/60/60) = INT(187936/60/60)= 52 h   = Stundenzahl

Diese wenigen Umformungssschritte bewirken, dass Sie die Sekundenzahl in der Form hh:mm:ss ausgeben können. Im Beispiel würde ein Benutzer als Ausgabe 52:12:16 erhalten. Auch diese Zeitangabe ist noch nicht ideal und würde vom Benutzer einen weiteren Verarbeitungsprozeß erfordern. Er müßte überlegen, wieviele Tage 52h sind. Diese Arbeit können Sie dem Benutzer abnehmen, indem Sie die ermittelte Stundenzahl in Tage umwandeln. Genau wie bei der Umwandlung in Minuten und Stunden verwenden Sie wieder die ganzzahlige Division und den Modulo-Operator. Gerechnet wird jetzt natürlich nicht mehr mit 60 Minuten pro Stunde, sondern mit 24 Stunden pro Tag.

Tage    = INT(Stundenzahl/24) = INT(52/24)= 2 Tage
Stunden = Stundenzahl MOD 24  = 52 MOD 24 = 4 h

Auch hier ist es nicht notwendig, mit dem Zwischenergebnis weiterzurechnen. Sie können stattdessen wiederum für die Stundenzahl die Rechnenoperation angeben, die zur Stundenzahl führte.

Tage    = INT(Sekundenzahl/60/60/24) = INT(187936/60/60/24)= 2 Tage
Stunden = (Sekundenzahl/60/60) MOD 24  = (187936/60/60) MOD 24 = 4 h

Diese letzte Umformung führte zu dem leicht verständlichen Ergebnis von 2 Tagen 4 Stunden 12 Minuten und 16 Sekunden. Diesen Wert kann jeder Anwender sofort interpretieren.

Sollten es Ihre Ergebnisse erfordern, so können Sie dieses Verfahren beliebig erweitern, um zum Beispiel die Anzahl der Wochen oder Jahre zu berechnen. Da es vollkommen unabhängig von vorhandenen Datumsfunktionen arbeitet, ist es nicht nur auf Zeitumwandlungen begrenzt. Sie können es auf jeden ähnlich gelagerten Anwendungsfall anwenden.

Fassen wir zusammen: Die einzelnen Teilwerte für Tage, Stunden, Minuten und Sekunden lassen sich immer mit demselben Schema von Division und Modulo berechnen. Die bei der Division anfallenden Nachkommastellen fallen grundsätzlich unter den Tisch, es kann also auch zu keinen Rundungsfehlern kommen.

Die Formeln noch einmal in der Übersicht:

Sekunden = Sekundenzahl MOD 60
Minuten  = (Sekundenzahl/60) MOD 60
Stunden  = (Sekundenzahl/60/60) MOD 24
Tage     = INT(Sekundenzahl/60/60/24)

nach obennach unten

Beispiel und Erläuterungen

Alle im folgenden Abschnitt betrachteten Programmiersprachen verwenden das Prozentzeichen als Modulo-Operator. Die Formatierung als Integer-Wert in Verbindung mit dem Modulo-Operator ist nicht in jedem Fall zwingend notwendig, wird jedoch der Vollständigkeit halber verwendet. Die Verwendung negativer Zahlen wurde durch die Bildung des absoluten Betrages der Sekundenzahl unterdrückt.

Beispiel für PHP:

function zeitformat($Sekundenzahl)
{
  $Sekundenzahl = abs($Sekundenzahl); // Ganzzahlwert bilden

  return sprintf("%d Tage %02d:%02d:%02d",
                $Sekundenzahl/60/60/24,($Sekundenzahl/60/60)%24,($Sekundenzahl/60)%60,$Sekundenzahl%60);
}
$einezeit = 187936;
echo zeitformat($einezeit);

Erläuterung:

Formatierte Ausgaben können in PHP mittels der Funktion sprintf() als String in Variablen gespeichert oder als Funktionswert übergeben werden (außerdem kann man mit der Funktion printf() direkt Daten ausgeben). Die Angabe %d formatiert den Wert des Argumentes als Integer-Wert. Die Angabe %02d formatiert den übergebenen Wert als Integer-Wert und falls erforderlich mit führender Null.

Beispiel für Perl:

my $Sekundenzahl = 187936;

sub zeitformat{
     my $Sekundenzahl = shift;
        $Sekundenzahl =  abs($Sekundenzahl);
     printf "%d Tage %02d:%02d:%02d",
            $Sekundenzahl/24/60/60,($Sekundenzahl/60/60)%24,($Sekundenzahl/60)%60,$Sekundenzahl%60;
}
zeitformat($Sekundenzahl);

Erläuterung:

Formatierte Ausgaben können in Perl mittels der Funktion printf() ausgegeben werden. Die Angabe %d formatiert den Wert des Argumentes als Integer-Wert. Die Angabe %02d formatiert den übergebenen Wert als Integer-Wert und falls erforderlich mit führender Null.

Beachten Sie:

Die Verwendung des Modulo-Operators in Verbindung mit negativen Zahlen führt hier zu überraschenden Ergebnissen. -51%50 ergibt nicht wie erwartet -1 sondern 49.

Beispiel für JavaScript:

function fuehrendeNull(wert)
{
  if (wert<10) return "0" + parseInt(wert);
  else return parseInt(wert);
}

function Sekundenumwandeln(Sekundenzahl)
{
 Sekundenzahl = Math.abs(Sekundenzahl)
 return parseInt(Sekundenzahl/60/60/24)+ " Tage " + fuehrendeNull((Sekundenzahl/60/60)%24) + ":" +
                 fuehrendeNull((Sekundenzahl/60)%60) + ":" + fuehrendeNull(Sekundenzahl%60);
}

document.write(Sekundenumwandeln(187936));

Erläuterung:

Da JavaScript keine speziellen Formatierungsfunktionen für Ausgaben kennt, wurde die Formatierung in die Funktion Sekundenumwandeln() ausgelagert. Der Rückgabewert der Funktion ist ein formatierter String, der im Beispiel mittels document.write() in das Dokument geschrieben wird. Der ganzzahlige Anteil einer Zahl wird mit der Methode parseInt() ermittelt. Die Funktion fuehrendeNull() erledigt 2 Aufgaben. Sie fügt gegebenenfalls eine führende Null an und gibt den ganzzahligen Wert des übergebenen Parameters zurück.

nach obennach unten

Weiterführende Links

Die folgenden Stellen werden empfohlen, um die obigen Beispiele besser zu verstehen, oder um weitere Möglichkeiten und Details zu erfahren.

bereichsübergreifende Seite SELFHTML: Berechnungsoperatoren in JavaScript
bereichsübergreifende Seite SELFHTML: Berechnungsoperatoren in Perl

Teil von SELFHTML aktuell Teil von Artikel Teil von Programmiertechnik

© 2007 bereichsübergreifende Seite Impressum