SimpleDateFormat无法正确解析毫秒数

背景:

在我的数据库表中,我有两个时间戳

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

当我执行“ORDER BY TIMESTAMP ASC”时,timeStamp2被认为是更大的时间戳(这是正确的)。

要求:我需要得到这些时间戳的差异(timeStamp2 – timeStamp1)

我的实施:

 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"; } } 

答案应该是238毫秒,但返回的值是-653毫秒。 我不确定我做错了什么。 有什么建议么?

我不完全确定,但JavaDoc说明了这一点:

对于解析,除非需要分隔两个相邻字段,否则将忽略模式字母的数量。

这表明从2011-08-23 14:57:26.9的毫秒数将被解析为9而不是900 。 添加尾随零可能有效: 2011-08-23 14:57:26.900

您正在解析的格式和格式使用的格式不匹配。 您期望三位数字段,并且只提供一位数字。 当你想要的是900时,它需要9并假设你的意思是009 。 日期格式很复杂,当您以不同的格式certificate日期时,它可能会以不同的方式对您进行解析。

文档说S表示毫秒数,该字段中的数字是9,因此它的行为正确。


编辑:这个例子可能会有所帮助

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

版画

 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 

我有相同的问题,我的日志文件太精确的时间与6位数毫秒。 解析时间差异达16分钟! WTF?

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

更改位数减少了错误的差异,由于这个线程,我可以确定问题:

 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 

由于SimpleDateFormat内部只处理3个数字,我使用一个小的正则表达式删除了不必要的数字(忽略舍入错误,工作1到n位数):

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

感谢@Peter Lawrey的回答,阻止我疯了:-)

我建议使用Joda-Time 。 它正确处理这些情况。 在以下示例中,毫秒被正确解析为200毫秒。

 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()); } }