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