SimpleDateFormat is not parsing the milliseconds correctly

前端 未结 4 1995
臣服心动
臣服心动 2020-12-10 10:33

Background:

In my database table, I have two timestamps

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


        
相关标签:
4条回答
  • 2020-12-10 10:57

    The format you are parsing and the format uses doesn't match. You expect a three digit field and are only providing one digits. It takes 9 and assumes you mean 009 when what you want is 900. Date formats are complicated and when you prove dates in a different format it may parse them differently to you.

    The documentation says S means the number of milli-seconds and the number in that field is 9, so it is behaving correctly.


    EDIT: This example may help

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

    prints

    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
    
    0 讨论(0)
  • 2020-12-10 11:04

    I had the same problem with too accurate time from my logfiles with 6 digit milliseconds. Parsing Time gave up to 16 minutes difference! WTF?

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

    Changing the number of digits reduced the erroneous difference and thanks to this thread I could identify the problem:

    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
    

    As SimpleDateFormat internally handles only 3 digits I removed the unnecessary with a small regex (ignoring round-off errors, working for 1 up to n digits):

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

    Thanks to @Peter Lawrey for your answer, prevented me going insane :-)

    0 讨论(0)
  • 2020-12-10 11:10

    I'm not entirely sure, but the JavaDoc states this:

    For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.

    This indicates that the milliseconds from 2011-08-23 14:57:26.9 would be parsed as 9 instead of 900. Adding the trailing zeros might work: 2011-08-23 14:57:26.900.

    0 讨论(0)
  • 2020-12-10 11:12

    I'd suggest using Joda-Time. It handles these situations properly. In the following example, the milliseconds are correctly parsed as 200ms.

    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());
      }
    }
    
    0 讨论(0)
提交回复
热议问题