pattern illegal java date simpledateformat

java - illegal - SimpleDateFormat no está analizando los milisegundos correctamente



java lang illegalargumentexception illegal pattern character t (4)

Fondo:

En mi tabla de base de datos, tengo dos marcas de tiempo

timeStamp1 = 2011-08-23 14:57:26.662 timeStamp2 = 2011-08-23 14:57:26.9

Cuando hago un "ORDER BY TIMESTAMP ASC", timeStamp2 se considera como la marca de tiempo mayor (que es correcta).

Requisito: Necesito obtener la diferencia de estas marcas de tiempo (timeStamp2 - timeStamp1)

Mi implementación:

public static String timeDifference(String now, String prev) { try { final Date currentParsed = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(now); final Date previousParsed = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(prev); long difference = currentParsed.getTime() - previousParsed.getTime(); return "" + difference; } catch (ParseException e) { return "Unknown"; } }

La respuesta debería haber sido 238ms, pero el valor que se devuelve es -653ms. No estoy seguro de lo que estoy haciendo mal. ¿Alguna sugerencia?


El formato que está analizando y los usos de formato no coinciden. Esperas un campo de tres dígitos y solo estás proporcionando un dígito. Toma 9 y asume que te refieres a 009 cuando lo que quieres es 900 . Los formatos de fecha son complicados y cuando prueba las fechas en un formato diferente, puede analizarlos de manera diferente a usted.

La documentación dice que S significa el número de milisegundos y el número en ese campo es 9, por lo que se está comportando correctamente.

EDIT: este ejemplo puede ayudar

final SimpleDateFormat ss_SSS = new SimpleDateFormat("ss.SSS"); ss_SSS.setTimeZone(TimeZone.getTimeZone("GMT")); for (String text : "0.9, 0.456, 0.123456".split(", ")) { System.out.println(text + " parsed as /"ss.SSS/" is " + ss_SSS.parse(text).getTime() + " millis"); }

huellas dactilares

0.9 parsed as "ss.SSS" is 9 millis 0.456 parsed as "ss.SSS" is 456 millis 0.123456 parsed as "ss.SSS" is 123456 millis


No estoy completamente seguro, pero el JavaDoc dice esto:

Para el análisis, el número de letras de patrón se ignora a menos que sea necesario para separar dos campos adyacentes.

Esto indica que los milisegundos de 2011-08-23 14:57:26.9 se analizarán como 9 lugar de 900 . Agregar los ceros al final podría funcionar: 2011-08-23 14:57:26.900 .


Tuve el mismo problema con la hora demasiado precisa de mis archivos de registro con milisegundos de 6 dígitos. Tiempo de análisis dio hasta 16 minutos de diferencia! WTF?

16-JAN-12 04.00.00.999999 PM GMT --> 16 Jan 2012 04:16:39 GMT

Cambiar el número de dígitos redujo la diferencia errónea y gracias a este hilo pude identificar el problema:

16-JAN-12 04.00.00.99999 PM GMT --> 16 Jan 2012 04:01:39 GMT 16-JAN-12 04.00.00.9999 PM GMT --> 16 Jan 2012 04:00:09 GMT 16-JAN-12 04.00.00.999 PM GMT --> 16 Jan 2012 04:00:00 GMT

Como SimpleDateFormat maneja internamente solo 3 dígitos, SimpleDateFormat lo innecesario con una expresión regular pequeña (ignorando los errores de redondeo, trabajando para 1 hasta n dígitos):

str = str.replaceAll("(//.[0-9]{3})[0-9]*( [AP]M)", "$1$2");

Gracias a @Peter Lawrey por su respuesta, me impidió volverme loco :-)


Yo sugeriría usar Joda-Time . Maneja estas situaciones adecuadamente. En el siguiente ejemplo, los milisegundos se analizan correctamente como 200 ms.

import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; public class ParseMillis { public static void main(String[] args) { String s = "00:00:01.2"; DateTimeFormatter format = DateTimeFormat.forPattern("HH:mm:ss.S"); DateTime dateTime = format.parseDateTime(s); System.out.println(dateTime.getMillisOfSecond()); } }