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 }