22
22
import java .util .List ;
23
23
import java .util .Locale ;
24
24
import java .util .Objects ;
25
- import java .util .function .Consumer ;
25
+ import java .util .function .BiConsumer ;
26
26
import java .util .function .UnaryOperator ;
27
27
28
28
class JavaDateFormatter implements DateFormatter {
29
+ /**
30
+ * A default consumer that allows to round up fields (used for range searches, optional fields missing)
31
+ * it relies on toString implementation of DateTimeFormatter and ChronoField.
32
+ * For instance for pattern
33
+ * the parser would have a toString()
34
+ * <code>
35
+ * Value(MonthOfYear,2)'/'Value(DayOfMonth,2)'/'Value(YearOfEra,4,19,EXCEEDS_PAD)'
36
+ * 'Value(ClockHourOfAmPm,2)':'Value(MinuteOfHour,2)' 'Text(AmPmOfDay,SHORT)
37
+ * </code>
38
+ * and ChronoField.CLOCK_HOUR_OF_AMPM would have toString() ClockHourOfAmPm
39
+ * this allows the rounding logic to default CLOCK_HOUR_OF_AMPM field instead of HOUR_OF_DAY
40
+ * without this logic, the rounding would result in a conflict as HOUR_OF_DAY would be missing, but CLOCK_HOUR_OF_AMPM would be provided
41
+ */
42
+ private static final BiConsumer <DateTimeFormatterBuilder , DateTimeFormatter > DEFAULT_ROUND_UP = (builder , parser ) -> {
43
+ if (parser .toString ().contains (ChronoField .DAY_OF_YEAR .toString ())) {
44
+ builder .parseDefaulting (ChronoField .DAY_OF_YEAR , 1L );
45
+ } else {
46
+ builder .parseDefaulting (ChronoField .MONTH_OF_YEAR , 1L );
47
+ builder .parseDefaulting (ChronoField .DAY_OF_MONTH , 1L );
48
+ }
49
+ if (parser .toString ().contains (ChronoField .CLOCK_HOUR_OF_AMPM .toString ())) {
50
+ builder .parseDefaulting (ChronoField .CLOCK_HOUR_OF_AMPM , 11L );
51
+ builder .parseDefaulting (ChronoField .AMPM_OF_DAY , 1L );
52
+ } else if (parser .toString ().contains (ChronoField .HOUR_OF_AMPM .toString ())) {
53
+ builder .parseDefaulting (ChronoField .HOUR_OF_AMPM , 11L );
54
+ builder .parseDefaulting (ChronoField .AMPM_OF_DAY , 1L );
55
+ } else {
56
+ builder .parseDefaulting (ChronoField .HOUR_OF_DAY , 23L );
57
+ }
58
+ builder .parseDefaulting (ChronoField .MINUTE_OF_HOUR , 59L );
59
+ builder .parseDefaulting (ChronoField .SECOND_OF_MINUTE , 59L );
60
+ builder .parseDefaulting (ChronoField .NANO_OF_SECOND , 999_999_999L );
61
+ };
29
62
30
63
private final String format ;
31
64
private final DateTimeFormatter printer ;
@@ -50,12 +83,7 @@ JavaDateFormatter getRoundupParser() {
50
83
format ,
51
84
printer ,
52
85
// set up base fields which should be used for default parsing, when we round up for date math
53
- builder -> builder .parseDefaulting (ChronoField .MONTH_OF_YEAR , 1L )
54
- .parseDefaulting (ChronoField .DAY_OF_MONTH , 1L )
55
- .parseDefaulting (ChronoField .HOUR_OF_DAY , 23L )
56
- .parseDefaulting (ChronoField .MINUTE_OF_HOUR , 59L )
57
- .parseDefaulting (ChronoField .SECOND_OF_MINUTE , 59L )
58
- .parseDefaulting (ChronoField .NANO_OF_SECOND , 999_999_999L ),
86
+ DEFAULT_ROUND_UP ,
59
87
parsers
60
88
);
61
89
}
@@ -64,7 +92,7 @@ JavaDateFormatter getRoundupParser() {
64
92
JavaDateFormatter (
65
93
String format ,
66
94
DateTimeFormatter printer ,
67
- Consumer <DateTimeFormatterBuilder > roundupParserConsumer ,
95
+ BiConsumer <DateTimeFormatterBuilder , DateTimeFormatter > roundupParserConsumer ,
68
96
DateTimeFormatter ... parsers
69
97
) {
70
98
if (printer == null ) {
@@ -105,15 +133,15 @@ private static DateTimeFormatter[] parsersArray(DateTimeFormatter printer, DateT
105
133
*/
106
134
private static RoundUpFormatter createRoundUpParser (
107
135
String format ,
108
- Consumer <DateTimeFormatterBuilder > roundupParserConsumer ,
136
+ BiConsumer <DateTimeFormatterBuilder , DateTimeFormatter > roundupParserConsumer ,
109
137
Locale locale ,
110
138
DateTimeFormatter [] parsers
111
139
) {
112
140
if (format .contains ("||" ) == false ) {
113
141
return new RoundUpFormatter (format , mapParsers (parser -> {
114
142
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder ();
115
143
builder .append (parser );
116
- roundupParserConsumer .accept (builder );
144
+ roundupParserConsumer .accept (builder , parser );
117
145
return builder .toFormatter (locale );
118
146
}, parsers ));
119
147
}
0 commit comments