Warum besteht dieser Test, während der Monatswert offensichtlich ungültig ist (13)?
%Vor% Bei Verwendung einer temporären Abfrage wird das erwartete DateTimeParseException
geworfen:
Was passiert, wenn keine TemporalQuery
angegeben ist?
BEARBEITEN: Der 13-Wert scheint ein spezieller Wert zu sein, wie ich dank der Antwort von ΦXocê 웃 Пepeúpa ツ gelernt habe (siehe Undecimber ).
Aber die Ausnahme wird nicht einmal mit einem anderen Wert wie 50 geworfen:
%Vor%Ich habe hier ein Debugging gemacht und festgestellt, dass ein Teil des Parsing-Vorgangs darin besteht, die Felder anhand der Chronologie des Formatierers zu überprüfen.
Wenn Sie ein DateTimeFormatter
erstellen, standardmäßig es verwendet ein IsoChronology
, das ist verwendet, um die Datumsfelder aufzulösen. Während dieser Auflösungsphase Die Methode java.time.chrono.AbstractChronology::resolveDate
wird aufgerufen.
Wenn Sie sich die Quelle , Sie sehen die folgende Logik:
%Vor% Da die Eingabe nur die Felder Jahr und Monat enthält, gibt fieldValues.containsKey(DAY_OF_MONTH)
false
zurück, die Methode gibt null
zurück und es wird keine andere Prüfung wie für Sie durchgeführt kann in Parsed
class .
Wenn also 201750
oder 201713
ohne TemporalQuery
analysiert wird, wird aufgrund der obigen Logik keine zusätzliche Überprüfung durchgeführt, und die Methode parse
gibt ein java.time.format.Parsed
-Objekt zurück, wie Sie am folgender Code:
Die Ausgabe ist:
class java.time.format.Parsed
{Jahr = 2017, MonthOfYear = 50}, ISO
Beachten Sie, dass der Typ des zurückgegebenen Objekts java.time.format.Parsed
ist und das Drucken die Felder anzeigt, die analysiert wurden (Jahr und Monat).
Wenn Sie parse
mit einem TemporalQuery
aufrufen, wird das Objekt Parsed
jedoch an die Abfrage übergeben und ihre Felder werden validiert (natürlich hängt es von der Abfrage ab, aber die eingebauten APIs validieren immer ).
Im Falle von YearMonth::from
wird geprüft, ob das Jahr und der Monat gültig sind, indem die entsprechenden ChronoField
verwendet werden ( MONTH_OF_YEAR und YEAR ) und das Feld" Monat "akzeptiert nur Werte von 1 bis 12 .
Deshalb ruft nur der Aufruf von parse(value)
keine Ausnahme auf, sondern ruft mit TemporalQuery
auf.
Nur um die obige Logik zu überprüfen, wenn alle Datumsfelder (Jahr, Monat und Tag) vorhanden sind:
%Vor%Dies wirft:
Ausnahme im Thread "main" java.time.format.DateTimeParseException: Text '20175010' konnte nicht analysiert werden: Ungültiger Wert für MonthOfYear (gültige Werte 1 - 12): 50
Da alle Datumsfelder vorhanden sind, gibt fieldValues.containsKey(DAY_OF_MONTH)
true
zurück und prüft nun, ob es ein gültiges Datum ist (mit resolveYMD
Methode ).
Der Monat 13 heißt: Undecimber
Der gregorianische Kalender, den viele von uns verwenden, erlaubt nur 12 Monate, aber Java bietet Unterstützung für Kalender, die dreizehn Monate erlauben, also hängt es davon ab, von welchem Kalendersystem Sie sprechen
Der tatsächliche Höchstwert des Felds MONTH ist beispielsweise 12 in einigen Jahren und 13 in anderen Jahren im hebräischen -Kalender System. Also der Monat 13 ist gültig
Es ist ein wenig seltsam, dass eine Ausnahme nicht ausgelöst wird, wenn parse
ohne eine gegebene TemporalQuery
aufgerufen wird. Ein Teil der Dokumentation für das einzelne Argument parse
method:
Dies analysiert den gesamten Text, der ein temporäres Objekt erzeugt. In der Regel ist es sinnvoller, parse (CharSequence, TemporalQuery) zu verwenden. Das Ergebnis dieser Methode ist TemporalAccessor, das aufgelöst wurde und grundlegende Validierungsprüfungen anwendet, um ein gültiges Datum-Uhrzeit-Datum sicherzustellen.
Beachten Sie, dass es "normalerweise sinnvoller ist, parse (CharSequence, TemporalQuery) zu verwenden". In Ihren Beispielen gibt parse
ein java.time.format.Parsed
-Objekt zurück, das eigentlich nur für das Erstellen eines anderen TemporalAccessor
verwendet wird.
Beachten Sie, dass beim Versuch, YearMonth
aus dem zurückgegebenen Wert zu erstellen, eine Ausnahme ausgelöst wird:
wirft
%Vor% Dokumentation für Parsed
:
Ein Speicher von geparsten Daten.
Diese Klasse wird beim Parsen verwendet, um die Daten zu sammeln. Ein Teil des Analyseprozesses beinhaltet die Handhabung von optionalen Blöcken und mehrere Kopien der Daten werden erstellt, um das notwendige Zurückverfolgen zu unterstützen.
Sobald die Analyse abgeschlossen ist, kann diese Klasse als resultierender TemporalAccessor verwendet werden. In den meisten Fällen wird es nur angezeigt, sobald die Felder aufgelöst wurden.
Seit: 1.8
@implSpecThis-Klasse ist ein veränderbarer Kontext, der aus einem einzelnen Thread verwendet werden soll. Die Verwendung der Klasse ist Thread-sicher innerhalb der Standardanalyse, da eine neue Instanz dieser Klasse automatisch für jede Syntaxanalyse erstellt wird und die Analyse single-threaded ist
Tags und Links java-8 java-time datetime-parsing