Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0d05f4f authored by Victor Chang's avatar Victor Chang
Browse files

Remove libcore.icu.ICU usage in android.text.format.DateFormat

The methods can be implemented with ICU4J directly.

Bug: 160606356
Test: atest android.text.format.DateFormatTest
Test: atest CtsTextTestCases:android.text.format.cts.DateFormatTest
Change-Id: I3d5f639a94026c599b487563c95bf9d165adfeec
parent f61ae810
Loading
Loading
Loading
Loading
+49 −3
Original line number Diff line number Diff line
@@ -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) {
+1 −3
Original line number Diff line number Diff line
@@ -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]) {
+70 −0
Original line number Diff line number Diff line
@@ -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);
    }
}