diff options
author | Narayan Kamath <narayan@google.com> | 2014-08-14 13:18:07 +0100 |
---|---|---|
committer | Narayan Kamath <narayan@google.com> | 2014-08-15 14:15:28 +0100 |
commit | 6673173f156316105e18c52b03057cd621361a7e (patch) | |
tree | 7578a13d27a6b6a3e26f5e22ec4d7e5886f39725 /luni | |
parent | e4f01dff49442840faa828dcff0d1583a2e68530 (diff) | |
download | libcore-6673173f156316105e18c52b03057cd621361a7e.zip libcore-6673173f156316105e18c52b03057cd621361a7e.tar.gz libcore-6673173f156316105e18c52b03057cd621361a7e.tar.bz2 |
Fix parsing of fractional seconds.
We were just parsing them as millisecond values, which is wrong.
".1" fractional second is 100 milliseconds (we were parsing it as 1 ms),
and ".765432" fractional seconds is 765 milliseconds (we were
parsing it as 765432ms.
In most cases, this was hidden by the fact that we were formatting
such values incorrectly as well.
bug: 16969112
(cherry picked from commit e73ebc998a5b4017e805d750b395603d953d3c0c)
Change-Id: I8401cfa65d3d6d424ae0b962e8c045d65a776183
Diffstat (limited to 'luni')
-rw-r--r-- | luni/src/main/java/java/text/SimpleDateFormat.java | 28 | ||||
-rw-r--r-- | luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java | 11 |
2 files changed, 37 insertions, 2 deletions
diff --git a/luni/src/main/java/java/text/SimpleDateFormat.java b/luni/src/main/java/java/text/SimpleDateFormat.java index c1a8ee9..8f83ff7 100644 --- a/luni/src/main/java/java/text/SimpleDateFormat.java +++ b/luni/src/main/java/java/text/SimpleDateFormat.java @@ -907,8 +907,7 @@ public class SimpleDateFormat extends DateFormat { field = Calendar.SECOND; break; case MILLISECOND_FIELD: - field = Calendar.MILLISECOND; - break; + return parseFractionalSeconds(string, offset, absolute); case STAND_ALONE_DAY_OF_WEEK_FIELD: return parseDayOfWeek(string, offset, true); case DAY_OF_WEEK_FIELD: @@ -953,6 +952,31 @@ public class SimpleDateFormat extends DateFormat { return offset; } + /** + * Parses the fractional seconds section of a formatted date and assigns + * it to the {@code Calendar.MILLISECOND} field. Note that fractional seconds + * are somewhat unique, because they are zero suffixed. + */ + private int parseFractionalSeconds(String string, int offset, int count) { + final ParsePosition parsePosition = new ParsePosition(offset); + final Number fractionalSeconds = parseNumber(count, string, parsePosition); + if (fractionalSeconds == null) { + return -parsePosition.getErrorIndex() - 1; + } + + // NOTE: We could've done this using two parses instead. The first parse + // looking at |count| digits (to verify the date matched the format), and + // then a second parse that consumed just the first three digits. That + // would've avoided the floating point arithmetic, but would've demanded + // that we round values ourselves. + final double result = fractionalSeconds.doubleValue(); + final int numDigitsParsed = parsePosition.getIndex() - offset; + final double divisor = Math.pow(10, numDigitsParsed); + + calendar.set(Calendar.MILLISECOND, (int) ((result / divisor) * 1000)); + return parsePosition.getIndex(); + } + private int parseDayOfWeek(String string, int offset, boolean standAlone) { LocaleData ld = formatData.localeData; int index = parseText(string, offset, diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java index d65aa0e..e73104d 100644 --- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java +++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java @@ -351,6 +351,17 @@ public class SimpleDateFormatTest extends junit.framework.TestCase { assertEquals(1376927400000L, sdf.parse("19. Aug. 2013 8:50").getTime()); } + // http://b/16969112 + public void test_fractionalSeconds() throws Exception { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"); + assertEquals("1970-01-02 02:17:36.7", sdf.format(sdf.parse("1970-01-02 02:17:36.7"))); + + // We only have millisecond precision for Date objects, so we'll lose + // information from the fractional seconds section of the string presentation. + sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + assertEquals("1970-01-02 02:17:36.789000", sdf.format(sdf.parse("1970-01-02 02:17:36.789564"))); + } + public void test_nullLocales() { try { SimpleDateFormat.getDateInstance(DateFormat.SHORT, null); |