1 module hunt.time.format.DateTimePrinterParser;
2 
3 import hunt.time.format.DateTimeParseContext;
4 import hunt.time.format.DateTimePrintContext;
5 import hunt.time.temporal.TemporalField;
6 import hunt.util.StringBuilder;
7 
8 //-----------------------------------------------------------------------
9 /**
10  * Strategy for formatting/parsing date-time information.
11  * !(p)
12  * The printer may format any part, or the whole, of the input date-time object.
13  * Typically, a complete format is constructed from a number of smaller
14  * units, each outputting a single field.
15  * !(p)
16  * The parser may parse any piece of text from the input, storing the result
17  * _in the context. Typically, each individual parser will just parse one
18  * field, such as the day-of-month, storing the value _in the context.
19  * Once the parse is complete, the caller will then resolve the parsed values
20  * to create the desired object, such as a {@code LocalDate}.
21  * !(p)
22  * The parse position will be updated during the parse. Parsing will start at
23  * the specified index and the return value specifies the new parse position
24  * for the next parser. If an error occurs, the returned index will be negative
25  * and will have the error position encoded using the complement operator.
26  *
27  * @implSpec
28  * This interface must be implemented with care to ensure other classes operate correctly.
29  * All implementations that can be instantiated must be final, immutable and thread-safe.
30  * !(p)
31  * The context is not a thread-safe object and a new instance will be created
32  * for each format that occurs. The context must not be stored _in an instance
33  * variable or shared with any other threads.
34  */
35 interface DateTimePrinterParser
36 {
37 
38     /**
39      * Prints the date-time object to the buffer.
40      * !(p)
41      * The context holds information to use during the format.
42      * It also contains the date-time information to be printed.
43      * !(p)
44      * The buffer must not be mutated beyond the content controlled by the implementation.
45      *
46      * @param context  the context to format using, not null
47      * @param buf  the buffer to append to, not null
48      * @return false if unable to query the value from the date-time, true otherwise
49      * @throws DateTimeException if the date-time cannot be printed successfully
50      */
51     bool format(DateTimePrintContext context, StringBuilder buf);
52 
53     /**
54      * Parses text into date-time information.
55      * !(p)
56      * The context holds information to use during the parse.
57      * It is also used to store the parsed date-time information.
58      *
59      * @param context  the context to use and parse into, not null
60      * @param text  the input text to parse, not null
61      * @param position  the position to start parsing at, from 0 to the text length
62      * @return the new parse position, where negative means an error with the
63      *  error position encoded using the complement ~ operator
64      * @throws NullPointerException if the context or text is null
65      * @throws IndexOutOfBoundsException if the position is invalid
66      */
67     int parse(DateTimeParseContext context, string text, int position);
68 
69     string toString();
70 }
71 
72 
73 //-----------------------------------------------------------------------
74 /**
75  * Defaults a value into the parse if not currently present.
76  */
77 static class DefaultValueParser : DateTimePrinterParser
78 {
79     private TemporalField field;
80     private long value;
81 
82     this(TemporalField field, long value)
83     {
84         this.field = field;
85         this.value = value;
86     }
87 
88     public bool format(DateTimePrintContext context, StringBuilder buf)
89     {
90         return true;
91     }
92 
93     public int parse(DateTimeParseContext context, string text, int position)
94     {
95         if (context.getParsed(field) is null)
96         {
97             context.setParsedField(field, value, position, position);
98         }
99         return position;
100     }
101 
102     override public string toString()
103     {
104         return super.toString();
105     }
106 }