145 } |
146 } |
146 |
147 |
147 return Locale.forLanguageTag(langTag); |
148 return Locale.forLanguageTag(langTag); |
148 } |
149 } |
149 |
150 |
|
151 public static JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() { |
|
152 return new JavaTimeDateTimePatternProvider() { |
|
153 @Override |
|
154 public Locale[] getAvailableLocales() { |
|
155 return getSupportedCalendarLocales(); |
|
156 } |
|
157 |
|
158 @Override |
|
159 public boolean isSupportedLocale(Locale locale) { |
|
160 return isSupportedCalendarLocale(locale); |
|
161 } |
|
162 |
|
163 @Override |
|
164 public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) { |
|
165 return toJavaTimeDateTimePattern(calType, getDateTimePattern(dateStyle, timeStyle, locale)); |
|
166 |
|
167 } |
|
168 |
|
169 private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) { |
|
170 AtomicReferenceArray<String> dateFormatPatterns; |
|
171 SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale); |
|
172 |
|
173 if (ref == null || (dateFormatPatterns = ref.get()) == null) { |
|
174 dateFormatPatterns = new AtomicReferenceArray<>(5 * 5); |
|
175 ref = new SoftReference<>(dateFormatPatterns); |
|
176 dateFormatPatternsMap.put(locale, ref); |
|
177 } |
|
178 int index = (dateStyle + 1) * 5 + timeStyle + 1; |
|
179 String pattern = dateFormatPatterns.get(index); |
|
180 if (pattern == null) { |
|
181 String langTag = locale.toLanguageTag(); |
|
182 pattern = translateDateFormatLetters(getCalendarID(langTag), |
|
183 getDateTimePatternNative(dateStyle, timeStyle, langTag)); |
|
184 if (!dateFormatPatterns.compareAndSet(index, null, pattern)) { |
|
185 pattern = dateFormatPatterns.get(index); |
|
186 } |
|
187 } |
|
188 return pattern; |
|
189 } |
|
190 |
|
191 /** |
|
192 * This method will convert JRE Date/time Pattern String to JSR310 |
|
193 * type Date/Time Pattern |
|
194 */ |
|
195 private String toJavaTimeDateTimePattern(String calendarType, String jrePattern) { |
|
196 int length = jrePattern.length(); |
|
197 StringBuilder sb = new StringBuilder(length); |
|
198 boolean inQuote = false; |
|
199 int count = 0; |
|
200 char lastLetter = 0; |
|
201 for (int i = 0; i < length; i++) { |
|
202 char c = jrePattern.charAt(i); |
|
203 if (c == '\'') { |
|
204 // '' is treated as a single quote regardless of being |
|
205 // in a quoted section. |
|
206 if ((i + 1) < length) { |
|
207 char nextc = jrePattern.charAt(i + 1); |
|
208 if (nextc == '\'') { |
|
209 i++; |
|
210 if (count != 0) { |
|
211 convert(calendarType, lastLetter, count, sb); |
|
212 lastLetter = 0; |
|
213 count = 0; |
|
214 } |
|
215 sb.append("''"); |
|
216 continue; |
|
217 } |
|
218 } |
|
219 if (!inQuote) { |
|
220 if (count != 0) { |
|
221 convert(calendarType, lastLetter, count, sb); |
|
222 lastLetter = 0; |
|
223 count = 0; |
|
224 } |
|
225 inQuote = true; |
|
226 } else { |
|
227 inQuote = false; |
|
228 } |
|
229 sb.append(c); |
|
230 continue; |
|
231 } |
|
232 if (inQuote) { |
|
233 sb.append(c); |
|
234 continue; |
|
235 } |
|
236 if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) { |
|
237 if (count != 0) { |
|
238 convert(calendarType, lastLetter, count, sb); |
|
239 lastLetter = 0; |
|
240 count = 0; |
|
241 } |
|
242 sb.append(c); |
|
243 continue; |
|
244 } |
|
245 if (lastLetter == 0 || lastLetter == c) { |
|
246 lastLetter = c; |
|
247 count++; |
|
248 continue; |
|
249 } |
|
250 convert(calendarType, lastLetter, count, sb); |
|
251 lastLetter = c; |
|
252 count = 1; |
|
253 } |
|
254 if (inQuote) { |
|
255 // should not come here. |
|
256 // returning null so that FALLBACK provider will kick in. |
|
257 return null; |
|
258 } |
|
259 if (count != 0) { |
|
260 convert(calendarType, lastLetter, count, sb); |
|
261 } |
|
262 return sb.toString(); |
|
263 } |
|
264 |
|
265 private void convert(String calendarType, char letter, int count, StringBuilder sb) { |
|
266 switch (letter) { |
|
267 case 'G': |
|
268 if (calendarType.equals("japanese")) { |
|
269 if (count >= 4) { |
|
270 count = 1; |
|
271 } else { |
|
272 count = 5; |
|
273 } |
|
274 } else if (!calendarType.equals("iso8601")) { |
|
275 // Gregorian calendar is iso8601 for java.time |
|
276 // Adjust the number of 'G's |
|
277 if (count >= 4) { |
|
278 // JRE full -> JavaTime full |
|
279 count = 4; |
|
280 } else { |
|
281 // JRE short -> JavaTime short |
|
282 count = 1; |
|
283 } |
|
284 } |
|
285 break; |
|
286 case 'y': |
|
287 if (calendarType.equals("japanese") && count >= 4) { |
|
288 // JRE specific "gan-nen" support |
|
289 count = 1; |
|
290 } |
|
291 break; |
|
292 default: |
|
293 // JSR 310 and CLDR define 5-letter patterns for narrow text. |
|
294 if (count > 4) { |
|
295 count = 4; |
|
296 } |
|
297 break; |
|
298 } |
|
299 appendN(letter, count, sb); |
|
300 } |
|
301 |
|
302 private void appendN(char c, int n, StringBuilder sb) { |
|
303 for (int i = 0; i < n; i++) { |
|
304 sb.append(c); |
|
305 } |
|
306 } |
|
307 }; |
|
308 } |
|
309 |
150 public static DateFormatProvider getDateFormatProvider() { |
310 public static DateFormatProvider getDateFormatProvider() { |
151 return new DateFormatProvider() { |
311 return new DateFormatProvider() { |
152 |
312 |
153 @Override |
313 @Override |
154 public Locale[] getAvailableLocales() { |
314 public Locale[] getAvailableLocales() { |
161 } |
321 } |
162 |
322 |
163 @Override |
323 @Override |
164 public DateFormat getDateInstance(int style, Locale locale) { |
324 public DateFormat getDateInstance(int style, Locale locale) { |
165 return new SimpleDateFormat(getDateTimePattern(style, -1, locale), |
325 return new SimpleDateFormat(getDateTimePattern(style, -1, locale), |
166 getCalendarLocale(locale)); |
326 getCalendarLocale(locale)); |
167 } |
327 } |
168 |
328 |
169 @Override |
329 @Override |
170 public DateFormat getTimeInstance(int style, Locale locale) { |
330 public DateFormat getTimeInstance(int style, Locale locale) { |
171 return new SimpleDateFormat(getDateTimePattern(-1, style, locale), |
331 return new SimpleDateFormat(getDateTimePattern(-1, style, locale), |
172 getCalendarLocale(locale)); |
332 getCalendarLocale(locale)); |
173 } |
333 } |
174 |
334 |
175 @Override |
335 @Override |
176 public DateFormat getDateTimeInstance(int dateStyle, |
336 public DateFormat getDateTimeInstance(int dateStyle, |
177 int timeStyle, Locale locale) { |
337 int timeStyle, Locale locale) { |
178 return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale), |
338 return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale), |
179 getCalendarLocale(locale)); |
339 getCalendarLocale(locale)); |
180 } |
340 } |
181 |
341 |
182 private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) { |
342 private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) { |
183 AtomicReferenceArray<String> dateFormatPatterns; |
343 AtomicReferenceArray<String> dateFormatPatterns; |
184 SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale); |
344 SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale); |