4

I have noticed a discrepancy in Android's SimpleDateFormat for reading milliseconds for my formatter between Android 4.x and 5.0.

String dateString = "2012-10-01 00:00:00.000087";      
// ORMLite date format as seen at https://github.com/j256/ormlite-core/blob/master/src/main/java/com/j256/ormlite/field/types/BaseDateType.java
SimpleDateFormat formatForDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
try{
    Date parsedDate = formatForDate.parse(dateString);
    // Android 5.0 parsedDate.getTime() ends in 000
    // Android 4.x parsedDate.getTime() ends in 087 as expected
}
catch (ParseException e) {
    e.printStackTrace();
}

As explained in the comments, when running above code on android 4.x I get different results than when I do on Android 5.0. It seems to discard the MS field for Android 5.

(When I change the format to end in .SSS and change the value to drop extra zeros to be just 087 the date gets parsed correctly on Android 5.0. This isn't a great workaround as all my database fields are saved in the SSSSSS format, as is ORMLite's default.)

I can't seem to find changes that Google has made in SimpleDateFormat code. What would cause a problem lilke this? Where might I look for a fix?

Diederik
  • 5,536
  • 3
  • 44
  • 60
  • I just parsed `.463000` with `SSS` pattern, and the MS value becomes 463. – Diederik Apr 10 '15 at 12:54
  • but 463000 is greater than 1000. try `"yyyy-MM-dd HH:mm:ss.000SSS"` – Olayinka Apr 10 '15 at 13:13
  • Yes, making the pattern `000SSS` does parse milliseconds correctly, but as stated in the question changing the date format isn't really a fix for the problem (as I have persisted data that is read with `SSSSSS` format). I want the Android 4.x behaviour back. – Diederik Apr 10 '15 at 13:20
  • `.000087` is microseconds, not milliseconds – StenSoft Apr 10 '15 at 14:40

2 Answers2

2

According to Java 1.5 or newer, you would be correct:

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

However, according to Android documentation, S is right-padded and the length for parsing is not ignored, “SSSSSS” therefore means microseconds (or milliseconds with three digits ignored on the right) and Android 5.0 implementation is the correct one.

Edit: the limit and IllegalArgumentException does not apply to S

StenSoft
  • 9,369
  • 25
  • 30
  • 2
    AFAIK Android 5 doesn't support Java 8, only compatible with 7. – Raanan Apr 10 '15 at 14:46
  • I just checked that the behavior is the same from Java 1.5 – StenSoft Apr 10 '15 at 14:48
  • Well, it's only "compatible" with: http://stackoverflow.com/questions/20480090/does-android-support-jdk-6-or-7 – Raanan Apr 10 '15 at 14:49
  • 1
    I know, and this seems to be an example where they are not compatible – StenSoft Apr 10 '15 at 14:52
  • It looks like the older platform interpreted `SSSSSS` incorrectly and wrote `000321` when it wanted to write 321MS . Now it seems fixed in 5.0. Too bad I have to migrate all my dates to the new format for my poor Lollipop users. – Diederik Apr 10 '15 at 20:17
0

Basically SSS is for milliseconds and SSSSSS is undefined and therefore the behavior is also not defined.

http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html S Millisecond Number

So in any case the data you have is milliseconds but wrongly represented as microseconds, you'll need to parse it back to millis to get the correct time.

Raanan
  • 4,777
  • 27
  • 47
  • `SSSSSS` is valid but according to Oracle Java, it's milliseconds padded on the left to be 6 numbers long (so it's the same as `000SSS`) and according to Android, it's microseconds (fractional second) padded on the right (so it's `SSS000` because Date only has millisecond-precision). – StenSoft Apr 11 '15 at 00:30
  • @StenSoft where did you find documentation saying that SSSSSS is a valid format and it's microseconds? Date object is milliseconds based as well. – Raanan Apr 13 '15 at 12:34
  • The documentation says it's fractional seconds (and padded from the right) and put no limit on the length of the formatting strings. – StenSoft Apr 13 '15 at 12:37
  • ok, that means SSSSSS won't crash, and will be padded from right. Doesn't actually mean it will provide microseconds accuracy - just zeros. it actually makes sense to pad from the right if you want to represent a 3 digit milliseconds in microseconds. – Raanan Apr 13 '15 at 12:41
  • Yes, that is what I have written in my original comment as well, it's the same as `SSS000` right now. I guess Android developers made it ready for some more precise `Date`-compatible type. – StenSoft Apr 13 '15 at 12:44