Differenz zwischen 2 Daten berechnen, ohne importiere Funktionen!

zooza

Mitglied
Hi, ich bin ganz neu in Java (an der UNi Programmieren Kurs belegt). Ich habe gar keine Erfahrungen im Programmieren und muss jetzt die ersten Programme für die Uni schreiben. Unser Dozent setzt leider sehr viel Wissen vorraus und erklärt schlecht.

Wir sollen einen Code schreiben, welcher 2 Daten einliest und die Differenz in Tagen ausgibt, dabei jedoch keine Funktionen (außer Scanner) importieren.

Mein Code sieht im Moment so aus:

Java:
import java.util.Scanner;
public class Tageberechnen {

    public static void main(String[] args) {
    
        int tag1, tag2, monat1, monat2, jahr1, jahr2, i, z, k;
    /**
         @param tag1, tag2, monat1, monat2, jahr1, jahr2  Speicher für eingegebene Daten.
         @param i dient später als Schleifenzähler, und als Index
         @param z in z werden die "gezählten" Tage aufsummiert, bzw. abgezogen.
         @param k wird benötigt um später mit einem unveränderten jahr2 weiterrechnen zu können,
                 da k in der while-Schleife verändert wird.
         @return   es wird die Anzahl der Tage zwischen Datum1 und Datum2 ausgegeben.
    **/
        int monate[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
        int monateschalt[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
/** 
   Es werden zwei weitere Variablen angelegt (integer arrays). Diese dienen später zur Berechnung
   der der vergangenen Tage zwischen den Monaten. 
**/
        Scanner scan = new Scanner(System.in);
    
        System.out.print("Geben Sie das erste Datum ein: ");
        tag1 = scan.nextInt(); //tag1 nimmt den Wert der 1. eingegebenen Zahl an
        monat1 = scan.nextInt(); //monat1 nimmt den Wert der 2. eingegebenen Zahl an
        jahr1 = scan.nextInt(); //jahr1 nimmt den Wert der 3. eingegebenen Zahl an
    
        System.out.print("Geben Sie das zweite Datum ein: ");
        tag2 = scan.nextInt(); //tag2 nimmt den Wert der 1. eingegebenen Zahl an
        monat2 = scan.nextInt(); //monat2 nimmt den Wert der 2. eingegebenen Zahl an
        jahr2 = scan.nextInt(); //jahr2 nimmt den Wert der 3. eingegebenen Zahl an
        k = jahr2; //der Wert von jahr2 wird in "k" zwischengespeichert, da wir diesen später noch benötigen
        z = 0; //z wird initialisiert
    
        i = jahr2 - jahr1; //i wird als Schleifenzähler benötigt und erhält den Wert der Differenz der Jahre
        while (i > 0) {                
            k = k % 4; //k % 4 überprüft, ob es sich um ein Schaltjahr handelt oder nicht.
         if (k !=0) {
                z += 365; //falls das betrachtete Jahr kein Schaltjahr ist.            
            } else { 
                z += 366; //falls das betrachtete Jahr ein Schaltjahr ist.
            }                                    
        i -= 1; //Schleifenzähler -1
        k -= 1; //das nächste Jahr soll betrachtet werden
        }
        
        i = monat2 - 1; //i wird als Index benötigt                                   
        if (jahr2 % 4 == 0) {
            z += monateschalt[i] + tag2;
/** 
    liest den Wert aus dem int-array (Schaltjahr) und addiert bereits vergangene Tage des Monats
**/
        } else {
            z += monate[i] + tag2; 
        }
/**     
    liest den Wert aus dem int-array (kein Schaltjahr) und addiert bereits vergangene Tage des Monats
**/                        
        i = monat1 - 1;
        if (jahr1 % 4 == 0 && jahr2 % 4 != 0) {
            z -= (monateschalt[i] + tag1 - 1);
 /** 
    liest den Wert aus dem int-array (Schaltjahr) und subtrahiert bereits vergangene Tage des Monats,
    zieht 1 weiteren Tag pauschal ab, da sonst (1. Jahr Schaltjahr, 2. kein Schaltjahr) in der while Schleife
    dieser Fall nicht betrachtet wird.
**/      

        } else if (jahr1 % 4 == 0 && jahr2 % 4 == 0) {
            z -= (monateschalt[i] + tag1);
        } else {
            z -= (monate[i] + tag1);
        }
/** 
    liest den Wert aus dem int-array (kein Schaltjahr) und subtrahiert bereits vergangene Tage des Monats
**/                               
        System.out.println("Tage: " +z); //gibt das Ergebnis aus.         
    }
}

Im Prinzip funktioniert der Code gut, jedoch passiert immer folgendes:

Wenn man als 1. Datum KEIN Schaltjahr eingibt und als 2 Datum ein Schaltjahr, dann rechnet der Code immer mit 1 Tag zu viel. Wo ist mein Denkfehler? Kann mir jemand helfen?

Liebe Grüße
Zooza
 
Es gibt da einen einfachen Trick um Probleme mit Schaltjahren zu vermeiden. Man setzt den Februar einfach ans Ende des Jahres.
Ich hab hier mal ein Beispiel

Java:
static int[] tageBisMonat = {0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337};

static int tage(int jahr, int monat, int tag) {
    if(monat < 3) {
        jahr -= 1; monat += 9;
    } else {
        monat -= 3;
    }
    return jahr * 365 + jahr/4 - jahr/100 + jahr/400 + tageBisMonat[monat] + tag;
}
Die Methode tage berechnet wie viele Tage seit dem 29. Februar im Jahre 1 v.Chr. vergangen sind.

Dann kannst du die Differenz zweier Tage so berechnen
Java:
int diff = tage(jahr2, monat2, tag2) - tage(jahr1, monat1, tag1);
 
Zuletzt bearbeitet:
hey DrZoidberg, kannst du deine Lösung nochmal genauer erläutern? Ich sitze an 'nem ähnlichen Programm und auch wenn deine Lösung funktioniert kann ich nicht genau nachvollziehen was du da machst.
 
Wenn der Monat zwischen 3 und 12 liegt, ziehe ich 3 ab, so dass März dann 0 ist und Dezember 9.
Bei Jan/Feb addiere ich 9, d.h. Januar ist dann 10 und Februar 11. Ausserdem wird das Jahr dann um eins verringert. Damit liegt der Februar nun am Ende des Jahres. Das macht das Rechnen mit Schaltjahren einfacher.
Das Array tageBisMonat speichert wie viele Tage vom 1. März bis zum 1. Tag des jeweiligen Monats vergehen. Also vom 1.3. bis 1.4. sind es 31 Tage. Bis zum 1.5. 61 Tage usw.
Der Ausdruck "jahr/4 - jahr/100 + jahr/400" berechnet wie viele Schalttage (wie viele 29. Februare) es bisher gab. Jedes 4.Jahr ist ein Schaltjahr, jedes 100. Jahr ist kein Schaltjahr (also z.B. 1800, 1900) und jedes 400. Jahr ist wieder ein Schaltjahr (z.B. 2000).
 
So ewtas änliches musste ich auch bereits Porgrammieren (mit dem Unterschied, dass dabei noch für jeden Tag ein bestimmter Wert mitgerechnet werden musste). Da habe ich das (etwa) so gelöst:

Java:
public class DayDiff
{
	private static final byte[] monthDays = new byte[]{
		31,  28,  31, 30, 31, 30,  31, 31, 30, 31,  30,  31
	};
	public static int getDifferenceInDays(short year1, byte month1, byte day1,
		short year2, byte month2, byte day2)
	{
		int days = 0;
		// ganze jahre
		for (int y = year1 + 1;y < year2 - 1;y++)
		{
			days += isLeapYear(y)? 366 : 365;
		}
		// im selben jahr?
		if (year1 == year2)
		{
			// differenz der monate rechnen und mit getDaysInMonth addieren
			// wenn nötig noch einzelne Tage dazuzählen
		}
		else
		{
			// tage vom start-datum bis zum ende des ersten jahres rechnen
			// tage vom 1.1. des end-jahres bis zum end-datum errechnen
			// beide auf days addieren
		}
		return days;
	}
	
	private boolean isLeapYear(int year)
	{
		// wenn das jahr ein vielfaches von 4 ist, aber nicht 100 (da jahr 100 kein Schaltjahr ist)
		// oder
		// das jahr ein vielfaches von 400 ist
		return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
	}
	private byte getDaysInMonth(short year, short month)
	{
		return month == 1 && isLeapYear(year)? 29 : monthDays[month];
	}
	// liefert die tage seit dem 1.1. des jahres
	private short getDaysUntil(short year, byte month, byte day)
	{
		short days = 0;
		for (byte i = 0;i < month;i++)
		{
			days += getDaysInMonth(year, i);
		}
		return days + day;
	}
}

Der Orginialcode in JavaScript: http://www.bfw-gohl.de/sites/default/files/js/gtz_rechner.js
 
Ah vielen Dank, ich habe noch eine kurze Frage in die Runde, die hier an den Programm anschließt, ich möchte überprüfen ob die Datums-Eingabe ein "/" beinhaltet. Warum geht folgender Code nicht?

Code:
Scanner scan = new Scanner(System.in);
	        
String eingabe1 = scan.toString();
	        
if (eingabe1.contains("/")) {
 System.out.print("/ gefunden");
}
 
Zuletzt bearbeitet:
Weil du das .toString() auf dem Scanner ausführst. [c]toString()[/c] kann auf jedem Objekt ausgeführt werden und liefert einen String, über den sich das Objekt eindeutig identifizieren (evtl. auch klassifizieren) lässt.

Die Methode, die du brauchst ist [JAPI]Scanner#nextLine()[/JAPI]
 
Zuletzt bearbeitet:
hm leider läuft das Programm jetzt nicht mehr durch, es stoppt in der if-Schleife ...
Code:
                System.out.print("Insert 1:");
	        Scanner scan = new Scanner(System.in);
	        String insert1 = scan.nextLine();
	        scan.useDelimiter("[\\s.\\-/]+"); 
	        
	        if (insert1.contains("/")) {  
	        	month1 = scan.nextInt();   
	        	day1 = scan.nextInt();      
	        	year1 = scan.nextInt();   
	       
	        } else {                 
	       	
	 	        day1 = scan.nextInt();    
	 	        month1 = scan.nextInt();  
	 	        year1 = scan.nextInt();   
	       }
	     
	        System.out.print("Insert 2:");
	  
	        
	        day2 = scan.nextInt();  
	        month2 = scan.nextInt();
	        year2 = scan.nextInt(); 
	        
	        scan.close();
 
Nachdem du scan.nextLine aufgerufen hast ist die Zeile schon abgearbeitet. scan.nextInt hat dann nichts mehr zum einlesen.

So könnte es gehen
[Java]
System.out.print("Insert 1:");
Scanner scan = new Scanner(System.in);
String line = scan.nextLine();
Scanner nums = new Scanner(line);
nums.useDelimiter("[\\s\\-/]");

if (line.contains("/")) {
month1 = nums.nextInt();
day1 = nums.nextInt();
year1 = nums.nextInt();

} else {
day1 = nums.nextInt();
month1 = nums.nextInt();
year1 = nums.nextInt();
}

System.out.print("Insert 2:");
line = scan.nextLine();
nums = new Scanner(line);
nums.useDelimiter("[\\s\\-/]");

day2 = nums.nextInt();
month2 = nums.nextInt();
year2 = nums.nextInt();
[/Java]
 

Zurück
Oben