--- old/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java 2016-12-01 16:43:16.000000000 +0530 +++ new/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java 2016-12-01 16:43:16.000000000 +0530 @@ -52,6 +52,7 @@ import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; +import sun.text.spi.JavaTimeDateTimePatternProvider; import sun.util.spi.CalendarProvider; /** @@ -525,6 +526,167 @@ }; } + public static JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() { + return new JavaTimeDateTimePatternProvider() { + @Override + public Locale[] getAvailableLocales() { + return getSupportedCalendarLocales(); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + return isSupportedCalendarLocale(locale); + } + + @Override + public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) { + AtomicReferenceArray patterns = getDateTimePatterns(locale); + String pattern = new StringBuilder(patterns.get(dateStyle / 2)) + .append(" ") + .append(patterns.get(timeStyle / 2 + 2)) + .toString(); + return toJavaTimeDateTimePattern(calType, pattern); + + } + + private AtomicReferenceArray getDateTimePatterns(Locale locale) { + AtomicReferenceArray patterns; + SoftReference> ref = dateFormatCache.get(locale); + + if (ref == null || (patterns = ref.get()) == null) { + String langtag = removeExtensions(locale).toLanguageTag(); + patterns = new AtomicReferenceArray<>(4); + patterns.compareAndSet(0, null, convertDateTimePattern( + getDateTimePattern(DateFormat.LONG, -1, langtag))); + patterns.compareAndSet(1, null, convertDateTimePattern( + getDateTimePattern(DateFormat.SHORT, -1, langtag))); + patterns.compareAndSet(2, null, convertDateTimePattern( + getDateTimePattern(-1, DateFormat.LONG, langtag))); + patterns.compareAndSet(3, null, convertDateTimePattern( + getDateTimePattern(-1, DateFormat.SHORT, langtag))); + ref = new SoftReference<>(patterns); + dateFormatCache.put(locale, ref); + } + return patterns; + } + /** + * This method will convert JRE Date/time Pattern String to JSR310 + * type Date/Time Pattern + */ + private String toJavaTimeDateTimePattern(String calendarType, String jrePattern) { + int length = jrePattern.length(); + StringBuilder sb = new StringBuilder(length); + boolean inQuote = false; + int count = 0; + char lastLetter = 0; + for (int i = 0; i < length; i++) { + char c = jrePattern.charAt(i); + if (c == '\'') { + // '' is treated as a single quote regardless of being + // in a quoted section. + if ((i + 1) < length) { + char nextc = jrePattern.charAt(i + 1); + if (nextc == '\'') { + i++; + if (count != 0) { + convert(calendarType, lastLetter, count, sb); + lastLetter = 0; + count = 0; + } + sb.append("''"); + continue; + } + } + if (!inQuote) { + if (count != 0) { + convert(calendarType, lastLetter, count, sb); + lastLetter = 0; + count = 0; + } + inQuote = true; + } else { + inQuote = false; + } + sb.append(c); + continue; + } + if (inQuote) { + sb.append(c); + continue; + } + if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) { + if (count != 0) { + convert(calendarType, lastLetter, count, sb); + lastLetter = 0; + count = 0; + } + sb.append(c); + continue; + } + if (lastLetter == 0 || lastLetter == c) { + lastLetter = c; + count++; + continue; + } + convert(calendarType, lastLetter, count, sb); + lastLetter = c; + count = 1; + } + if (inQuote) { + // should not come here. + // returning null so that FALLBACK provider will kick in. + return null; + } + if (count != 0) { + convert(calendarType, lastLetter, count, sb); + } + return sb.toString(); + } + + private void convert(String calendarType, char letter, int count, StringBuilder sb) { + switch (letter) { + case 'G': + if (calendarType.equals("japanese")) { + if (count >= 4) { + count = 1; + } else { + count = 5; + } + } else if (!calendarType.equals("iso8601")) { + // Adjust the number of 'G's + // Gregorian calendar is iso8601 for java.time + if (count >= 4) { + // JRE full -> JavaTime full + count = 4; + } else { + // JRE short -> JavaTime short + count = 1; + } + } + break; + case 'y': + if (calendarType.equals("japanese") && count >= 4) { + // JRE specific "gan-nen" support + count = 1; + } + break; + default: + // JSR 310 and CLDR define 5-letter patterns for narrow text. + if (count > 4) { + count = 4; + } + break; + } + appendN(letter, count, sb); + } + + private void appendN(char c, int n, StringBuilder sb) { + for (int i = 0; i < n; i++) { + sb.append(c); + } + } + }; + } private static String convertDateTimePattern(String winPattern) { String ret = winPattern.replaceAll("dddd", "EEEE");