8075577: java.time does not support HOST provider
authorrgoel
Mon, 05 Dec 2016 12:53:53 +0530
changeset 42360 5e60b1e45041
parent 42359 e9e4835c9027
child 42361 b64a8f0c668e
child 42734 b9a2deda98ef
8075577: java.time does not support HOST provider Reviewed-by: okutsu, rriggs
jdk/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
jdk/src/java.base/share/classes/module-info.java
jdk/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java
jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java
jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
jdk/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java
jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
jdk/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
--- a/jdk/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Fri Dec 02 18:03:46 2016 -0800
+++ b/jdk/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Mon Dec 05 12:53:53 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,7 @@
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.TimeZoneNameProvider;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
@@ -147,6 +148,165 @@
         return Locale.forLanguageTag(langTag);
     }
 
+    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) {
+                return toJavaTimeDateTimePattern(calType, getDateTimePattern(dateStyle, timeStyle, locale));
+
+            }
+
+            private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
+                AtomicReferenceArray<String> dateFormatPatterns;
+                SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale);
+
+                if (ref == null || (dateFormatPatterns = ref.get()) == null) {
+                    dateFormatPatterns = new AtomicReferenceArray<>(5 * 5);
+                    ref = new SoftReference<>(dateFormatPatterns);
+                    dateFormatPatternsMap.put(locale, ref);
+                }
+                int index = (dateStyle + 1) * 5 + timeStyle + 1;
+                String pattern = dateFormatPatterns.get(index);
+                if (pattern == null) {
+                    String langTag = locale.toLanguageTag();
+                    pattern = translateDateFormatLetters(getCalendarID(langTag),
+                            getDateTimePatternNative(dateStyle, timeStyle, langTag));
+                    if (!dateFormatPatterns.compareAndSet(index, null, pattern)) {
+                        pattern = dateFormatPatterns.get(index);
+                    }
+                }
+                return pattern;
+            }
+
+            /**
+             * 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")) {
+                            // Gregorian calendar is iso8601 for java.time
+                            // Adjust the number of 'G's
+                            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);
+                }
+            }
+        };
+    }
+
     public static DateFormatProvider getDateFormatProvider() {
         return new DateFormatProvider() {
 
@@ -163,20 +323,20 @@
             @Override
             public DateFormat getDateInstance(int style, Locale locale) {
                 return new SimpleDateFormat(getDateTimePattern(style, -1, locale),
-                                            getCalendarLocale(locale));
+                        getCalendarLocale(locale));
             }
 
             @Override
             public DateFormat getTimeInstance(int style, Locale locale) {
                 return new SimpleDateFormat(getDateTimePattern(-1, style, locale),
-                                            getCalendarLocale(locale));
+                        getCalendarLocale(locale));
             }
 
             @Override
             public DateFormat getDateTimeInstance(int dateStyle,
                     int timeStyle, Locale locale) {
                 return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale),
-                                            getCalendarLocale(locale));
+                        getCalendarLocale(locale));
             }
 
             private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Fri Dec 02 18:03:46 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Mon Dec 05 12:53:53 2016 +0530
@@ -119,6 +119,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.locale.provider.LocaleProviderAdapter;
 import sun.util.locale.provider.LocaleResources;
 import sun.util.locale.provider.TimeZoneNameUtility;
@@ -212,9 +213,10 @@
         if (dateStyle == null && timeStyle == null) {
             throw new IllegalArgumentException("Either dateStyle or timeStyle must be non-null");
         }
-        LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale);
-        String pattern = lr.getJavaTimeDateTimePattern(
-                convertStyle(timeStyle), convertStyle(dateStyle), chrono.getCalendarType());
+        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, locale);
+        JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider();
+        String pattern = provider.getJavaTimeDateTimePattern(convertStyle(timeStyle),
+                         convertStyle(dateStyle), chrono.getCalendarType(), locale);
         return pattern;
     }
 
--- a/jdk/src/java.base/share/classes/module-info.java	Fri Dec 02 18:03:46 2016 -0800
+++ b/jdk/src/java.base/share/classes/module-info.java	Mon Dec 05 12:53:53 2016 +0530
@@ -305,6 +305,7 @@
     uses jdk.internal.logger.DefaultLoggerFinder;
     uses sun.security.ssl.ClientKeyExchangeService;
     uses sun.security.util.AuthResourcesProvider;
+    uses sun.text.spi.JavaTimeDateTimePatternProvider;
     uses sun.util.spi.CalendarProvider;
     uses sun.util.locale.provider.LocaleDataMetaInfo;
     uses sun.util.resources.LocaleData.CommonResourceBundleProvider;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java	Mon Dec 05 12:53:53 2016 +0530
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package sun.text.spi;
+
+import java.util.Locale;
+import java.util.spi.LocaleServiceProvider;
+
+/**
+ * Service Provider Interface for retrieving DateTime patterns from
+ * specified Locale provider for java.time.
+ */
+
+public abstract class JavaTimeDateTimePatternProvider extends LocaleServiceProvider {
+
+    protected JavaTimeDateTimePatternProvider() {
+    }
+
+    /**
+     * Gets the formatting pattern for a timeStyle
+     * dateStyle, calendarType and locale.
+     * Concrete implementation of this method will retrieve
+     * a java.time specific dateTime Pattern from selected Locale Provider.
+     *
+     * @param timeStyle an {@code int} value representing FormatStyle constant, -1
+     * for date-only pattern
+     * @param dateStyle an {@code int} value,representing FormatStyle constant, -1
+     * for time-only pattern
+     * @param locale {@code locale}, non-null
+     * @param calType a {@code String},non-null representing CalendarType such as "japanese",
+     * "iso8601"
+     * @return  formatting pattern {@code String}
+     * @see java.time.format.DateTimeFormatterBuilder#convertStyle(java.time.format.FormatStyle)
+     * @since 9
+     */
+    public abstract String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale);
+}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java	Fri Dec 02 18:03:46 2016 -0800
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java	Mon Dec 05 12:53:53 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.LocaleServiceProvider;
 import java.util.spi.TimeZoneNameProvider;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
