summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2014-08-14 13:18:07 +0100
committerNarayan Kamath <narayan@google.com>2014-08-15 14:15:28 +0100
commit6673173f156316105e18c52b03057cd621361a7e (patch)
tree7578a13d27a6b6a3e26f5e22ec4d7e5886f39725 /luni
parente4f01dff49442840faa828dcff0d1583a2e68530 (diff)
downloadlibcore-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.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);