Java: Problem bei der Berechnung einer Differenz zweier Datumsangaben

Guten Abend miteinander!

Als Neuling, sowohl im Bereich Programmieren als auch hier im Forum, möchte ich mich kurz vorstellen.

Mein Name ist Malte, ich studiere im zweiten Semester Wirtschaftsinformatik und betrete beim Schreiben von Programmen, insbesondere in Java, absolutes Neuland.

Ich bin mir nicht sicher, ob ich im richtigen Bereich gelandet bin, aber ich fange einfach mal an (kann ja eventuell von einem Mod. verschoben werden :) )

Die Aufgabe, die zu lösen ist, sieht wie folgt aus:

Abfrage des ersten Datums mit dem Format: DD.MM.YYYY

Abfrage des zweiten Datums mit dem Format: DD.MM.YYYY

Anschließende Berechnung der Differenz zwischen Datum 1 und Datum 2 in Tagen (!)

Beachtet werden sollen sowohl Schaltjahre als auch die Tage der einzelnen Monate (Sprich Januar 31, Februar 28, März 31 etc.)


Es sollen nur Daten zwischen dem 1. Januar 1901 und dem 31. Dezember 2099 überprüft werden.

Benutzt werden dürfen für diese Aufgabe ausschließlich Variable, Ausdrücke, Operatoren, If-Anweisungen, Ausgaben und Scanner.

Importieren darf ich allerdings nur Klassen für die Eingabe der Datumsangaben.

Ich habe im Internet einiges über den gregorianischen Kalender gelesen, weiß aber zum einen nicht, ob der Schaltjahre überhaupt beachtet, und zum anderen wie ich ihn einbinden kann.

Habe im Anhang mal meinen bisherigen Code angehängt. Der funktioniert soweit, dass er die zwei eingelesenen Daten verrechnet, allerdings feste Werte für Monat (31 Tage) und Jahr (365 Tage) verwendet. Ebenfalls habe ich noch keine Möglichkeit gefunden, die Werte immer positiv darzustellen. Die Differenz kann ja schlecht negativ sein..


Über jegliche Anregungen und Tipps wäre ich sehr dankbar!
 
Zuletzt bearbeitet:
Guten Abend miteinander!
Benutzt werden dürfen für diese Aufgabe ausschließlich Variable, Ausdrücke, Operatoren, If-Anweisungen, Ausgaben und Scanner.

Importieren darf ich allerdings nur Klassen für die Eingabe der Datumsangaben.

Ich habe im Internet einiges über den gregorianischen Kalender gelesen, weiß aber zum einen nicht, ob der Schaltjahre überhaupt beachtet, und zum anderen wie ich ihn einbinden kann.

Hi!
Was denn nun? Der gregorianische Kalender beachtet natürlich Schaltjahre, schließlich leben wir nach diesem. Wenn du die Java Klasse GregorianCalender meinst, dann tut sie das natürlich auch, aber nach deinen ersten Aussagen darfst du das gar nicht einbinden.

Dir bleibt dann nicht's anderes übrig als die Regeln für Schaltjahre anzugucken und zu schauen, ob im relevanten Bereich ein oder mehrere Schaltjahre vorliegen. Ansonsten würde ich einfach die Tage pro Monat fest hinterlegen und nur anhand der Berechnung des Schaltjahrs den Februar variieren.

Ebenfalls habe ich noch keine Möglichkeit gefunden, die Werte immer positiv darzustellen. Die Differenz kann ja schlecht negativ sein..

Ich lass sowas irgendwie ungern stehen :D. Differenzen können natürlich negativ sein. Du suchst aber auch einen Abstand, daher muss du von der Differenz den Absolutbetrag nehmen. Das geht in Java sehr einfach mit einer Funktion: Math.abs(int a);
Math (Java Platform SE 6)
 
Hey Tsjuder,

vielen Dank erst einmal für deine ausführliche Antwort! :)

Dass der gregorianische Kalender als solcher Schaltjahre beinhaltet war mir bewusst, blöd ausgedrückt von mir :P

Für die Schaltjahre kommt damit also nur boolean in Frage nehme ich an?

Das heißt dann wohl ich sollte es auf Grund der gegebenen Restriktionen was die Monatslängen betrifft mit einer if-Verkettung angehen..?

Werde mich dem wohl morgen mal intensiver annehmen, habe heute schon ein paar Stunden mein Java-Buch gewälzt um überhaupt so weit zu kommen wie ich jetzt bin (unser Dozent ist ein ziemlicher Lappen :D )

Also, danke dir noch einmal für das konstruktive Feedback und dir eine gute Nacht (es sei denn du fährst Nachtschicht :rolleyes: )
 
