¿Cómo convertir String a Date sin conocer el formato?

Tengo un problema. Estoy intentando convertir algunas cadenas hasta la fecha, y no sé el formato en que está llegando la fecha.

Puede venir como yyyy.mm.dd hh:mm:ss o MM.dd.yy hh:mm:ss y así sucesivamente.

¿Cómo puedo convertir estas cadenas en Fecha? Intenté esto:

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

Pero cuando imprimí algún día, se imprimió así: 2010-08-05 12: 42: 48.638 CEST, que significa yyyy.mm.dd hh:mm:ss , sin embargo, cuando ejecuté el código anterior, el objeto de fecha ahora se convirtió en Sat Jan 31 00:42:48 CET 11 que es extraño, por decir lo menos.

¿Alguna idea de cómo puedo formatear correctamente las cadenas hasta la fecha?

¡No puedes!

Si tiene la fecha 2010-08-05 , puede ser el 5 de agosto de 2010 o el 8 de mayo de 2010; necesita saber el formato de fecha (o al menos priorizar un formato al final) para diferenciarlos.

Estoy de acuerdo con Kragen en que, en el caso general, no hay una solución correcta. Sin embargo, si se cumplen las siguientes condiciones, puede usar la solución a continuación:

  1. Tienes un conjunto de todos los formatos posibles

  2. No hay ambigüedad entre los formatos; ninguna expresión de fecha puede ser analizada con éxito por dos de ellos.

Considere la siguiente solución que itera sobre una lista de formatos posibles. Esta solución hace uso de ThreadLocal , para que el análisis de fecha sea eficiente en un entorno de subprocesos múltiples (recuerde que SimpleDateFormat no es seguro para subprocesos):

 public class FlexibleDateParser { private List> threadLocals = new ArrayList>(); public FlexibleDateParser(List formats, final TimeZone tz){ threadLocals.clear(); for (final String format : formats) { ThreadLocal dateFormatTL = new ThreadLocal() { 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 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; } } 

Como se señaló anteriormente, debe tener al menos una lista ordenada de candidatos de patrones. Una vez que tenga eso, Apache DateUtils tiene un parseDate(String dateString, String[] patterns) que le permite probar fácilmente una lista de patrones en su cadena de fecha y analizarla con la primera que coincida:

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

Analiza una cadena que representa una fecha probando una variedad de analizadores diferentes.

El análisis analizará cada patrón de análisis a su vez. Un análisis solo se considera exitoso si analiza la totalidad de la cadena de entrada. Si no coinciden los patrones de análisis, se lanza una excepción ParseException.

El analizador será indulgente con la fecha analizada.

Aquí hay una solución rápida y sucia basada en formatos de fecha americanos.

 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 + "'"); } 

Tu problema está relacionado con la internacionalización. Como respondió Kragen, no puedes simplemente analizar la fecha en un formato desconocido. Aunque puede escanear todas las configuraciones regionales posibles y analizar algo , pero no sabría si se analizó correctamente.

Solo un pequeño fondo de i18n:

P: ¿Puede decirme a qué día mes y año se refiere esta fecha?

11/09/10?

R: Sin conocer la configuración regional, no puedes. Podría ser cualquier cosa. 11 de septiembre en Estados Unidos. 9 de noviembre en Gran Bretaña. Y así.

Si es un protocolo; define el formato, tal vez ISO, que irritará a todos menos a nosotros en Suecia …

Si ingresa desde usuarios; Permítales configurar su configuración regional. Si puede hacerlo, muestre la fecha analizada en formato completo para que el usuario pueda verificarla, como el 10 de noviembre de 2009.

Mi única conjetura es que primero debes reunir algunas estadísticas para descubrir el formato.

Si tiene suerte, tendrá una fecha como “2010/08/13” que se puede analizar sin ambigüedades

Aquí está la solución simple, que me funciona. Este es el método simple para analizar la fecha, pasar el String como argumento y analizarlo en cualquier formato que desee.

 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; } 
 public String compareDate( PaymentTxnRequest request ) throws ParseException { Date debitDate= request.getPaymentTxn().getCrValDt(); Date now = new Date(); String response=""; SimpleDateFormat sdfDate = new SimpleDateFormat("dd/MM/yyyy"); String strCurrDate = sdfDate.format(now); String strDebitDate = sdfDate.format(debitDate); System.out.println("Current Date: " + strCurrDate); Date currentDate = new SimpleDateFormat("dd/MM/yyyy").parse(strCurrDate); Date txnDate = new SimpleDateFormat("dd/MM/yyyy").parse(strDebitDate); System.out.println("C -> "+currentDate); System.out.println("C -> "+txnDate); if (txnDate!=null){ if (currentDate.equals(txnDate)) { System.out.println("Valid Txn"); response="valid"; } if (currentDate.after(txnDate)) { System.out.println("--> Not Valid TXN Past"); response="notValid"; } if (currentDateenter code here.before(txnDate)){ System.out.println("Future Valid TXn"); response="future"; } } return response; }