User input in Verbindung mit ChronoUnit anpassen und falls falsche Eingabe getätigtwird

triade

Aktives Mitglied
Hallo, ich habe einen Code geschrieben der einen den zeitlichen abstand zwischen zwei vom user eingegebenen abstände ausrechnet.
Habe mit den eingaben allerdings mit dem Input und zwar zum einen muss man jetzt immer erst das Jahr dann, Monat und dann das Datum und das alles einzeln kompakter und idiotensicherer wäre wenn man alles zsm eingeben könnte z.b YYYY.MM.DD. Und zu dem punkt idiotensicher auch wenn man aufgefodert wird erst die ältere Zeitangabe einzufügen und dann die neuere wäre es schön wenn der Code damit umgehen könnte, verscuht ahbe ich wenn eben der zeitabschnitt negativ ist was passiert wenn man erst die jüngere zeit eingibt der Code alle negativen werte mit -1 multiplizieren soll was diese positiv machen sollte, klappt aber nd. Ich hatte auch versucht was aber jetzt weg vom Code ist mit einer if Anweisung zu schauen welches Jahr kleiner ist und das eben danach gerechnet wird das Problem war allerdings wenn das Jahr gleich ist aber der Monat oder der Tag nicht passten. Weiß wer was man da machen kann?#

mein
Java:
import java.util.Scanner;
import java.time.temporal.ChronoUnit;
import java.time.LocalDate;

public class Zeitabstand
{
    public static void main(String[] args)
    {
        Scanner zeta = new Scanner(System.in);
       
        System.out.println("Hallo ich rechenn Ihnen den zeitlichen abstand zwichen zwei Zeiten aus. In Monaten, Wochen & Tagen. Geben sie dafür bitte erst den die ältere zeit das die kleinere und erst Jahr dan Monat dann den Tag!");
       
        int jahr, monat, tag, jahr2, monat2, tag2;

        jahr = zeta.nextInt();
        monat = zeta.nextInt();
        tag = zeta.nextInt();

        jahr2 = zeta.nextInt();
        monat2 = zeta.nextInt();
        tag2 = zeta.nextInt();

        LocalDate datum1 = LocalDate.of(jahr,monat,tag);
        LocalDate datum2 = LocalDate.of(jahr2,monat2,tag2);
           

     
            long monate = ChronoUnit.MONTHS.between(datum1, datum2);
            long wochen = ChronoUnit.WEEKS.between(datum1, datum2);
            long tage = ChronoUnit.DAYS.between(datum1, datum2);

            if(monate>0 || wochen>0 || tage>0 )
            {
                monate = monate *-1;
                wochen = wochen *-1;
                tage = tage *-1;
            }
                System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + monate + " Monate.");
                System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + wochen + " Wochen.");
                System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + tage + " Tage.");
         
           /*else
            {
                System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + monate + " Monate.");
                System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + wochen + " Wochen.");
                System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + tage + " Tage.");
            }
            */
           
        /*  der versuch mit dem JAhr:
        if (jahr < jahr2)
        {
            long monate = ChronoUnit.MONTHS.between(datum1, datum2);
            long wochen = ChronoUnit.WEEKS.between(datum1, datum2);
            long tage = ChronoUnit.DAYS.between(datum1, datum2);

           
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + monate + " Monate.");
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + wochen + " Wochen.");
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + tage + " Tage.");
        }
        else
        {
            long monate = ChronoUnit.MONTHS.between(datum2, datum1);
            long wochen = ChronoUnit.WEEKS.between(datum2, datum1);
            long tage = ChronoUnit.DAYS.between(datum2, datum1);

           
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + monate + " Monate.");
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + wochen + " Wochen.");
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + tage + " Tage.");
        */
     
        }
    }
}
Anmerkung zur Fragestellung diese ist unvollendet entschuldigen sie mich bitte falls dies zur Missverständnissen führt habe diese aber mittendrin ausersehen abgeschickt.
 
zu dem zweiten also der er drauf achtet welcher Zeitraum älter ist usw. klappt jetzt hatte die größer kleiner Zeichen einfach falsch. Hatte schon immer meine Unstimmigkeiten mit den :}
 
Du kannst mit dem Scanner eine Zeile einlesen und dann das Datum parsen.

Hier mal ein Beispiel mit einem DateTimeFormatter, der alles mögliche akzeptiert: 6.3.23, 6.03.23, 06.3.23, 06.03.23 und natürlich auch mit vierstelligen Jahreszahlen. Die Methode readDate ist aber noch ohne Fehlerbehandlung, wenn Du also Mist eingibst (z. B. eine leere Zeile), dann bricht das Programm mit einer Exception ab.

Java:
import java.time.LocalDate;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.Scanner;

