summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/java/text/SimpleDateFormat.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/java/text/SimpleDateFormat.java')
-rw-r--r--luni/src/main/java/java/text/SimpleDateFormat.java56
1 files changed, 39 insertions, 17 deletions
diff --git a/luni/src/main/java/java/text/SimpleDateFormat.java b/luni/src/main/java/java/text/SimpleDateFormat.java
index 5cad44b..f682c0b 100644
--- a/luni/src/main/java/java/text/SimpleDateFormat.java
+++ b/luni/src/main/java/java/text/SimpleDateFormat.java
@@ -468,7 +468,7 @@ public class SimpleDateFormat extends DateFormat {
@Override
public AttributedCharacterIterator formatToCharacterIterator(Object object) {
if (object == null) {
- throw new NullPointerException();
+ throw new NullPointerException("object == null");
}
if (object instanceof Date) {
return formatToCharacterIteratorImpl((Date) object);
@@ -1067,24 +1067,42 @@ public class SimpleDateFormat extends DateFormat {
}
private Number parseNumber(int max, String string, ParsePosition position) {
- int digit, length = string.length(), result = 0;
+ int length = string.length();
int index = position.getIndex();
if (max > 0 && max < length - index) {
length = index + max;
}
- while (index < length
- && (string.charAt(index) == ' ' || string.charAt(index) == '\t')) {
- index++;
+ while (index < length && (string.charAt(index) == ' ' || string.charAt(index) == '\t')) {
+ ++index;
}
if (max == 0) {
position.setIndex(index);
- return numberFormat.parse(string, position);
+ Number n = numberFormat.parse(string, position);
+ // In RTL locales, NumberFormat might have parsed "2012-" in an ISO date as the
+ // negative number -2012.
+ // Ideally, we wouldn't have this broken API that exposes a NumberFormat and expects
+ // us to use it. The next best thing would be a way to ask the NumberFormat to parse
+ // positive numbers only, but icu4c supports negative (BCE) years. The best we can do
+ // is try to recognize when icu4c has done this, and undo it.
+ if (n != null && n.longValue() < 0) {
+ if (numberFormat instanceof DecimalFormat) {
+ DecimalFormat df = (DecimalFormat) numberFormat;
+ char lastChar = string.charAt(position.getIndex() - 1);
+ char minusSign = df.getDecimalFormatSymbols().getMinusSign();
+ if (lastChar == minusSign) {
+ n = Long.valueOf(-n.longValue()); // Make the value positive.
+ position.setIndex(position.getIndex() - 1); // Spit out the negative sign.
+ }
+ }
+ }
+ return n;
}
- while (index < length
- && (digit = Character.digit(string.charAt(index), 10)) != -1) {
- index++;
+ int result = 0;
+ int digit;
+ while (index < length && (digit = Character.digit(string.charAt(index), 10)) != -1) {
result = result * 10 + digit;
+ ++index;
}
if (index == position.getIndex()) {
position.setErrorIndex(index);
@@ -1171,14 +1189,18 @@ public class SimpleDateFormat extends DateFormat {
}
int raw = zone.getRawOffset();
if (j == TimeZones.LONG_NAME_DST || j == TimeZones.SHORT_NAME_DST) {
- /*
- * TODO, http://b/4723412
- * We can't use TimeZone#getDSTSavings here because that
- * will return 0 if the zone no longer uses DST. We
- * should change this to use TimeZone.getOffset(long),
- * which requires the complete date to be parsed first.
- */
- raw += 3600000;
+ // Not all time zones use a one-hour difference, so we need to query
+ // the TimeZone. (Australia/Lord_Howe is the usual example of this.)
+ int dstSavings = zone.getDSTSavings();
+ // One problem with TimeZone.getDSTSavings is that it will return 0 if the
+ // time zone has stopped using DST, even if we're parsing a date from
+ // the past. In that case, assume the default.
+ if (dstSavings == 0) {
+ // TODO: we should change this to use TimeZone.getOffset(long),
+ // but that requires the complete date to be parsed first.
+ dstSavings = 3600000;
+ }
+ raw += dstSavings;
}
calendar.setTimeZone(new SimpleTimeZone(raw, ""));
return offset + element[j].length();