diff options
3 files changed, 120 insertions, 6 deletions
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index 0863a813543c..683c74737a2d 100755 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -19,12 +19,12 @@ package android.text.format; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.icu.text.DateTimePatternGenerator; import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.SpannedString; -import libcore.icu.ICU; import libcore.icu.LocaleData; import java.text.SimpleDateFormat; @@ -251,7 +251,8 @@ public class DateFormat { * @return a string pattern suitable for use with {@link java.text.SimpleDateFormat}. */ public static String getBestDateTimePattern(Locale locale, String skeleton) { - return ICU.getBestDateTimePattern(skeleton, locale); + DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(locale); + return dtpg.getBestPattern(skeleton); } /** @@ -333,7 +334,52 @@ public class DateFormat { * order returned here. */ public static char[] getDateFormatOrder(Context context) { - return ICU.getDateFormatOrder(getDateFormatString(context)); + return getDateFormatOrder(getDateFormatString(context)); + } + + /** + * @hide Used by internal framework class {@link android.widget.DatePickerSpinnerDelegate}. + */ + public static char[] getDateFormatOrder(String pattern) { + char[] result = new char[3]; + int resultIndex = 0; + boolean sawDay = false; + boolean sawMonth = false; + boolean sawYear = false; + + for (int i = 0; i < pattern.length(); ++i) { + char ch = pattern.charAt(i); + if (ch == 'd' || ch == 'L' || ch == 'M' || ch == 'y') { + if (ch == 'd' && !sawDay) { + result[resultIndex++] = 'd'; + sawDay = true; + } else if ((ch == 'L' || ch == 'M') && !sawMonth) { + result[resultIndex++] = 'M'; + sawMonth = true; + } else if ((ch == 'y') && !sawYear) { + result[resultIndex++] = 'y'; + sawYear = true; + } + } else if (ch == 'G') { + // Ignore the era specifier, if present. + } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { + throw new IllegalArgumentException("Bad pattern character '" + ch + "' in " + + pattern); + } else if (ch == '\'') { + if (i < pattern.length() - 1 && pattern.charAt(i + 1) == '\'') { + ++i; + } else { + i = pattern.indexOf('\'', i + 1); + if (i == -1) { + throw new IllegalArgumentException("Bad quoting in " + pattern); + } + ++i; + } + } else { + // Ignore spaces and punctuation. + } + } + return result; } private static String getDateFormatString(Context context) { diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java index 096e6ea52c8a..fd89b2e09131 100644 --- a/core/java/android/widget/DatePickerSpinnerDelegate.java +++ b/core/java/android/widget/DatePickerSpinnerDelegate.java @@ -34,8 +34,6 @@ import android.view.inputmethod.InputMethodManager; import android.widget.DatePicker.AbstractDatePickerDelegate; import android.widget.NumberPicker.OnValueChangeListener; -import libcore.icu.ICU; - import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -459,7 +457,7 @@ class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate { // We use numeric spinners for year and day, but textual months. Ask icu4c what // order the user's locale uses for that combination. http://b/7207103. String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd"); - char[] order = ICU.getDateFormatOrder(pattern); + char[] order = DateFormat.getDateFormatOrder(pattern); final int spinnerCount = order.length; for (int i = 0; i < spinnerCount; i++) { switch (order[i]) { diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java index 5a0a84db5905..fa1d56f2e68d 100644 --- a/core/tests/coretests/src/android/text/format/DateFormatTest.java +++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java @@ -16,8 +16,10 @@ package android.text.format; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import android.platform.test.annotations.Presubmit; @@ -27,6 +29,7 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; import java.util.Locale; @Presubmit @@ -55,4 +58,71 @@ public class DateFormatTest { assertFalse(DateFormat.is24HourLocale(Locale.US)); assertTrue(DateFormat.is24HourLocale(Locale.GERMANY)); } + + @Test + public void testGetDateFormatOrder() { + // lv and fa use differing orders depending on whether you're using numeric or + // textual months. + Locale lv = new Locale("lv"); + assertEquals("[d, M, y]", Arrays.toString(DateFormat.getDateFormatOrder( + best(lv, "yyyy-M-dd")))); + assertEquals("[y, d, M]", Arrays.toString(DateFormat.getDateFormatOrder( + best(lv, "yyyy-MMM-dd")))); + assertEquals("[d, M, \u0000]", Arrays.toString(DateFormat.getDateFormatOrder( + best(lv, "MMM-dd")))); + Locale fa = new Locale("fa"); + assertEquals("[y, M, d]", Arrays.toString(DateFormat.getDateFormatOrder( + best(fa, "yyyy-M-dd")))); + assertEquals("[d, M, y]", Arrays.toString(DateFormat.getDateFormatOrder( + best(fa, "yyyy-MMM-dd")))); + assertEquals("[d, M, \u0000]", Arrays.toString(DateFormat.getDateFormatOrder( + best(fa, "MMM-dd")))); + + // English differs on each side of the Atlantic. + Locale enUS = Locale.US; + assertEquals("[M, d, y]", Arrays.toString(DateFormat.getDateFormatOrder( + best(enUS, "yyyy-M-dd")))); + assertEquals("[M, d, y]", Arrays.toString(DateFormat.getDateFormatOrder( + best(enUS, "yyyy-MMM-dd")))); + assertEquals("[M, d, \u0000]", Arrays.toString(DateFormat.getDateFormatOrder( + best(enUS, "MMM-dd")))); + Locale enGB = Locale.UK; + assertEquals("[d, M, y]", Arrays.toString(DateFormat.getDateFormatOrder( + best(enGB, "yyyy-M-dd")))); + assertEquals("[d, M, y]", Arrays.toString(DateFormat.getDateFormatOrder( + best(enGB, "yyyy-MMM-dd")))); + assertEquals("[d, M, \u0000]", Arrays.toString(DateFormat.getDateFormatOrder( + best(enGB, "MMM-dd")))); + + assertEquals("[y, M, d]", Arrays.toString(DateFormat.getDateFormatOrder( + "yyyy - 'why' '' 'ddd' MMM-dd"))); + + try { + DateFormat.getDateFormatOrder("the quick brown fox jumped over the lazy dog"); + fail(); + } catch (IllegalArgumentException expected) { + } + + try { + DateFormat.getDateFormatOrder("'"); + fail(); + } catch (IllegalArgumentException expected) { + } + + try { + DateFormat.getDateFormatOrder("yyyy'"); + fail(); + } catch (IllegalArgumentException expected) { + } + + try { + DateFormat.getDateFormatOrder("yyyy'MMM"); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + private static String best(Locale l, String skeleton) { + return DateFormat.getBestDateTimePattern(l, skeleton); + } } |