@@ -156,6 +157,11 @@
         return null;
     }
 
+    @Override
+    public JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
+        return getLocaleServiceProvider(JavaTimeDateTimePatternProvider.class);
+    }
+
     private static Locale[] availableLocales = null;
 
     @Override
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Fri Dec 02 18:03:46 2016 -0800
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Mon Dec 05 12:53:53 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,7 @@
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.LocaleServiceProvider;
 import java.util.spi.TimeZoneNameProvider;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.resources.LocaleData;
 import sun.util.spi.CalendarProvider;
 
@@ -109,6 +110,8 @@
             return (P) getCalendarNameProvider();
         case "CalendarProvider":
             return (P) getCalendarProvider();
+        case "JavaTimeDateTimePatternProvider":
+            return (P) getJavaTimeDateTimePatternProvider();
         default:
             throw new InternalError("should not come down here");
         }
@@ -128,6 +131,7 @@
     private volatile CalendarNameProvider calendarNameProvider;
 
     private volatile CalendarProvider calendarProvider;
+    private volatile JavaTimeDateTimePatternProvider javaTimeDateTimePatternProvider;
 
     /*
      * Getter methods for java.text.spi.* providers
@@ -354,6 +358,27 @@
         return calendarProvider;
     }
 
+    /**
+     * Getter methods for sun.text.spi.JavaTimeDateTimePatternProvider provider
+     */
+    @Override
+    public JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
+        if (javaTimeDateTimePatternProvider == null) {
+            JavaTimeDateTimePatternProvider provider = AccessController.doPrivileged(
+                    (PrivilegedAction<JavaTimeDateTimePatternProvider>) ()
+                    -> new JavaTimeDateTimePatternImpl(
+                            getAdapterType(),
+                            getLanguageTagSet("FormatData")));
+
+            synchronized (this) {
+                if (javaTimeDateTimePatternProvider == null) {
+                    javaTimeDateTimePatternProvider = provider;
+                }
+            }
+        }
+        return javaTimeDateTimePatternProvider;
+    }
+
     @Override
     public LocaleResources getLocaleResources(Locale locale) {
         LocaleResources lr = localeResourcesMap.get(locale);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java	Mon Dec 05 12:53:53 2016 +0530
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.util.locale.provider;
+
+import java.util.Locale;
+import java.util.Set;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
+
+/**
+ * Concrete implementation of the {@link sun.text.spi.JavaTimeDateTimePatternProvider
+ * } class for the JRE LocaleProviderAdapter.
+ *
+ */
+public class JavaTimeDateTimePatternImpl extends JavaTimeDateTimePatternProvider implements AvailableLanguageTags {
+
+    private final LocaleProviderAdapter.Type type;
+    private final Set<String> langtags;
+
+    public JavaTimeDateTimePatternImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
+        this.type = type;
+        this.langtags = langtags;
+    }
+
+    /**
+     * Returns an array of all locales for which this locale service provider
+     * can provide localized objects or names.
+     *
+     * @return An array of all locales for which this locale service provider
+     * can provide localized objects or names.
+     */
+    @Override
+    public Locale[] getAvailableLocales() {
+        return LocaleProviderAdapter.toLocaleArray(langtags);
+    }
+
+    @Override
+    public boolean isSupportedLocale(Locale locale) {
+        return LocaleProviderAdapter.forType(type).isSupportedProviderLocale(locale, langtags);
+    }
+
+    @Override
+    public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) {
+        LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale);
+        String pattern = lr.getJavaTimeDateTimePattern(
+                timeStyle, dateStyle, calType);
+        return pattern;
+
+    }
+
+    @Override
+    public Set<String> getAvailableLanguageTags() {
+        return langtags;
+    }
+}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Fri Dec 02 18:03:46 2016 -0800
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Mon Dec 05 12:53:53 2016 +0530
@@ -47,6 +47,7 @@
 import java.util.spi.LocaleServiceProvider;
 import java.util.spi.TimeZoneNameProvider;
 import sun.security.action.GetPropertyAction;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
@@ -428,6 +429,14 @@
      */
     public abstract CalendarProvider getCalendarProvider();
 
+    /**
+     * Returns a JavaTimeDateTimePatternProvider for this LocaleProviderAdapter,
+     * or null if no JavaTimeDateTimePatternProvider is available.
+     *
+     * @return a JavaTimeDateTimePatternProvider
+     */
+    public abstract JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider();
+
     public abstract LocaleResources getLocaleResources(Locale locale);
 
     public abstract Locale[] getAvailableLocales();
--- a/jdk/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Fri Dec 02 18:03:46 2016 -0800
+++ b/jdk/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Mon Dec 05 12:53:53 2016 +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<String> 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<String> getDateTimePatterns(Locale locale) {
+                AtomicReferenceArray<String> patterns;
+                SoftReference<AtomicReferenceArray<String>> 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");