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-14 13:26:22 +0100
commite73ebc998a5b4017e805d750b395603d953d3c0c (patch)
tree6fdf5355bc7470cb241720451b95c318634fba32 /luni
parent0dcfa1d088f114eb92a96b09eebf6172428ea6b5 (diff)
downloadlibcore-e73ebc998a5b4017e805d750b395603d953d3c0c.zip
libcore-e73ebc998a5b4017e805d750b395603d953d3c0c.tar.gz
libcore-e73ebc998a5b4017e805d750b395603d953d3c0c.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 Change-Id: Id287684f78691090ac4a6c3029d7909f2c1e1310
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);