diff options
author | Elliott Hughes <enh@google.com> | 2013-03-08 23:50:02 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-03-08 23:50:02 +0000 |
commit | e0cd3c19546a00db3db706c6a993fb0e3bd00b3a (patch) | |
tree | 7caa33842712e0ba213f69d8fe545029a6bcc681 /core | |
parent | 3f7a49904cef7ea14808590b63b115a4381537a1 (diff) | |
parent | 8326b9a429b63b680aa9af116c670ce674744d80 (diff) | |
download | frameworks_base-e0cd3c19546a00db3db706c6a993fb0e3bd00b3a.zip frameworks_base-e0cd3c19546a00db3db706c6a993fb0e3bd00b3a.tar.gz frameworks_base-e0cd3c19546a00db3db706c6a993fb0e3bd00b3a.tar.bz2 |
Merge "Improve DateFormat.format."
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/text/format/DateFormat.java | 348 | ||||
-rw-r--r-- | core/java/android/text/format/DateUtils.java | 13 |
2 files changed, 114 insertions, 247 deletions
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index cc676de..167a834 100644 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -34,178 +34,72 @@ import java.text.SimpleDateFormat; import libcore.icu.LocaleData; /** - Utility class for producing strings with formatted date/time. - - <p> - Most callers should avoid supplying their own format strings to this - class' {@code format} methods and rely on the correctly localized ones - supplied by the system. This class' factory methods return - appropriately-localized {@link java.text.DateFormat} instances, suitable - for both formatting and parsing dates. For the canonical documentation - of format strings, see {@link java.text.SimpleDateFormat}. - </p> - <p> - The format methods in this class takes as inputs a format string and a representation of a date/time. - The format string controls how the output is generated. - This class only supports a subset of the full Unicode specification. - Use {@link java.text.SimpleDateFormat} if you need more. - Formatting characters may be repeated in order to get more detailed representations - of that field. For instance, the format character 'M' is used to - represent the month. Depending on how many times that character is repeated - you get a different representation. - </p> - <p> - For the month of September:<br/> - M -> 9<br/> - MM -> 09<br/> - MMM -> Sep<br/> - MMMM -> September - </p> - <p> - The effects of the duplication vary depending on the nature of the field. - See the notes on the individual field formatters for details. For purely numeric - fields such as <code>HOUR</code> adding more copies of the designator will - zero-pad the value to that number of characters. - </p> - <p> - For 7 minutes past the hour:<br/> - m -> 7<br/> - mm -> 07<br/> - mmm -> 007<br/> - mmmm -> 0007 - </p> - <p> - Examples for April 6, 1970 at 3:23am:<br/> - "MM/dd/yy h:mmaa" -> "04/06/70 3:23am"<br/> - "MMM dd, yyyy h:mmaa" -> "Apr 6, 1970 3:23am"<br/> - "MMMM dd, yyyy h:mmaa" -> "April 6, 1970 3:23am"<br/> - "E, MMMM dd, yyyy h:mmaa" -> "Mon, April 6, 1970 3:23am&<br/> - "EEEE, MMMM dd, yyyy h:mmaa" -> "Monday, April 6, 1970 3:23am"<br/> - "'Noteworthy day: 'M/d/yy" -> "Noteworthy day: 4/6/70" + * Utility class for producing strings with formatted date/time. + * + * <p>Most callers should avoid supplying their own format strings to this + * class' {@code format} methods and rely on the correctly localized ones + * supplied by the system. This class' factory methods return + * appropriately-localized {@link java.text.DateFormat} instances, suitable + * for both formatting and parsing dates. For the canonical documentation + * of format strings, see {@link java.text.SimpleDateFormat}. + * + * <p>The format methods in this class implement a subset of Unicode + * <a href="http://www.unicode.org/reports/tr35/#Date_Format_Patterns">UTS #35</a> patterns. + * The subset supported by this class includes the following format characters: + * {@code acdEhkLMmsyz}. See {@link java.text.SimpleDateFormat} for more documentation + * about patterns, or if you need a more compete implementation. */ - public class DateFormat { - /** - Text in the format string that should be copied verbatim rather that - interpreted as formatting codes must be surrounded by the <code>QUOTE</code> - character. If you need to embed a literal <code>QUOTE</code> character in - the output text then use two in a row. - */ + /** @deprecated Use a literal {@code '} instead. */ + @Deprecated public static final char QUOTE = '\''; - - /** - This designator indicates whether the <code>HOUR</code> field is before - or after noon. The output is lower-case. - - Examples: - a -> a or p - aa -> am or pm - */ + + /** @deprecated Use a literal {@code 'a'} instead. */ + @Deprecated public static final char AM_PM = 'a'; - /** - This designator indicates whether the <code>HOUR</code> field is before - or after noon. The output is capitalized. - - Examples: - A -> A or P - AA -> AM or PM - */ + /** @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'. */ + @Deprecated public static final char CAPITAL_AM_PM = 'A'; - /** - This designator indicates the day of the month. - - Examples for the 9th of the month: - d -> 9 - dd -> 09 - */ + /** @deprecated Use a literal {@code 'd'} instead. */ + @Deprecated public static final char DATE = 'd'; - /** - This designator indicates the name of the day of the week. - - Examples for Sunday: - E -> Sun - EEEE -> Sunday - */ + /** @deprecated Use a literal {@code 'E'} instead. */ + @Deprecated public static final char DAY = 'E'; - /** - This designator indicates the hour of the day in 12 hour format. - - Examples for 3pm: - h -> 3 - hh -> 03 - */ + /** @deprecated Use a literal {@code 'h'} instead. */ + @Deprecated public static final char HOUR = 'h'; - /** - This designator indicates the hour of the day in 24 hour format. - - Example for 3pm: - k -> 15 - - Examples for midnight: - k -> 0 - kk -> 00 - */ + /** @deprecated Use a literal {@code 'k'} instead. */ + @Deprecated public static final char HOUR_OF_DAY = 'k'; - /** - This designator indicates the minute of the hour. - - Examples for 7 minutes past the hour: - m -> 7 - mm -> 07 - */ + /** @deprecated Use a literal {@code 'm'} instead. */ + @Deprecated public static final char MINUTE = 'm'; - /** - This designator indicates the month of the year. See also - {@link #STANDALONE_MONTH}. - - Examples for September: - M -> 9 - MM -> 09 - MMM -> Sep - MMMM -> September - */ + /** @deprecated Use a literal {@code 'M'} instead. */ + @Deprecated public static final char MONTH = 'M'; - /** - This designator indicates the standalone month of the year, - necessary in some format strings in some languages. For - example, Russian distinguishes between the "June" in - "June" and that in "June 2010". - */ + /** @deprecated Use a literal {@code 'L'} instead. */ + @Deprecated public static final char STANDALONE_MONTH = 'L'; - /** - This designator indicates the seconds of the minute. - - Examples for 7 seconds past the minute: - s -> 7 - ss -> 07 - */ + /** @deprecated Use a literal {@code 's'} instead. */ + @Deprecated public static final char SECONDS = 's'; - /** - This designator indicates the offset of the timezone from GMT. - - Example for US/Pacific timezone: - z -> -0800 - zz -> PST - */ + /** @deprecated Use a literal {@code 'z'} instead. */ + @Deprecated public static final char TIME_ZONE = 'z'; - /** - This designator indicates the year. - - Examples for 2006 - y -> 06 - yyyy -> 2006 - */ + /** @deprecated Use a literal {@code 'y'} instead. */ + @Deprecated public static final char YEAR = 'y'; @@ -233,8 +127,7 @@ public class DateFormat { } java.text.DateFormat natural = - java.text.DateFormat.getTimeInstance( - java.text.DateFormat.LONG, locale); + java.text.DateFormat.getTimeInstance(java.text.DateFormat.LONG, locale); if (natural instanceof SimpleDateFormat) { SimpleDateFormat sdf = (SimpleDateFormat) natural; @@ -273,7 +166,7 @@ public class DateFormat { } /** - * Returns a {@link java.text.DateFormat} object that can format the date + * Returns a {@link java.text.DateFormat} object that can format the date * in short form (such as 12/31/1999) according * to the current locale and the user's date-order preference. * @param context the application context @@ -342,10 +235,10 @@ public class DateFormat { value = context.getString(R.string.numeric_date_format); return value; } - + /** * Returns a {@link java.text.DateFormat} object that can format the date - * in long form (such as December 31, 1999) for the current locale. + * in long form (such as {@code Monday, January 3, 2000}) for the current locale. * @param context the application context * @return the {@link java.text.DateFormat} object that formats the date in long form. */ @@ -355,7 +248,7 @@ public class DateFormat { /** * Returns a {@link java.text.DateFormat} object that can format the date - * in medium form (such as Dec. 31, 1999) for the current locale. + * in medium form (such as {@code Jan 3, 2000}) for the current locale. * @param context the application context * @return the {@link java.text.DateFormat} object that formats the date in long form. */ @@ -365,13 +258,13 @@ public class DateFormat { /** * Gets the current date format stored as a char array. The array will contain - * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order + * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order * specified by the user's format preference. Note that this order is * only appropriate for all-numeric dates; spelled-out (MEDIUM and LONG) * dates will generally contain other punctuation, spaces, or words, * not just the day, month, and year, and not necessarily in the same * order returned here. - */ + */ public static char[] getDateFormatOrder(Context context) { char[] order = new char[] {DATE, MONTH, YEAR}; String value = getDateFormatString(context); @@ -401,7 +294,7 @@ public class DateFormat { } return order; } - + private static String getDateFormatString(Context context) { String value = Settings.System.getString(context.getContentResolver(), Settings.System.DATE_FORMAT); @@ -410,7 +303,7 @@ public class DateFormat { } /** - * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a + * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a * CharSequence containing the requested date. * @param inFormat the format string, as described in {@link android.text.format.DateFormat} * @param inTimeInMillis in milliseconds since Jan 1, 1970 GMT @@ -428,22 +321,20 @@ public class DateFormat { * @return a {@link CharSequence} containing the requested text */ public static CharSequence format(CharSequence inFormat, Date inDate) { - Calendar c = new GregorianCalendar(); - + Calendar c = new GregorianCalendar(); c.setTime(inDate); - return format(inFormat, c); } /** * Indicates whether the specified format string contains seconds. - * + * * Always returns false if the input format is null. - * + * * @param inFormat the format string, as described in {@link android.text.format.DateFormat} - * + * * @return true if the format string contains {@link #SECONDS}, false otherwise - * + * * @hide */ public static boolean hasSeconds(CharSequence inFormat) { @@ -498,24 +389,23 @@ public class DateFormat { } /** - * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence + * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence * containing the requested date. * @param inFormat the format string, as described in {@link android.text.format.DateFormat} * @param inDate the date to format * @return a {@link CharSequence} containing the requested text */ public static CharSequence format(CharSequence inFormat, Calendar inDate) { - SpannableStringBuilder s = new SpannableStringBuilder(inFormat); - int c; - int count; + SpannableStringBuilder s = new SpannableStringBuilder(inFormat); + int count; + + LocaleData localeData = LocaleData.get(Locale.getDefault()); int len = inFormat.length(); for (int i = 0; i < len; i += count) { - int temp; - count = 1; - c = s.charAt(i); + int c = s.charAt(i); if (c == QUOTE) { count = appendQuotedText(s, i, len); @@ -528,102 +418,89 @@ public class DateFormat { } String replacement; - switch (c) { - case AM_PM: - replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM)); + case 'A': + case 'a': + replacement = localeData.amPm[inDate.get(Calendar.AM_PM) - Calendar.AM]; break; - - case CAPITAL_AM_PM: - //FIXME: this is the same as AM_PM? no capital? - replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM)); - break; - - case DATE: + case 'd': replacement = zeroPad(inDate.get(Calendar.DATE), count); break; - - case DAY: - temp = inDate.get(Calendar.DAY_OF_WEEK); - replacement = DateUtils.getDayOfWeekString(temp, - count < 4 ? - DateUtils.LENGTH_MEDIUM : - DateUtils.LENGTH_LONG); + case 'c': + case 'E': + replacement = getDayOfWeekString(localeData, + inDate.get(Calendar.DAY_OF_WEEK), count, c); break; - - case HOUR: - temp = inDate.get(Calendar.HOUR); - - if (0 == temp) - temp = 12; - - replacement = zeroPad(temp, count); + case 'h': + int hour = inDate.get(Calendar.HOUR); + replacement = zeroPad(hour == 0 ? 24 : hour, count); break; - - case HOUR_OF_DAY: + case 'k': replacement = zeroPad(inDate.get(Calendar.HOUR_OF_DAY), count); break; - - case MINUTE: - replacement = zeroPad(inDate.get(Calendar.MINUTE), count); + case 'L': + case 'M': + replacement = getMonthString(localeData, + inDate.get(Calendar.MONTH), count, c); break; - - case MONTH: - case STANDALONE_MONTH: - replacement = getMonthString(inDate, count, c); + case 'm': + replacement = zeroPad(inDate.get(Calendar.MINUTE), count); break; - - case SECONDS: + case 's': replacement = zeroPad(inDate.get(Calendar.SECOND), count); break; - - case TIME_ZONE: - replacement = getTimeZoneString(inDate, count); + case 'y': + replacement = getYearString(inDate.get(Calendar.YEAR), count); break; - - case YEAR: - replacement = getYearString(inDate, count); + case 'z': + replacement = getTimeZoneString(inDate, count); break; - default: replacement = null; break; } - + if (replacement != null) { s.replace(i, i + count, replacement); count = replacement.length(); // CARE: count is used in the for loop above len = s.length(); } } - - if (inFormat instanceof Spanned) + + if (inFormat instanceof Spanned) { return new SpannedString(s); - else + } else { return s.toString(); + } + } + + private static String getDayOfWeekString(LocaleData ld, int day, int count, int kind) { + boolean standalone = (kind == 'c'); + if (count == 5) { + return standalone ? ld.tinyStandAloneWeekdayNames[day] : ld.tinyWeekdayNames[day]; + } else if (count == 4) { + return standalone ? ld.longStandAloneWeekdayNames[day] : ld.longWeekdayNames[day]; + } else { + return standalone ? ld.shortStandAloneWeekdayNames[day] : ld.shortWeekdayNames[day]; + } } - - private static String getMonthString(Calendar inDate, int count, int kind) { - boolean standalone = (kind == STANDALONE_MONTH); - int month = inDate.get(Calendar.MONTH); - - if (count >= 4) { - return standalone - ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_LONG) - : DateUtils.getMonthString(month, DateUtils.LENGTH_LONG); + + private static String getMonthString(LocaleData ld, int month, int count, int kind) { + boolean standalone = (kind == 'L'); + if (count == 5) { + return standalone ? ld.tinyStandAloneMonthNames[month] : ld.tinyMonthNames[month]; + } else if (count == 4) { + return standalone ? ld.longStandAloneMonthNames[month] : ld.longMonthNames[month]; } else if (count == 3) { - return standalone - ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_MEDIUM) - : DateUtils.getMonthString(month, DateUtils.LENGTH_MEDIUM); + return standalone ? ld.shortStandAloneMonthNames[month] : ld.shortMonthNames[month]; } else { // Calendar.JANUARY == 0, so add 1 to month. return zeroPad(month+1, count); } } - + private static String getTimeZoneString(Calendar inDate, int count) { TimeZone tz = inDate.getTimeZone(); - if (count < 2) { // FIXME: shouldn't this be <= 2 ? return formatZoneOffset(inDate.get(Calendar.DST_OFFSET) + inDate.get(Calendar.ZONE_OFFSET), @@ -652,13 +529,12 @@ public class DateFormat { tb.append(zeroPad(minutes, 2)); return tb.toString(); } - - private static String getYearString(Calendar inDate, int count) { - int year = inDate.get(Calendar.YEAR); + + private static String getYearString(int year, int count) { return (count <= 2) ? zeroPad(year % 100, 2) : String.format(Locale.getDefault(), "%d", year); } - + private static int appendQuotedText(SpannableStringBuilder s, int i, int len) { if (i + 1 < len && s.charAt(i + 1) == QUOTE) { s.delete(i, i + 1); diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java index 5a20ceb..08813df 100644 --- a/core/java/android/text/format/DateUtils.java +++ b/core/java/android/text/format/DateUtils.java @@ -274,10 +274,6 @@ public class DateUtils */ @Deprecated public static String getMonthString(int month, int abbrev) { - // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER. - // This is a shortcut to not spam the translators with too many variations - // of the same string. If we find that in a language the distinction - // is necessary, we can can add more without changing this API. LocaleData d = LocaleData.get(Locale.getDefault()); String[] names; switch (abbrev) { @@ -308,19 +304,14 @@ public class DateUtils */ @Deprecated public static String getStandaloneMonthString(int month, int abbrev) { - // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER. - // This is a shortcut to not spam the translators with too many variations - // of the same string. If we find that in a language the distinction - // is necessary, we can can add more without changing this API. LocaleData d = LocaleData.get(Locale.getDefault()); String[] names; switch (abbrev) { - case LENGTH_LONG: names = d.longStandAloneMonthNames; - break; + case LENGTH_LONG: names = d.longStandAloneMonthNames; break; case LENGTH_MEDIUM: names = d.shortMonthNames; break; case LENGTH_SHORT: names = d.shortMonthNames; break; case LENGTH_SHORTER: names = d.shortMonthNames; break; - case LENGTH_SHORTEST: names = d.tinyMonthNames; break; + case LENGTH_SHORTEST: names = d.tinyStandAloneMonthNames; break; default: names = d.shortMonthNames; break; } return names[month]; |