1 module hunt.time.format.LocalizedPrinterParser; 2 3 import hunt.time.chrono.Chronology; 4 import hunt.time.chrono.ChronoLocalDate; 5 import hunt.time.format.DateTimeFormatter; 6 import hunt.time.format.DateTimeFormatterBuilder; 7 import hunt.time.format.DateTimeParseContext; 8 import hunt.time.format.DateTimePrinterParser; 9 import hunt.time.format.DateTimePrintContext; 10 import hunt.time.format.FormatStyle; 11 import hunt.time.temporal.TemporalField; 12 import hunt.time.util.Common; 13 // import hunt.time.util.Locale; 14 import hunt.util.StringBuilder; 15 16 import hunt.collection.HashMap; 17 import hunt.collection.Map; 18 import hunt.Exceptions; 19 import hunt.util.Locale; 20 21 import std.concurrency : initOnce; 22 23 //----------------------------------------------------------------------- 24 /** 25 * Prints or parses a localized pattern. 26 */ 27 final class LocalizedPrinterParser : DateTimePrinterParser 28 { 29 /** Cache of formatters. */ 30 static Map!(string, DateTimeFormatter) FORMATTER_CACHE() { 31 __gshared Map!(string, DateTimeFormatter) inst; 32 return initOnce!(inst)( 33 new HashMap!(string, DateTimeFormatter)(16, 0.75f /* , 2 */ )); 34 } 35 36 private FormatStyle dateStyle; 37 private FormatStyle timeStyle; 38 39 /** 40 * Constructor. 41 * 42 * @param dateStyle the date style to use, may be null 43 * @param timeStyle the time style to use, may be null 44 */ 45 this(FormatStyle dateStyle, FormatStyle timeStyle) 46 { 47 // validated by caller 48 this.dateStyle = dateStyle; 49 this.timeStyle = timeStyle; 50 } 51 52 override bool format(DateTimePrintContext context, StringBuilder buf) 53 { 54 Chronology chrono = Chronology.from(context.getTemporal()); 55 return formatter(context.getLocale(), chrono).toPrinterParser(false) 56 .format(context, buf); 57 } 58 59 override int parse(DateTimeParseContext context, string text, int position) 60 { 61 Chronology chrono = context.getEffectiveChronology(); 62 return formatter(context.getLocale(), chrono).toPrinterParser(false) 63 .parse(context, text, position); 64 } 65 66 /** 67 * Gets the formatter to use. 68 * !(p) 69 * The formatter will be the most appropriate to use for the date and time style _in the locale. 70 * For example, some locales will use the month name while others will use the number. 71 * 72 * @param locale the locale to use, not null 73 * @param chrono the chronology to use, not null 74 * @return the formatter, not null 75 * @throws IllegalArgumentException if the formatter cannot be found 76 */ 77 private DateTimeFormatter formatter(Locale locale, Chronology chrono) 78 { 79 string key = chrono.getId() ~ '|' ~ locale.toString() ~ '|' ~ dateStyle.name() ~ timeStyle.name(); 80 DateTimeFormatter formatter = FORMATTER_CACHE.get(key); 81 if (formatter is null) { 82 string pattern = getLocalizedDateTimePattern(dateStyle, 83 timeStyle, chrono, locale); 84 formatter = new DateTimeFormatterBuilder().appendPattern(pattern) 85 .toFormatter(locale); 86 DateTimeFormatter old = FORMATTER_CACHE.putIfAbsent(key, formatter); 87 if (old !is null) { 88 formatter = old; 89 } 90 } 91 return formatter; 92 // implementationMissing(false); 93 // return null; 94 } 95 96 97 /** 98 * Gets the formatting pattern for date and time styles for a locale and chronology. 99 * The locale and chronology are used to lookup the locale specific format 100 * for the requested dateStyle and/or timeStyle. 101 * !(p) 102 * If the locale contains the "rg" (region override) 103 * <a href="../../util/Locale.html#def_locale_extension">Unicode extensions</a>, 104 * the formatting pattern is overridden with the one appropriate for the region. 105 * 106 * @param dateStyle the FormatStyle for the date, null for time-only pattern 107 * @param timeStyle the FormatStyle for the time, null for date-only pattern 108 * @param chrono the Chronology, non-null 109 * @param locale the locale, non-null 110 * @return the locale and Chronology specific formatting pattern 111 * @throws IllegalArgumentException if both dateStyle and timeStyle are null 112 */ 113 static string getLocalizedDateTimePattern(FormatStyle dateStyle, 114 FormatStyle timeStyle, Chronology chrono, Locale locale) { 115 // assert(locale, "locale"); 116 // assert(chrono, "chrono"); 117 // if (dateStyle is null && timeStyle is null) { 118 // throw new IllegalArgumentException("Either dateStyle or timeStyle must be non-null"); 119 // } 120 // LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, locale); 121 // JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider(); 122 // string pattern = provider.getJavaTimeDateTimePattern(convertStyle(timeStyle), 123 // convertStyle(dateStyle), chrono.getCalendarType(), 124 // CalendarDataUtility.findRegionOverride(locale)); 125 // return pattern; 126 implementationMissing(false); 127 return null; 128 } 129 130 override string toString() 131 { 132 return "Localized(" ~ (dateStyle !is null ? dateStyle.name() 133 : "") ~ "," ~ (timeStyle !is null ? timeStyle.name() : "") ~ ")"; 134 } 135 }