So analysieren Sie Daten in mehreren Formaten mit SimpleDateFormat
Lesezeit: 7 Minuten
Derek
Ich versuche, einige Daten zu analysieren, die aus einem Dokument stammen. Es scheint, dass Benutzer diese Daten in einem ähnlichen, aber nicht genauen Format eingegeben haben.
hier sind die formate:
9/09
9/2009
09/2009
9/1/2009
9-1-2009
Was ist der beste Weg, um zu versuchen, all diese zu analysieren? Diese scheinen am häufigsten zu sein, aber ich denke, was mich aufhängt, ist, dass, wenn ich ein Muster von “M/yyyy” habe, das nicht immer vor “MM/yyyy” fängt. Muss ich meine try/catch-Blöcke einrichten verschachtelt in einer am wenigsten restriktiven bis am restriktivsten Weise? Es scheint, als würde es sicher eine Menge Code-Duplizierung erfordern, um dies richtig zu machen.
Nun, Sie könnten einfach eine Liste mit Mustern haben und dann eine einfache Schleife, um es weiter zu versuchen, bis Sie eines finden, das funktioniert.
– Spitze
26. Oktober 2010 um 14:14 Uhr
Und dann einfach die Schleife unterbrechen?
– Derek
26. Oktober 2010 um 14:16 Uhr
Mattball
Sie müssen eine andere verwenden SimpleDateFormat Objekt für jedes verschiedene Muster. Das heißt, Sie brauchen nicht so viele verschiedene, Danke dafür:
Anzahl: Für die Formatierung ist die Anzahl der Musterbuchstaben die Mindestanzahl von Ziffern, und kürzere Zahlen werden mit Nullen aufgefüllt. Beim Parsen wird die Anzahl der Musterbuchstaben ignoriert, es sei denn, sie wird benötigt, um zwei benachbarte Felder zu trennen.
Sie benötigen also diese Formate:
"M/y" (das deckt 9/09, 9/2009und 09/2009)
"M/d/y" (das deckt 9/1/2009)
"M-d-y" (das deckt 9-1-2009)
Mein Rat wäre also, eine Methode zu schreiben, die in etwa so funktioniert (ungetestet):
Viele der Antworten hier bieten eine Form davon als Lösung an, aber es wird leider nicht funktionieren. Wenn die zu analysierende Zeichenfolge mit Format Nr. 3 übereinstimmt, ist es sehr wahrscheinlich, dass SimpleDateFormat erfolgreich mit Format Nr. 1 analysiert wird, aber Sie haben das falsche Datum.
– Ben Bynum
31. Mai 2021 um 16:36 Uhr
Wie wäre es, wenn Sie einfach mehrere Muster definieren? Sie könnten aus einer Konfigurationsdatei stammen, die bekannte Muster enthält, fest codiert lautet sie wie folgt:
List<SimpleDateFormat> knownPatterns = new ArrayList<SimpleDateFormat>();
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm.ss'Z'"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss"));
knownPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
for (SimpleDateFormat pattern : knownPatterns) {
try {
// Take a try
return new Date(pattern.parse(candidate).getTime());
} catch (ParseException pe) {
// Loop on
}
}
System.err.println("No known Date format found: " + candidate);
return null;
Hey, ich versuche, mir all diese Muster anzusehen "yyyy-MM-dd'T'HH:mm:ss'Z'" können Sie mich bitte auf ein Beispiel oder Dokumente dieser Muster @xybrek hinweisen
– Totes Schwimmbad
18. Juli 2018 um 15:24 Uhr
Tolle Lösung. Tausend Dank fürs Teilen.!
– Ajay Kumar
5. Juli 2020 um 20:09 Uhr
ChrisR
Der obige Ansatz von Matt ist in Ordnung, aber bitte beachten Sie, dass Sie auf Probleme stoßen werden, wenn Sie ihn verwenden, um zwischen Datumsangaben des Formats zu unterscheiden y/M/d und d/M/y. Zum Beispiel ein Formatierer, der mit initialisiert wurde y/M/d akzeptiert ein Datum wie 01/01/2009 und Ihnen ein Datum zurückgeben, das eindeutig nicht das ist, was Sie wollten. Ich habe das Problem wie folgt behoben, aber ich habe nur begrenzt Zeit und bin mit der Lösung aus zwei Hauptgründen nicht zufrieden:
Es verstößt gegen eine der Richtlinien von Josh Bloch, nämlich „keine Ausnahmen verwenden, um den Programmfluss zu handhaben“.
Ich kann die sehen getDateFormat() -Methode zu einem Alptraum werden, wenn Sie viele andere Datumsformate verarbeiten müssen.
Wenn ich etwas machen müsste, das mit vielen, vielen verschiedenen Datumsformaten umgehen kann und hochleistungsfähig sein müsste, dann würde ich den Ansatz verwenden, eine Aufzählung zu erstellen, die jede unterschiedliche Datums-Regex mit ihrem Format verknüpft. Dann benutze MyEnum.values() um die Aufzählung zu durchlaufen und mit zu testen if(myEnum.getPattern().matches(date)) anstatt eine dateformatException abzufangen.
Abgesehen davon können die folgenden Daten mit den Formaten umgehen 'y/M/d' 'y-M-d' 'y M d' 'd/M/y' 'd-M-y' 'd M y' und alle anderen Variationen davon, die auch Zeitformate enthalten:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static final String[] timeFormats = {"HH:mm:ss","HH:mm"};
private static final String[] dateSeparators = {"https://stackoverflow.com/","-"," "};
private static final String DMY_FORMAT = "dd{sep}MM{sep}yyyy";
private static final String YMD_FORMAT = "yyyy{sep}MM{sep}dd";
private static final String ymd_template = "\\d{4}{sep}\\d{2}{sep}\\d{2}.*";
private static final String dmy_template = "\\d{2}{sep}\\d{2}{sep}\\d{4}.*";
public static Date stringToDate(String input){
Date date = null;
String dateFormat = getDateFormat(input);
if(dateFormat == null){
throw new IllegalArgumentException("Date is not in an accepted format " + input);
}
for(String sep : dateSeparators){
String actualDateFormat = patternForSeparator(dateFormat, sep);
//try first with the time
for(String time : timeFormats){
date = tryParse(input,actualDateFormat + " " + time);
if(date != null){
return date;
}
}
//didn't work, try without the time formats
date = tryParse(input,actualDateFormat);
if(date != null){
return date;
}
}
return date;
}
private static String getDateFormat(String date){
for(String sep : dateSeparators){
String ymdPattern = patternForSeparator(ymd_template, sep);
String dmyPattern = patternForSeparator(dmy_template, sep);
if(date.matches(ymdPattern)){
return YMD_FORMAT;
}
if(date.matches(dmyPattern)){
return DMY_FORMAT;
}
}
return null;
}
private static String patternForSeparator(String template, String sep){
return template.replace("{sep}", sep);
}
private static Date tryParse(String input, String pattern){
try{
return new SimpleDateFormat(pattern).parse(input);
}
catch (ParseException e) {}
return null;
}
}
Aaron G.
Wenn Sie in Java 1.8 arbeiten, können Sie den DateTimeFormatterBuilder nutzen
Siehe Beitrag: Java 8 Date entspricht Jodas DateTimeFormatterBuilder mit mehreren Parser-Formaten?
SANN3
In Apache-Commons-Sprache, DateUtils Klasse haben wir eine Methode namens parseDate. Wir können dies zum Analysieren des Datums verwenden.
Auch eine andere Bibliothek Joda-Time hat ebenfalls die Methode dazu analysieren das Datum.
Vinayak Dornala
Hier ist das vollständige Beispiel (mit Hauptmethode), das Ihrem Projekt als Hilfsklasse hinzugefügt werden kann. Alle genannten Formate in Einfaches Datumsformat API wird in der folgenden Methode unterstützt.
Diese Lösung überprüft alle möglichen Formate, bevor eine Ausnahme ausgelöst wird. Diese Lösung ist bequemer, wenn Sie versuchen, mehrere Datumsformate zu testen.
Date extractTimestampInput(String strDate){
final List<String> dateFormats = Arrays.asList("yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd");
for(String format: dateFormats){
SimpleDateFormat sdf = new SimpleDateFormat(format);
try{
return sdf.parse(strDate);
} catch (ParseException e) {
//intentionally empty
}
}
throw new IllegalArgumentException("Invalid input for date. Given '"+strDate+"', expecting format yyyy-MM-dd HH:mm:ss.SSS or yyyy-MM-dd.");
}
9146500cookie-checkSo analysieren Sie Daten in mehreren Formaten mit SimpleDateFormatyes
Nun, Sie könnten einfach eine Liste mit Mustern haben und dann eine einfache Schleife, um es weiter zu versuchen, bis Sie eines finden, das funktioniert.
– Spitze
26. Oktober 2010 um 14:14 Uhr
Und dann einfach die Schleife unterbrechen?
– Derek
26. Oktober 2010 um 14:16 Uhr