diff options
-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); |