1 module hunt.time.format.ChronoPrinterParser; 2 3 import hunt.time.chrono.Chronology; 4 5 import hunt.time.format.DateTimeParseContext; 6 import hunt.time.format.DateTimePrinterParser; 7 import hunt.time.format.DateTimePrintContext; 8 import hunt.time.format.DateTimeTextProvider; 9 import hunt.time.format.TextStyle; 10 import hunt.time.temporal.TemporalField; 11 import hunt.time.temporal.TemporalQueries; 12 13 import hunt.collection.Set; 14 import hunt.util.StringBuilder; 15 import hunt.Exceptions; 16 import hunt.util.Locale; 17 18 //----------------------------------------------------------------------- 19 /** 20 * Prints or parses a chronology. 21 */ 22 static final class ChronoPrinterParser : DateTimePrinterParser 23 { 24 /** The text style to output, null means the ID. */ 25 private TextStyle textStyle; 26 27 this(TextStyle textStyle) 28 { 29 // validated by caller 30 this.textStyle = textStyle; 31 } 32 33 override public bool format(DateTimePrintContext context, StringBuilder buf) 34 { 35 Chronology chrono = context.getValue(TemporalQueries.chronology()); 36 if (chrono is null) 37 { 38 return false; 39 } 40 if (textStyle is null) 41 { 42 buf.append(chrono.getId()); 43 } 44 else 45 { 46 buf.append(getChronologyName(chrono, context.getLocale())); 47 } 48 return true; 49 } 50 51 override public int parse(DateTimeParseContext context, string text, int position) 52 { 53 // simple looping parser to find the chronology 54 if (position < 0 || position > text.length) 55 { 56 throw new IndexOutOfBoundsException(); 57 } 58 Set!(Chronology) chronos = Chronology.getAvailableChronologies(); 59 Chronology bestMatch = null; 60 int matchLen = -1; 61 foreach (Chronology chrono; chronos) 62 { 63 string name; 64 if (textStyle is null) 65 { 66 name = chrono.getId(); 67 } 68 else 69 { 70 name = getChronologyName(chrono, context.getLocale()); 71 } 72 int nameLen = cast(int)(name.length); 73 if (nameLen > matchLen && context.subSequenceEquals(text, 74 position, name, 0, nameLen)) 75 { 76 bestMatch = chrono; 77 matchLen = nameLen; 78 } 79 } 80 if (bestMatch is null) 81 { 82 return ~position; 83 } 84 context.setParsed(bestMatch); 85 return position + matchLen; 86 } 87 88 /** 89 * Returns the chronology name of the given chrono _in the given locale 90 * if available, or the chronology Id otherwise. The regular ResourceBundle 91 * search path is used for looking up the chronology name. 92 * 93 * @param chrono the chronology, not null 94 * @param locale the locale, not null 95 * @return the chronology name of chrono _in locale, or the id if no name is available 96 * @throws NullPointerException if chrono or locale is null 97 */ 98 private string getChronologyName(Chronology chrono, Locale locale) 99 { 100 string key = "calendarname." ~ chrono.getCalendarType(); 101 string name = DateTimeTextProvider.getLocalizedResource!string(key, locale); 102 return name /* , () => chrono.getId()) */ ; 103 } 104 105 override public string toString() 106 { 107 return super.toString(); 108 } 109 } 110