class Test {
    private static final Scanner input = new Scanner(System.in);
    private static final DateTimeFormatter format = new DateTimeFormatterBuilder()
            .appendPattern("d.M.")
            .appendValueReduced(ChronoField.YEAR, 2, 4, Year.now().getValue() - 80)
            .toFormatter();

    public static void main(final String[] args) {
        final LocalDate firstDate = readDate("erste");       
        final LocalDate secondDate = readDate("zweite");
        final LocalDate from = min(firstDate, secondDate);
        final LocalDate until = max(firstDate, secondDate);
        final long months = ChronoUnit.MONTHS.between(from, until);
        final long weeks = ChronoUnit.WEEKS.between(from, until);
        final long days = ChronoUnit.DAYS.between(from, until);
        System.out.printf("Der Abstand zwischen den beiden Tagen beträgt %d Tage bzw. %d Wochen bzw. %d Monate.%n",
                days, weeks, months);
    }

    private static LocalDate min(final LocalDate first, final LocalDate second) {
        return first.isBefore(second) ? first : second;
    }

    private static LocalDate max(final LocalDate first, final LocalDate second) {
        return first.isBefore(second) ? second : first;
    }

    private static LocalDate readDate(final String which) {
        System.out.print("Bitte geben Sie das " + which + " Datum im Format tt.mm.jjjj ein: ");
        final String line = input.nextLine().trim();
        return LocalDate.parse(line, format);
    }
}
 
Du kannst mit dem Scanner eine Zeile einlesen und dann das Datum parsen.

Hier mal ein Beispiel mit einem DateTimeFormatter, der alles mögliche akzeptiert: 6.3.23, 6.03.23, 06.3.23, 06.03.23 und natürlich auch mit vierstelligen Jahreszahlen. Die Methode readDate ist aber noch ohne Fehlerbehandlung, wenn Du also Mist eingibst (z. B. eine leere Zeile), dann bricht das Programm mit einer Exception ab.
Hey, vielen Dank für die antwortnich muss aber sagen das dein Code da er Bestandteile beinhaltet die ich nicht kenne kompliziert wirkt, ich konnte meinen Code verbessern hier ist meine Lösung:
Java:
import java.util.Scanner;
import java.time.temporal.ChronoUnit;
import java.time.LocalDate;

public class Zeitabstand
{
    public static void main(String[] args)
    {
        Scanner zeta = new Scanner(System.in);
       
        System.out.println("Hallo ich rechenn Ihnen den zeitlichen abstand zwichen zwei Zeiten aus." + "\n" + "In Monaten, Wochen & Tagen." + "\n" + "Geben sie dafür bitte erst den die ältere zeit ein, folglich die neuere." + "\n" + "bitte im format JJJJ-MM-TT");
       
     
       
        int jahr, monat, tag, jahr2, monat2, tag2;

        String zeit1 = zeta.nextLine();

        String[] dteile = zeit1.split("-");
        jahr = Integer.parseInt(dteile[0]);
        monat = Integer.parseInt(dteile[1]);
        tag = Integer.parseInt(dteile[2]);

        String zeit2 = zeta.nextLine();

        String[] dteile2 = zeit2.split("-");
        jahr2 = Integer.parseInt(dteile2[0]);
        monat2 = Integer.parseInt(dteile2[1]);
        tag2 = Integer.parseInt(dteile2[2]);
           
       
        LocalDate datum1 = LocalDate.of(jahr,monat,tag);
        LocalDate datum2 = LocalDate.of(jahr2,monat2,tag2);
           

     
            long monate = ChronoUnit.MONTHS.between(datum1, datum2);
            long wochen = ChronoUnit.WEEKS.between(datum1, datum2);
            long tage = ChronoUnit.DAYS.between(datum1, datum2);

            if(monate<0 || wochen<0 || tage<0 )
            {
                monate = monate *-1;
                wochen = wochen *-1;
                tage = tage *-1;
            }

            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + monate + " Monate.");
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + wochen + " Wochen.");
            System.out.println("Der abstand zwichen den beiden Zeiten beträgt " + tage + " Tage.");
         
         
    }
   
}
 
muss aber sagen das dein Code da er Bestandteile beinhaltet die ich nicht kenne kompliziert wirkt
Das ist durchaus beabsichtigt, um zu vermeiden, dass Leute ihre Hausaufgaben einfach per Copy & Paste erledigen 🙂

Also, bleiben wir mal bei Deinem Code: klar, das kann man schon so machen. Ein kleiner Tipp: schau Dir mal Math.abs() an, damit kannst Du Dir den if-Block sparen, z. B.
Java:
long monate = Math.abs(ChronoUnit.MONTHS.between(datum1, datum2));

Der nächste Schritt bestünde in der Erkenntnis, dass da viel doppelter Code enthalten ist. Du liest zweimal eine Zeile ein, Du teilst zweimal eine Zeile in ihre Bestandteile auf, Du extrahierst Jahr, Monat und Tag - zweimal - und natürlich baust Du dann auch zweimal das Datum zusammen. Das wären dann so Dinge, die man in eine Methode auslagert, um den Code nur einmal schreiben/warten zu müssen.