Ein heißer Tipp: Du musst, abhängig davon ob das jeweilige Jahr durch 4, 100, 400, ... teilbar ist einen Tag dazu addieren.

mfg benediktibk
 
Hallo benediktibk,

die Regeln zur Kontrolle einer einzelnen Jahreszahl kenne ich, das Problem ist nur, dass er dann nicht alle Jahre kontrolliert, die zwischen den beiden eingegeben Daten liegen. X(

Hat jemand vielleicht eine Ahnung, wie sich das realisieren lässt? :D

LG
 
Hallo benediktibk,

die Regeln zur Kontrolle einer einzelnen Jahreszahl kenne ich, das Problem ist nur, dass er dann nicht alle Jahre kontrolliert, die zwischen den beiden eingegeben Daten liegen. X(

Hat jemand vielleicht eine Ahnung, wie sich das realisieren lässt? :D

LG

Du läufst zum Beispiel von dem niedrigeren Jahr weg in Richtung zum oberen Jahr und überprüfst für jedes, ob es ein Schaltjahr ist oder nicht und addierst je nachdem einen Tag dazu. Aufpassen musst du nur bei dem Anfangs- und Endjahr, weil die vielleicht Schaltjahre sind, aber du trotzdem den Schalttag nicht dabei hast.
Das ist zwar sicher nicht die beste Lösung im Sinne von Performance, aber eine recht intuitive und in meinen Augen leicht verständliche.

mfg benediktibk
 
Ich habe jetzt einfach die Differenz zwischen beiden Jahren ermittelt, diese durch 4 geteilt und anschließend den erhaltenen Wert auf das Ergebnis addiert.
Wenn bei einem Schaltjahr ein Tag mehr vorliegt, so müsste ja die Anzahl der Schaltjahre mit der Anzahl der zusätzlichen Tage übereinstimmen (so zumindest die Logik in meinem Kopf..) Da sind jetzt Ausgangs- und Zieljahr noch nicht mit einbegriffen, aber für den Anfang dachte ich mir es sollte funktionieren.

Liefert allerdings falsche Ergebnisse :rolleyes:

Die Regel ob teilbar durch 100 ist für meine Aufgabe vernachlässigbar, da wir uns auf einen zu kurzen Zeitraum beschränken als dass der Fall eintreten könnte..

Vielleicht kann mir ja nochmal jemand zu Hilfe kommen, bin am Verzweifeln X(
 
Du kannst aus der Differenz nicht schließen ob ein Schaltjahr dazwischen war. Ein Beispiel: als Anfang 1999, als Ende 2001. Die Differenz wäre dann 2001 - 1999 = 2, welche nicht durch 4 teilbar ist. Trotzdem ist ein Schaltjahr, 2000, dazwischen. Mathematischer ausgedrückt: Aus c|(a-b) kannst du nicht schließen ob c|a oder c|b. Simpler Beweis durch ein Beispiel: 4|8 = 4|(10-2) aber es gilt nicht 4|10 oder 4|2.

mfg benediktibk
 
ich habe mir die aufgabe mal ein halbes stündchen angesehen und folgende lösung dafür ...

da es sich um eine Hausaufgabe zu handeln scheint, gibts keinen copypasta fertigen code... dafür aber eine lösung in c# (ist java ähnlich)

sprich wenn du das ganze nach java übersetzt, wirst du dich hoffentlich genug damit auseinandergesetzt haben...

ich habe keine ahnung wie strikt bei eich die auslegung dieser zeile ist:

Benutzt werden dürfen für diese Aufgabe ausschließlich Variable, Ausdrücke, Operatoren, If-Anweisungen, Ausgaben und Scanner.
falls das auch besagt dass ihr keine funktionen benutzen dürft, müsstest du die funktionen inlinen, sprich da wo der aufruf steht, muss quasi der code der funktion eingebaut werden ...

Code:
using System;

namespace KalenderSpass
{
    class Program
    {
        static void Main(string[] args)
        {
            long d1 = 0, d2 = 0;
            Console.WriteLine("Datumsformat: DD.MM.YYYY");
            d1 = eingabe("Datum 1?");
            d2 = eingabe("Datum 2?");

            Console.WriteLine("Anzahl der Tage zwischen Datum 1 und Datum 2: {0}", d2 - d1);
        }

        private static long eingabe(string EingabeAufforderung)
        {
            Console.WriteLine(EingabeAufforderung);
            return readDatumFromConsole();
        }

        private static int[] monatZuTagen = new int[] { 0, 31, 28, 31, 30, 31, 31, 30, 31, 30, 31, 30, 31 };
        private static long readDatumFromConsole()
        {
            int dd = 0, mm = 0, yyyy = 0, d = 0; //d wird mal die anzahl der tage seit dem 1.1.1901
            string tmp;
            string[] tmp2;
            int maxTage = 0;
            string allowedChars = ".0987654321";
            while (true) // wir bleiben in der schleife bis ein gültiges datum eingegeben wurde ... ausbruch durch break
            {
                tmp = Console.ReadLine(); // eingabe lesen
                for (int i = 0; i < tmp.Length; i++)
                {// durchsuche die eingabe nach ungültigen zeichen
                    if (!allowedChars.Contains(tmp[i].ToString())) 
                    {
                        Console.WriteLine("Ungültiges Zeichen gefunden.");
                        continue; // beginne schleife wieder von vorne ...
                    }
                }
                tmp2 = tmp.Split('.'); // splitte die eingabe an den punkten
                if (tmp2.Length != 3 // falls sich durch das splitten keine 3 teile ergeben...
                    || tmp2[0].Length != 2 // oder der erste teil nicht exakt 2 zeichen lang ist...
                    || tmp2[1].Length != 2 // oder der zweite teil nicht exakt 2 zeichen lang ist...
                    || tmp2[2].Length != 4) // oder der dritte teil nicht exakt 4 zeichen lang ist
                {
                    Console.WriteLine("Das Format ist falsch.");
                    continue;
                }
                dd = int.Parse(tmp2[0]); // umwandeln der eingabeteile teile in zeichen
                mm = int.Parse(tmp2[1]);
                yyyy = int.Parse(tmp2[2]);

                if (yyyy < 1901 && yyyy > 2099)
                {
                    Console.WriteLine("Jahreszahl ausserhalb des gültigen Bereichs.");
                    continue;
                }

                if (mm < 1 || mm > 12)
                {
                    Console.WriteLine("Monat ausserhalb des gültigen Bereichs.");
                    continue;
                }

                maxTage = monatZuTagen[mm]; // hole die anzahl der tage des monats aus einer lookup tabelle


                if (isSchaltjahr(yyyy) && mm == 2)
                    maxTage++; // falls schaltjahr und februar ... addiere einen tag

                if (dd < 1 || dd > maxTage)
                {
                    Console.WriteLine("Tag ausserhalb des gültigen Bereichs.");
                    continue;
                }


                break; // alle prüfungen sind ok, wir beenden die schleife
            }

            d = dd;// wir beginnen mit den tagen
            for (int i = 1; i < mm; i++)
            {//für jeden abgeschlossenen monat des jahres ...
                d += monatZuTagen[i];//... addiere die anzahl der tage aus der lookup tabelle
                if (isSchaltjahr(yyyy) && i == 2)
                    d++; // falls schaltjahr und februar ... inkrementiere um 1
            }
            for (int i = 1901; i < yyyy; i++)
            {// für jedes abgeschlossene jahr seit 1901...
                d += 365;//... addiere 365...
                if (isSchaltjahr(i))
                    d++; // falls schaltjahr, inkrementiere nochmals um 1
            }

            return d; // gebe zurück, die anzahl der tage seit dem 1.1.1901
            
        }

        private static bool isSchaltjahr(int yyyy)
        {//ist yyyy ein schaltjahr?
            return (yyyy % 4 == 0 && (yyyy % 100 != 0 || yyyy % 400 == 0));
            /*
             * ein jahr ist ein schaltjahr wenn es durch 4 teilbar ist,
             * ausser es ist durch 100 teilbar, ausgenommen wenn es 
             * gleichzeitig auch durch 400 teilbar ist
             */
        }
    }
}
 
Danke für die weiteren Antworten!

Habe mein ursprüngliches Konzept inzwischen komplett über den Haufen geworfen und jetzt eine Lösung mit Case-Break (weiss nicht ob man das so nennt :rolleyes:) geschrieben.

Die funktioniert, ist aber 10 mal so lang wie die vom Prof. geschriebene Musterlösung (er sagt er hat 12 Zeilen, ich habe ca. 120) :D

Soll seiner Aussage nach aber nicht zu Punktabzug führen, deshalb belasse ich es dabei..


Vielen Dank für die Hilfe und einen schönen Sonntag! 8) :thumb_up:
 
Die kurze Loesung berechnet wohl die Tage seit Jahr 0 von den jeweiligen Daten und bildet daraus dann den Abstand:

Code:
def date_to_days(y, m, d):
     if m <= 2:
         y -= 1
         m += 12
     return 365*y + y/4 - y/100 + y/400 + 3*(m + 1)/5 + 30*m + d
print abs(date_to_days(2012, 2, 3) - date_to_days(2013, 2, 3))
----
$ python dates.py
366
 
Zuletzt bearbeitet:
Zurück
Oben