summaryrefslogtreecommitdiffstats
path: root/text/src
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2010-01-13 23:14:56 -0800
committerElliott Hughes <enh@google.com>2010-01-14 12:50:53 -0800
commite1e5e8e60af12f145c4dd0395e30069665f97529 (patch)
tree191a722e9ccb999bf9eec8d162abc540f409fa8e /text/src
parentb64c406bd2becd117d88cef3d90d84243d6016af (diff)
downloadlibcore-e1e5e8e60af12f145c4dd0395e30069665f97529.zip
libcore-e1e5e8e60af12f145c4dd0395e30069665f97529.tar.gz
libcore-e1e5e8e60af12f145c4dd0395e30069665f97529.tar.bz2
Fix Date.toString.
Date.toString was using the TimeZone id ("America/Los_Angeles") rather than the time zone short name ("PDT" or "PST", depending on time of year). The naive fix made things 5x slower, so I improved Resources.getDisplayTimeZone so the fixed Date.toString is only 2x slower. This could be improved further with a faster getDisplayTimeZone. I hoped to replace the body of Date.toString with a call to SimpleDateFormat, but that turns out to be 40x slower. This patch also optimizes SimpleDateFormat to bring the gap down to 8x by using Resources.getDisplayTimeZone instead of asking for all the strings. (Note that these improvements refer to the hopefully common case of localized strings for the default locale. If you have the misfortune to need strings for other locales, the new code will be more like 600x faster. At 0.5s a call on the fastest current hardware, I hope no-one's actually doing that. Dalvik Explorer -- available on the Market -- needs to do it when generating summary reports, and it is indeed ridiculously slow. It uses two SimpleDateFormat objects per locale, so it takes 1s per locale, for about 60 locales. I've tested Dalvik Explorer with this patch, and it does fix that pathological behavior.) Also fix a bug I introduced in https://android-git.corp.google.com/g/36242 that meant that our zone names String[][] contained incorrect values (accidentally concatenating each successive value in a row), found by existing tests now we use more of those values. Also replace a couple of "new Integer" calls with Integer.valueOf for a modest speedup. Also factor out some duplication. Bug: http://code.google.com/p/android/issues/detail?id=6013
Diffstat (limited to 'text/src')
-rw-r--r--text/src/main/java/java/text/DateFormatSymbols.java4
-rw-r--r--text/src/main/java/java/text/SimpleDateFormat.java105
2 files changed, 58 insertions, 51 deletions
diff --git a/text/src/main/java/java/text/DateFormatSymbols.java b/text/src/main/java/java/text/DateFormatSymbols.java
index 767a301..184cdcf 100644
--- a/text/src/main/java/java/text/DateFormatSymbols.java
+++ b/text/src/main/java/java/text/DateFormatSymbols.java
@@ -79,7 +79,10 @@ public class DateFormatSymbols implements Serializable, Cloneable {
String[] ampms, eras, months, shortMonths, shortWeekdays, weekdays;
+ // Localized display names.
String[][] zoneStrings;
+ // Has the user called setZoneStrings?
+ transient boolean customZoneStrings;
// BEGIN android-removed
// transient private com.ibm.icu4jni.text.DateFormatSymbols icuSymbols;
@@ -474,5 +477,6 @@ public class DateFormatSymbols implements Serializable, Cloneable {
*/
public void setZoneStrings(String[][] data) {
zoneStrings = Resources.clone2dStringArray(data);
+ customZoneStrings = true;
}
}
diff --git a/text/src/main/java/java/text/SimpleDateFormat.java b/text/src/main/java/java/text/SimpleDateFormat.java
index 01a4418..e2422ad 100644
--- a/text/src/main/java/java/text/SimpleDateFormat.java
+++ b/text/src/main/java/java/text/SimpleDateFormat.java
@@ -30,13 +30,13 @@ import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
// BEGIN android-added
-import java.util.ResourceBundle;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
// END android-added
import java.util.Vector;
import com.ibm.icu4jni.util.LocaleData;
+import com.ibm.icu4jni.util.Resources;
import org.apache.harmony.text.internal.nls.Messages;
/**
@@ -894,7 +894,7 @@ public class SimpleDateFormat extends DateFormat {
// BEGIN android-changed
case (TIMEZONE_FIELD + 1): // Z
dateFormatField = Field.TIME_ZONE;
- appendTimeZone(buffer, count, false);
+ appendNumericTimeZone(buffer, false);
break;
// END android-changed
}
@@ -918,62 +918,65 @@ public class SimpleDateFormat extends DateFormat {
}
}
- private void appendTimeZone(StringBuffer buffer, int count,
- boolean generalTimezone) {
- // cannot call TimeZone.getDisplayName() because it would not use
- // the DateFormatSymbols of this SimpleDateFormat
-
- if (generalTimezone) {
- String id = calendar.getTimeZone().getID();
- // BEGIN android-changed
- String[][] zones = formatData.internalZoneStrings();
- // END android-changed
- String[] zone = null;
- for (String[] element : zones) {
- if (id.equals(element[0])) {
- zone = element;
- break;
- }
- }
- if (zone == null) {
- int offset = calendar.get(Calendar.ZONE_OFFSET)
- + calendar.get(Calendar.DST_OFFSET);
- char sign = '+';
- if (offset < 0) {
- sign = '-';
- offset = -offset;
- }
- buffer.append("GMT"); //$NON-NLS-1$
- buffer.append(sign);
- appendNumber(buffer, 2, offset / 3600000);
- buffer.append(':');
- appendNumber(buffer, 2, (offset % 3600000) / 60000);
- } else {
- int daylight = calendar.get(Calendar.DST_OFFSET) == 0 ? 0 : 2;
- if (count < 4) {
- buffer.append(zone[2 + daylight]);
- } else {
- buffer.append(zone[1 + daylight]);
- }
+ /**
+ * Append a representation of the time zone of 'calendar' to 'buffer'.
+ *
+ * @param count the number of z or Z characters in the format string; "zzz" would be 3,
+ * for example.
+ * @param generalTimeZone true if we should use a display name ("PDT") if available;
+ * false implies that we should use RFC 822 format ("-0800") instead. This corresponds to 'z'
+ * versus 'Z' in the format string.
+ */
+ private void appendTimeZone(StringBuffer buffer, int count, boolean generalTimeZone) {
+ // BEGIN android-changed: optimized.
+ if (generalTimeZone) {
+ TimeZone tz = calendar.getTimeZone();
+ boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
+ int style = count < 4 ? TimeZone.SHORT : TimeZone.LONG;
+ if (!formatData.customZoneStrings) {
+ buffer.append(tz.getDisplayName(daylight, style, formatData.locale));
+ return;
}
- } else {
- int offset = calendar.get(Calendar.ZONE_OFFSET)
- + calendar.get(Calendar.DST_OFFSET);
- char sign = '+';
- if (offset < 0) {
- sign = '-';
- offset = -offset;
+ // We can't call TimeZone.getDisplayName() because it would not use
+ // the custom DateFormatSymbols of this SimpleDateFormat.
+ String custom = Resources.lookupDisplayTimeZone(formatData.zoneStrings, tz.getID(), daylight, style);
+ if (custom != null) {
+ buffer.append(custom);
+ return;
}
- buffer.append(sign);
- appendNumber(buffer, 2, offset / 3600000);
- appendNumber(buffer, 2, (offset % 3600000) / 60000);
}
+ // We didn't find what we were looking for, so default to a numeric time zone.
+ appendNumericTimeZone(buffer, generalTimeZone);
+ // END android-changed
}
+ // BEGIN android-added: factored out duplication.
+ /**
+ * @param generalTimeZone "GMT-08:00" rather than "-0800".
+ */
+ private void appendNumericTimeZone(StringBuffer buffer, boolean generalTimeZone) {
+ int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
+ char sign = '+';
+ if (offset < 0) {
+ sign = '-';
+ offset = -offset;
+ }
+ if (generalTimeZone) {
+ buffer.append("GMT");
+ }
+ buffer.append(sign);
+ appendNumber(buffer, 2, offset / 3600000);
+ if (generalTimeZone) {
+ buffer.append(':');
+ }
+ appendNumber(buffer, 2, (offset % 3600000) / 60000);
+ }
+ // END android-added
+
private void appendNumber(StringBuffer buffer, int count, int value) {
int minimumIntegerDigits = numberFormat.getMinimumIntegerDigits();
numberFormat.setMinimumIntegerDigits(count);
- numberFormat.format(new Integer(value), buffer, new FieldPosition(0));
+ numberFormat.format(Integer.valueOf(value), buffer, new FieldPosition(0));
numberFormat.setMinimumIntegerDigits(minimumIntegerDigits);
}
@@ -1296,7 +1299,7 @@ public class SimpleDateFormat extends DateFormat {
return null;
}
position.setIndex(index);
- return new Integer(result);
+ return Integer.valueOf(result);
}
private int parseNumber(int max, String string, int offset, int field,