Java.time
Mal sehen, ob die java.time Rahmen kann helfen.
Über java.time
En java.time Framework, das in Java 8 integriert ist und die lästigen alten java.util.Date/.Calendar-Klassen ablöst. Die neuen Klassen sind inspiriert von dem sehr erfolgreichen Joda-Time das als Nachfolger gedacht ist, vom Konzept her ähnlich, aber mit einer neuen Architektur. Definiert durch JSR 310 . Erweitert um den DreiZehn-Extra Projekt. Siehe die Tutorial .
LocalDate
Anders als die alten Klassen bietet java.time die LocalDate
um einen reinen Datumswert ohne Tageszeit und Zeitzone darzustellen.
Französische Abkürzungen
Schauen Sie sich an, was die Formatierer in java.time für abgekürzte Monatsnamen in auf Französisch .
Wir können die Schleife Month
enum, um eine Liste der Monate zu erhalten. Diese Aufzählung bietet die getDisplayName
Methode zur Erzeugung eines lokalisierten Monatsnamens. Dieser Code zeigt, dass die Methode die gleiche Ausgabe wie der java.time formatter erzeugt.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yyyy" ).withLocale ( Locale.FRENCH );
for ( Month month : Month.values () ) {
LocalDate localDate = LocalDate.of ( 2015 , month.getValue () , 1 );
String output = formatter.format ( localDate );
String displayName = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );
System.out.println ( "output: " + output + " | displayName: " + displayName );// System.out.println ( "input: " + input + " " + localDate + " " + output );
}
output: 01-janv.-2015 | displayName: janv.
output: 01-févr.-2015 | displayName: févr.
output: 01-mars-2015 | displayName: mars
output: 01-avr.-2015 | displayName: avr.
output: 01-mai-2015 | displayName: mai
output: 01-juin-2015 | displayName: juin
output: 01-juil.-2015 | displayName: juil.
output: 01-août-2015 | displayName: août
output: 01-sept.-2015 | displayName: sept.
output: 01-oct.-2015 | displayName: oct.
output: 01-nov.-2015 | displayName: nov.
output: 01-déc.-2015 | displayName: déc.
Wir finden eine Mischung aus Schreibweisen mit 3 und 4 Buchstaben. Längere Namen werden auf vier Buchstaben plus einen Punkt abgekürzt ( FULL STOP ). Vier Monate haben so kurze Namen, dass sie ohne Abkürzung verwendet werden können: mars
, mai
, juin
, août
.
Wie bereits in den anderen Antworten erwähnt, gibt es also keine einfache Lösung.
Fixieren Sie die Datenquelle
Mein erster Vorschlag ist, Ihre Datenquelle zu reparieren. Diese Quelle hält sich offensichtlich nicht an die korrekten französischen Regeln für Abkürzungen. Yale stimmt mit dem Verständnis von Französisch in Java 8 überein. Übrigens, wenn Sie Ihre Datenquelle fixieren, empfehle ich dringend, vierstellige Jahreszahlen zu verwenden, da zwei zu unendlicher Verwirrung und Mehrdeutigkeit führen.
Fixieren der Eingabe
Natürlich kann die Quelle außerhalb Ihrer Kontrolle/Einflussnahme liegen. In diesem Fall, wie auch bei den anderen Antworten, müssen Sie vielleicht eher einen Brute-Force-Ersatz durchführen, als irgendetwas Gescheites zu versuchen. Wenn das einzige Problem bei Ihrer Eingabe darin besteht, dass einfach der Punkt (FULL STOP) fehlt, können Sie den Softcode mit der Month
enum zu verwenden, anstatt die unzulässigen Werte fest zu kodieren.
Ich würde einen ersten Parse-Versuch unternehmen. Trap für die DateTimeParseException
bevor Sie eine Reparatur versuchen. Wenn die Ausnahme ausgelöst wird, dann korrigieren Sie die Eingabe.
Um die Eingabe zu korrigieren, probieren Sie jeden Monat des Jahres aus, indem Sie eine Schleife durch die möglichen Enum-Instanzen ziehen. Ermitteln Sie für jeden Monat seinen abgekürzten Namen. Entfernen Sie den Punkt (FULL STOP) aus dieser Abkürzung, um den vermutlich falschen Eingangswert zu ermitteln. Testen Sie, ob dies tatsächlich eine Übereinstimmung mit der Eingabe ist. Wenn nicht, fahren Sie mit dem nächsten Monat fort.
Wenn wir einen Treffer erhalten, korrigieren Sie die Eingabe so, dass sie für die Regeln des Gebietsschemas (in unserem Fall Französisch) richtig abgekürzt ist. Dann wird die korrigierte Eingabe geparst. Dies wäre unser zweiter Parse-Versuch, da wir oben einen ersten Versuch unternommen haben. Wenn dieser zweite Versuch fehlschlägt, ist etwas sehr falsch, wie in der FIXME:
hier zu sehen. Aber normalerweise wird dieser zweite Parse-Versuch erfolgreich sein, und wir können aus dem for
Schleife des Month
enum.
Schließlich können Sie den Erfolg überprüfen, indem Sie testen, ob das Ergebnis immer noch der ursprünglich gesetzte falsche Flaggenwert ist ( LocalDate.MIN
).
String input = "09-oct-08"; // Last two digits are Year.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yy" ).withLocale ( Locale.FRENCH );
LocalDate localDate = LocalDate.MIN; // Some folks prefer a bogus default value as a success/failure flag rather than using a NULL.
try {
localDate = LocalDate.parse ( input , formatter );
} catch ( DateTimeParseException e ) {
// Look for any month name abbreviation improperly missing the period (FULL STOP).
for ( Month month : Month.values () ) {
String abbreviation = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );
String abbreviationWithoutFullStop = abbreviation.replace ( "." , "" ); // Get short abbreviation, but drop any period (FULL STOP).
String proper = "-" + abbreviation + "-";
String improper = "-" + abbreviationWithoutFullStop + "-";
if ( input.contains ( improper ) ) {
String inputFixed = input.replace ( improper , proper );
try {
localDate = LocalDate.parse ( inputFixed , formatter );
} catch ( DateTimeParseException e2 ) {
// FIXME: Handle this error. We expected this second parse attempt to succeed.
}
break; // Bail-out of the loop as we got a hit, matching input with a particular improper value.
}
}
}
Boolean success = ! ( localDate.equals ( LocalDate.MIN ) );
String formatted = formatter.format ( localDate );;
String outputImproper = formatted.replace ( "." , "" ); // Drop any period (FULL STOP).
Dump auf die Konsole.
System.out.println ( "success: " + success + ". input: " + input + " localDate: " + localDate + " formatted: " + formatted + " outputImproper: " + outputImproper );
Erfolg: true. input: 09-okt-08 localDate: 2008-10-09 formatiert: 09-okt.-08 outputImproper: 09-okt-08