Wenn Du die Zeile 32 mal hochziehst, hättest Du beispielsweise stehen:
Java:
        String[] dteile = zeit1.split("-");
        jahr = Integer.parseInt(dteile[0]);
        monat = Integer.parseInt(dteile[1]);
        tag = Integer.parseInt(dteile[2]);
        LocalDate datum1 = LocalDate.of(jahr,monat,tag);
Dieser Block wandelt also den String zeit1 in ein LocalDate datum1 um. Genau das gleiche machst Du mit zeit2... Der Block lässt sich aber einfach in eine Methode auslagern:
Java:
private static LocalDate ermittleDatum(String text) {
    String[] teile = text.split("-");
    int jahr = Integer.parseInt(teile[0]);
    int monat = Integer.parseInt(teile[1]);
    int tag = Integer.parseInt(teile[2]);
    return LocalDate.of(jahr, monat, tag);
}
Damit hast Du eine Methode (aka Funktion), die einen Text als Parameter erwartet und dafür dann ein LocalDate zurückgibt.

In main kann damit Zeile 15 komplett entfallen, und die Zeilen 19 bis 33 kannst Du ersetzen durch:
Java:
    String zeit1 = zeta.nextLine();
    LocalDate datum1 = ermittleDatum(zeit1);
    String zeit2 = zeta.nextLine();
    LocalDate datum2 = ermittleDatum(zeit2);

Das ist doch schon viel schöner. Da Du aber mit LocalDate arbeitest, kannst Du ach mit DateTimeFormatter arbeiten. Wenn Du ein ISO-Datum parsen möchtest, kannst Du auch auf vordefinierte DateTimeFormatter zurückgreifen:
Java:
LocalDate datum1 = LocalDate.parse(zeit1, DateTimeFormatter.ISO_LOCAL_DATE);
Damit bräuchtest Du die Methode ermittleDatum auch nicht mehr.
 
Hey, vielen Dank erstmal sehe deine Antwort zwar etwas spät, werde dennoch dies was ich an deinen verbesserungen verstehe(da ich nichts anwenden möchte was ich nicht verstehe) in meinen Code verbessern. Ich hätte allerdings eine frage undzwar weißt Du ob es eine Methode oder einen Befehl gibt der mit statt wie es nis jetzg isg alle Monate, Wochen oder Tage ausgerechnet werden mit die genaue zeit in Jahren, dann die restlicjen Monate, Wochen und Tahen ausgibt. Denn man kann zwar auch die Jahre so bestimmen lassen aber eben mir ist leider nixhts bekannt wo alles bestimmt wird. Der Gedanke das man dies Ermitteln könnte war da, allerdings das die Monate unregelmäßige Tage haben und es Schaltjahre gibt macht der Idee die Jahre mit 365 mal zu nehmen es abzuziehen usw… zu nichte.
 
Hast Du ein Beispiel für eine Eingabe und eine erwartete Ausgabe?

EDIT: Ach, kann es sein, dass Du ausgeben willst, dass es vom soundsovielten bis zum soundsovielten eben 2 Jahre, 3 Monate und 5 Tage sind?

Java:
public void zeigeJahreMonateTage(LocalDate von, LocalDate bis) {
    Period period = Period.between(von, bis);
    System.out.printf("%d Jahre, %d Monate und %d Tage", period.getYears(), period.getMonths(), period.getDays());
}
 
Zuletzt bearbeitet:
Hast Du ein Beispiel für eine Eingabe und eine erwartete Ausgabe?

EDIT: Ach, kann es sein, dass Du ausgeben willst, dass es vom soundsovielten bis zum soundsovielten eben 2 Jahre, 3 Monate und 5 Tage sind?

Java:
public
[/QUOTE]
[QUOTE="mihe7, post: 1349709, member: 58041"]
EDIT: Ach, kann es sein, dass Du ausgeben willst, dass es vom soundsovielten bis zum soundsovielten eben 2 Jahre, 3 Monate und 5 Tage sind?
[/QUOTE]
Hast Du ein Beispiel für eine Eingabe und eine erwartete Ausgabe?

EDIT: Ach, kann es sein, dass Du ausgeben willst, dass es vom soundsovielten bis zum soundsovielten eben 2 Jahre, 3 Monate und 5 Tage sind?

Java:
public void zeigeJahreMonateTage(LocalDate von, LocalDate bis) {
    Period period = Period.between(von, bis);
    System.out.printf("%d Jahre, %d Monate und %d Tage", period.getYears(), period.getMonths(), period.getDays());
}
Ja das wäre wie ich es noch ergänzen möchte vielen dank.🙏
 

Zurück
Oben