it-swarm.com.de

Wie konvertiere ich String in Date, ohne das Format zu kennen?

Ich habe ein Problem. Ich versuche, einige Zeichenfolgen in ein Datum umzuwandeln, und ich weiß nicht, in welchem ​​Format das Datum ankommt.

Es könnte als yyyy.mm.dd hh:mm:ss oder MM.dd.yy hh:mm:ss und so weiter kommen.

Wie kann ich diese Zeichenfolgen in Date konvertieren? Ich habe Folgendes versucht:

DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
Date d = (Date)formatter.parse(someDate);

Aber als ich someDate ausgedruckt habe, wurde es wie folgt ausgedruckt: 2010-08-05 12: 42: 48.638 CEST, was yyyy.mm.dd hh:mm:ss bedeutet. Wenn ich jedoch den obigen Code ausführte, wurde das Datumsobjekt jetzt Sat Jan 31 00:42:48 CET 11, was seltsam ist, um es gelinde auszudrücken.

Irgendwelche Ideen, wie ich Strings richtig formatieren kann?

37
Shervin Asgari

Du kannst nicht

Wenn Sie das Datum 2010-08-05 haben, kann es entweder der 5. August 2010 oder der 8. Mai 2010 sein - Sie müssen brauchen, um das Datumsformat zu kennen (oder zumindest ein Format vor dem Over zu priorisieren), um sie zu unterscheiden.

42
Justin

Ich stimme mit Kragen überein, dass es im Allgemeinen keine korrekte Lösung gibt. Wenn jedoch die folgenden Bedingungen zutreffen, können Sie die Lösung unten verwenden:

  1. Sie haben eine Reihe aller möglichen Formate

  2. Es gibt keine Mehrdeutigkeit zwischen den Formaten. Kein Datumsausdruck kann von zwei von ihnen erfolgreich analysiert werden.

Betrachten Sie die folgende Lösung, die eine Liste möglicher Formate durchläuft. Diese Lösung verwendet ThreadLocal , um die Datumsanalyse in einer Multithread-Umgebung effizient zu gestalten (denken Sie daran, dass SimpleDateFormat nicht threadsicher ist):

public class FlexibleDateParser {
    private List<ThreadLocal<SimpleDateFormat>> threadLocals = new  ArrayList<ThreadLocal<SimpleDateFormat>>();

    public FlexibleDateParser(List<String> formats, final TimeZone tz){
        threadLocals.clear();
        for (final String format : formats) {
            ThreadLocal<SimpleDateFormat> dateFormatTL = new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    SimpleDateFormat sdf = new SimpleDateFormat(format);
                    sdf.setTimeZone(tz); 
                    sdf.setLenient(false);
                    return sdf;
                }
            };
            threadLocals.add(dateFormatTL);
        }       
    }

    public Date parseDate(String dateStr) throws ParseException {
        for (ThreadLocal<SimpleDateFormat> tl : threadLocals) {
            SimpleDateFormat sdf = tl.get();
            try {
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                // Ignore and try next date parser
            }
        }
        // All parsers failed
        return null;
    }       
}
10
Eyal Schneider

Wie bereits erwähnt, müssen Sie mindestens eine geordnete Liste von Musterkandidaten haben. Sobald Sie das haben, hat Apache DateUtils eine parseDate(String dateString, String[] patterns)-Methode, mit der Sie ganz einfach eine Liste von Mustern in Ihrer Datumszeichenfolge ausprobieren und die erste nach der folgenden analysieren können:

public static Date parseDate(String str,
                         String[] parsePatterns)
                  throws ParseException

Analysiert eine Zeichenfolge, die ein Datum darstellt, indem verschiedene Parser verwendet werden.

Die Analyse wird nacheinander jedes Analyse-Muster testen. Eine Analyse gilt nur als erfolgreich, wenn sie die gesamte Eingabezeichenfolge analysiert. Wenn keine Analysemuster übereinstimmen, wird eine ParseException ausgelöst.

Der Parser wird dem geparsten Datum nachsichtig sein. 

7
oksayt

Hier ist eine schnelle und schmutzige Lösung, die auf amerikanischen Datumsformaten basiert.

