summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--luni/src/main/java/java/text/SimpleDateFormat.java28
-rw-r--r--luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java11
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);