diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 02208f3de..9438361e8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,6 +49,7 @@ The type attribute can be add,update,fix,remove. Reimplement StopWatch internals to use java.time. RandomStringUtils.random() with a negative character index should throw IllegalArgumentException. + LocaleUtils.toLocale(String) cannot parse four segments. Add StopWatch.getSplitDuration() and deprecate getSplitTime(). Add StopWatch.getStartInstant() and deprecate getStartTime(). diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java b/src/main/java/org/apache/commons/lang3/LocaleUtils.java index 8548ba4ee..39b81a490 100644 --- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java +++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java @@ -249,28 +249,30 @@ public class LocaleUtils { } /** - * Tries to parse a locale from the given String. + * Tries to parse a Locale from the given String. + *

+ * See {@Link Locale} for the format. + *

* - * @param str the String to parse a locale from. - * @return a Locale instance parsed from the given String. + * @param str the String to parse as a Locale. + * @return a Locale parsed from the given String. * @throws IllegalArgumentException if the given String can not be parsed. + * @see Locale */ private static Locale parseLocale(final String str) { if (isISO639LanguageCode(str)) { return new Locale(str); } - - final String[] segments = str.indexOf(UNDERSCORE) != -1 - ? str.split(String.valueOf(UNDERSCORE), -1) - : str.split(String.valueOf(DASH), -1); + final int limit = 3; + final char separator = str.indexOf(UNDERSCORE) != -1 ? UNDERSCORE : DASH; + final String[] segments = str.split(String.valueOf(separator), 3); final String language = segments[0]; if (segments.length == 2) { final String country = segments[1]; - if (isISO639LanguageCode(language) && isISO3166CountryCode(country) || - isNumericAreaCode(country)) { + if (isISO639LanguageCode(language) && isISO3166CountryCode(country) || isNumericAreaCode(country)) { return new Locale(language, country); } - } else if (segments.length == 3) { + } else if (segments.length == limit) { final String country = segments[1]; final String variant = segments[2]; if (isISO639LanguageCode(language) && diff --git a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java index 6205283f5..dc9e3969d 100644 --- a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java @@ -538,9 +538,10 @@ public class LocaleUtilsTest extends AbstractLangTest { assertValidToLocale("us_EN_a", "us", "EN", "A"); assertValidToLocale("us_EN_SFsafdFDsdfF", "us", "EN", "SFSAFDFDSDFF"); } - assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("us_EN-a"), "Should fail as no consistent delimiter"); assertThrows(IllegalArgumentException.class, () -> LocaleUtils.toLocale("uu_UU_"), "Must be 3, 5 or 7+ in length"); + // LANG-1741 + assertEquals(new Locale("en", "001", "US_POSIX"), LocaleUtils.toLocale("en_001_US_POSIX")); } /**