public Date parseDate(String strDate) throws Exception
{
    if (strDate != null && !strDate.isEmpty())
    {
        SimpleDateFormat[] formats =
                new SimpleDateFormat[] {new SimpleDateFormat("MM-dd-yyyy"), new SimpleDateFormat("yyyyMMdd"),
                        new SimpleDateFormat("MM/dd/yyyy")};

        Date parsedDate = null;

        for (int i = 0; i < formats.length; i++)
        {
            try
            {
                parsedDate = formats[i].parse(strDate);
                return parsedDate;
            }
            catch (ParseException e)
            {
                continue;
            }
        }
    }
    throw new Exception("Unknown date format: '" + strDate + "'");
}
5
bjoern

Ihr Problem hängt mit der Internationalisierung zusammen. Wie Kragen antwortete, können Sie das Datum nicht in unbekanntem Format analysieren. Sie können zwar alle möglichen Schauplätze scannen und etwas analysieren, aber Sie würden nicht wissen, ob es richtig geparst wurde.

Nur ein kleiner i18n-Hintergrund: 

F: Können Sie mir sagen, auf welchen Tag, Monat und Jahr sich dieses Datum bezieht:

09/11/10?

A: Ohne das Gebietsschema zu kennen, können Sie nicht. Es könnte alles sein. 11. September in den USA. 9. November in Großbritannien. Und so weiter.

4
Paweł Dyda

Wenn es ein Protokoll ist; Definieren Sie das Format - vielleicht ISO, das jeden außer uns in Schweden irritieren wird ...

Wenn es Eingaben von Benutzern sind; Lassen Sie sie ihre Ländereinstellung festlegen. Wenn Sie dies tun können, zeigen Sie das geparste Datum im vollständigen Format an, damit der Benutzer es überprüfen kann (z. B. 10. November 2009). 

1
KarlP

Hier ist die einfache Lösung, die für mich funktioniert. Dies ist die einfache Methode, um das Datum zu analysieren, den String als Argument zu übergeben und in jedem gewünschten Format zu analysieren.

String dateToConvert(String date) {
        String strDate = "";
        try {
            //create SimpleDateFormat object with source string date format
            DateFormat sdfSource = new SimpleDateFormat("yyyy-MM-dd");

            //parse the string into Date object
            Date d = sdfSource.parse(date);
            LocalLog.e(LOG_TAG, d.toString());
            //create SimpleDateFormat object with desired date format
            SimpleDateFormat sdfDestination = new SimpleDateFormat(AppConstants.UNIVERSAL_DATE_FORMAT);

            //parse the date into another format
            strDate = sdfDestination.format(d);

            LocalLog.e(LOG_TAG, strDate);

        } catch (ParseException pe) {
            System.out.println("Parse Exception : " + pe);
        }
        return strDate;
    }
0

Meine einzige Vermutung ist, dass Sie zuerst einige Statistiken sammeln sollten, um das Format herauszufinden. 

Wenn Sie Glück haben, haben Sie ein Datum wie "2010/08/13", das eindeutig analysiert werden kann

0

Diese Antwort ist eine Kopie meiner Antwort auf eine andere Frage, die als Duplikat dieser Frage markiert ist

Ich hatte einmal die Aufgabe, einen Code zu schreiben, der eine Zeichenfolge bis zu einem Datum analysiert, bei dem das Datumsformat nicht im Voraus bekannt war. Das heißt Ich musste jedes gültige Datumsformat analysieren. Ich schrieb ein Projekt und danach schrieb ich einen Artikel, der die Idee hinter meiner Implementierung beschrieb. Hier ist der Link zum Artikel: Java 8 Java.time-Paket: Parsing eines beliebigen Strings bis heute . Generelle Idee ist es, alle Muster, die Sie unterstützen möchten, in eine externe Eigenschaftendatei zu schreiben und von dort aus zu lesen und zu versuchen, Ihren String nacheinander nach diesen Formaten zu analysieren, bis Sie Erfolg haben oder keine Formate mehr haben. Beachten Sie, dass die Reihenfolge ebenfalls wichtig ist, da einige Zeichenfolgen für verschiedene Formate gültig sein können (Unterschiede zwischen den USA und Europa). Vorteil ist, dass Sie der Datei weiterhin Formate hinzufügen/entfernen können, ohne Ihren Code zu ändern. So könnte ein solches Projekt auch für verschiedene Kunden angepasst werden

0
Michael Gantman