webentwicklung-frage-antwort-db.com.de

Java 8 LocalDateTime analysiert ungültiges Datum

Ich wollte das Datum auf der Clientseite überprüfen, sodass ich den folgenden Code schrieb. Anstatt eine Ausnahme zu erhalten, erhalte ich ein Datumsobjekt für den 31. Februar, das eindeutig ein ungültiges Datum ist. 

public class Test {

    public static void main(String[] args) {
        String dateFormat = "HH:mm:ss MM/dd/yyyy";
        String dateString = "11:30:59 02/31/2015";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US);
        try {
            LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
            System.out.println(date);
        } catch (Exception e) {
            // Throw invalid date message
        }
    }
}

Ausgabe : 2015-02-28T11: 30: 59

Weiß jemand, warum LocalDateTime dieses Datum analysiert, anstatt eine Ausnahme auszulösen.

15
Zeeshan

Sie brauchen nur eine strikte ResolverStyle .

Das Parsen einer Textzeichenfolge erfolgt in zwei Phasen. Phase 1 ist eine grundlegende Textanalyse nach den zum Builder hinzugefügten Feldern. In Phase 2 werden die analysierten Feldwertpaare in Datums- und/oder Zeitobjekte aufgelöst. Dieser Stil wird verwendet, um zu steuern, wie sich das Auflösen in Phase 2 ereignet.

Beispielcode - wobei withResolverStyle(ResolverStyle.STRICT) die wichtige Änderung ist, zusammen mit der Verwendung von uuuu statt yyyy (wobei uuuu "year" ist und "yyyy" ist "year of era" und daher mehrdeutig):

import Java.time.*;
import Java.time.format.*;
import Java.util.*;

public class Test {

    public static void main(String[] args) {
        String dateFormat = "HH:mm:ss MM/dd/uuuu";
        String dateString = "11:30:59 02/31/2015";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
            .ofPattern(dateFormat, Locale.US)
            .withResolverStyle(ResolverStyle.STRICT);
        try {
            LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
            System.out.println(date);
        } catch (DateTimeParseException e) {
            // Throw invalid date message
            System.out.println("Exception was thrown");
        }
    }
}
27
Jon Skeet

DateTimeFormatter in Java 8 verwendet yyyy für YEAR_OF_ERA und uuuu für YEAR. Sie müssen Ihre Musterzeichenfolge wie folgt ändern:

String dateFormat = "HH:mm:ss MM/dd/uuuu";

Der DateTimeFormatter verwendet standardmäßig den Auflösungsstil SMART, Sie möchten jedoch den STRICT-Auflösungsstil verwenden. Ändern Sie Ihren dateTimeFormatter-Initialisierungscode wie folgt:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US)
                                                       .withResolverStyle(ResolverStyle.STRICT);
8
Palamino

Es wird nicht abgerundet. Der Februar hatte noch nie 31 Tage und es ist unmöglich, ein Datum und eine Uhrzeit für die Validierung eines Datums zu verwenden, um einen Tag zu repräsentieren, der nicht existiert.

Als Ergebnis nimmt es die ungültige Eingabe an und gibt Ihnen die beste Näherung an das korrekte Datum (das letzte Datum des Monats Februar dieses Jahres).

SimpleDateFormat erbt von DateFormat, die eine setLenient(boolean value)-Methode enthält. Ich würde erwarten, dass, wenn Sie setLenient(true) vor dem Parsen angerufen haben, es sich wahrscheinlich mehr beschweren würde, wie in den Javadocs beschrieben .

3
Edwin Buck
try {
    SimpleDateFormat df = new Java.text.SimpleDateFormat("HH:mm:ss MM/dd/yyyy");
    df.setLenient(false);
    System.out.println(df.parse("11:30:59 02/29/2015"));
} catch (Java.text.ParseException e) {
  System.out.println(e);
}

Ich habe eine Lösung gefunden, um das Datum als gültiges Datum mit DateFormat.setLenient (boolean) zu erkennen. Wenn Sie versuchen, ein ungültiges Datum zu analysieren, wird eine Analyse-Ausnahme ausgelöst.

Bearbeiten:

Java 8, dies führt jedoch zu einer Ausnahme, wenn ein Monat nicht zwischen 1 und 12 liegt und ein Tag mehr als 32 ist. Genau funktioniert nicht. Aber für Monat arbeitet es.

try {
TemporalAccessor ta = DateTimeFormatter.ofPattern("HH:mm:ss MM/dd/yyyy").parse("11:30:59 02/32/2015");
} catch (Exception e) {
System.out.println(e);
}

Ausgabe:

Java.time.format.DateTimeParseException: Text '11:30:59 02/32/2015' could not be
 parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
2
SatyaTNV

LocalDateTime.parse gibt nur dann einen Fehler aus, wenn der übergebene String ungültige Zeichen enthält, eine Anzahl von Tagen, die 31 übersteigt oder einen Monat, der 12 überschreitet.

Wenn Sie beispielsweise Ihren Code als solchen geändert haben:

String dateString = "11:30:59 0zz2/31/2015";

es wird eine Ausnahme ausgelöst, die durch ungültige Zeichen "zz" innerhalb des angegebenen Datums verursacht wurde. Warum wird das Datum sozusagen "abgerundet", weiß ich nicht.

Quelle: https://docs.Oracle.com/javase/8/docs/api/Java/time/LocalDateTime.html#parse-Java.lang.CharSequence-

0
jste89