1 /*
2  * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * This file is available under and governed by the GNU General Public
26  * License version 2 only, as published by the Free Software Foundation.
27  * However, the following notice accompanied the original version of this
28  * file:
29  *
30  * Copyright (c) 2008-2013, Stephen Colebourne & Michael Nascimento Santos
31  *
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions are met:
36  *
37  *  * Redistributions of source code must retain the above copyright notice,
38  *    this list of conditions and the following disclaimer.
39  *
40  *  * Redistributions in binary form must reproduce the above copyright notice,
41  *    this list of conditions and the following disclaimer in the documentation
42  *    and/or other materials provided with the distribution.
43  *
44  *  * Neither the name of JSR-310 nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
51  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
52  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
53  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
56  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59  */
60 package tck.java.time.format;
61 
62 import static java.time.format.ResolverStyle.LENIENT;
63 import static java.time.format.ResolverStyle.SMART;
64 import static java.time.format.ResolverStyle.STRICT;
65 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
66 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
67 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
68 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
69 import static java.time.temporal.ChronoField.AMPM_OF_DAY;
70 import static java.time.temporal.ChronoField.CLOCK_HOUR_OF_AMPM;
71 import static java.time.temporal.ChronoField.CLOCK_HOUR_OF_DAY;
72 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
73 import static java.time.temporal.ChronoField.DAY_OF_WEEK;
74 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
75 import static java.time.temporal.ChronoField.EPOCH_DAY;
76 import static java.time.temporal.ChronoField.ERA;
77 import static java.time.temporal.ChronoField.HOUR_OF_AMPM;
78 import static java.time.temporal.ChronoField.HOUR_OF_DAY;
79 import static java.time.temporal.ChronoField.INSTANT_SECONDS;
80 import static java.time.temporal.ChronoField.MICRO_OF_DAY;
81 import static java.time.temporal.ChronoField.MICRO_OF_SECOND;
82 import static java.time.temporal.ChronoField.MILLI_OF_DAY;
83 import static java.time.temporal.ChronoField.MILLI_OF_SECOND;
84 import static java.time.temporal.ChronoField.MINUTE_OF_DAY;
85 import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
86 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
87 import static java.time.temporal.ChronoField.NANO_OF_DAY;
88 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
89 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
90 import static java.time.temporal.ChronoField.SECOND_OF_DAY;
91 import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
92 import static java.time.temporal.ChronoField.YEAR;
93 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
94 import static org.testng.Assert.assertEquals;
95 import static org.testng.Assert.fail;
96 
97 import libcore.test.annotation.NonCts;
98 import libcore.test.reasons.NonCtsReasons;
99 
100 import java.time.Instant;
101 import java.time.LocalDate;
102 import java.time.LocalDateTime;
103 import java.time.LocalTime;
104 import java.time.Period;
105 import java.time.ZoneId;
106 import java.time.ZoneOffset;
107 import java.time.ZonedDateTime;
108 import java.time.chrono.ChronoLocalDate;
109 import java.time.chrono.ChronoLocalDateTime;
110 import java.time.chrono.ChronoZonedDateTime;
111 import java.time.chrono.IsoChronology;
112 import java.time.chrono.MinguoChronology;
113 import java.time.chrono.MinguoDate;
114 import java.time.chrono.ThaiBuddhistChronology;
115 import java.time.format.DateTimeFormatter;
116 import java.time.format.DateTimeFormatterBuilder;
117 import java.time.format.DateTimeParseException;
118 import java.time.format.ResolverStyle;
119 import java.time.temporal.IsoFields;
120 import java.time.temporal.Temporal;
121 import java.time.temporal.TemporalAccessor;
122 import java.time.temporal.TemporalField;
123 import java.time.temporal.TemporalQueries;
124 import java.time.temporal.TemporalUnit;
125 import java.time.temporal.ValueRange;
126 import java.util.Map;
127 
128 import org.testng.annotations.DataProvider;
129 import org.testng.annotations.Test;
130 
131 /**
132  * Test parse resolving.
133  */
134 @Test
135 public class TCKDateTimeParseResolver {
136     // TODO: tests with weird TenporalField implementations
137     // TODO: tests with non-ISO chronologies
138 
139     private static final ZoneId EUROPE_ATHENS = ZoneId.of("Europe/Athens");
140     private static final ZoneId EUROPE_PARIS = ZoneId.of("Europe/Paris");
141 
142     //-----------------------------------------------------------------------
143     @DataProvider(name="resolveOneNoChange")
data_resolveOneNoChange()144     Object[][] data_resolveOneNoChange() {
145         return new Object[][]{
146                 {YEAR, 2012},
147                 {MONTH_OF_YEAR, 8},
148                 {DAY_OF_MONTH, 7},
149                 {DAY_OF_YEAR, 6},
150                 {DAY_OF_WEEK, 5},
151         };
152     }
153 
154     @Test(dataProvider="resolveOneNoChange")
test_resolveOneNoChange(TemporalField field1, long value1)155     public void test_resolveOneNoChange(TemporalField field1, long value1) {
156         String str = Long.toString(value1);
157         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field1).toFormatter();
158 
159         TemporalAccessor accessor = f.parse(str);
160         assertEquals(accessor.query(TemporalQueries.localDate()), null);
161         assertEquals(accessor.query(TemporalQueries.localTime()), null);
162         assertEquals(accessor.isSupported(field1), true);
163         assertEquals(accessor.getLong(field1), value1);
164     }
165 
166     //-----------------------------------------------------------------------
167     @DataProvider(name="resolveTwoNoChange")
data_resolveTwoNoChange()168     Object[][] data_resolveTwoNoChange() {
169         return new Object[][]{
170                 {YEAR, 2012, MONTH_OF_YEAR, 5},
171                 {YEAR, 2012, DAY_OF_MONTH, 5},
172                 {YEAR, 2012, DAY_OF_WEEK, 5},
173                 {YEAR, 2012, ALIGNED_WEEK_OF_YEAR, 5},
174                 {YEAR, 2012, ALIGNED_WEEK_OF_MONTH, 5},
175                 {YEAR, 2012, IsoFields.QUARTER_OF_YEAR, 3},
176                 {YEAR, 2012, MINUTE_OF_HOUR, 5},
177                 {YEAR, 2012, SECOND_OF_MINUTE, 5},
178                 {YEAR, 2012, NANO_OF_SECOND, 5},
179 
180                 {MONTH_OF_YEAR, 5, DAY_OF_MONTH, 5},
181                 {MONTH_OF_YEAR, 5, DAY_OF_WEEK, 5},
182                 {MONTH_OF_YEAR, 5, ALIGNED_WEEK_OF_YEAR, 5},
183                 {MONTH_OF_YEAR, 5, ALIGNED_WEEK_OF_MONTH, 5},
184                 {MONTH_OF_YEAR, 3, IsoFields.QUARTER_OF_YEAR, 5},
185                 {MONTH_OF_YEAR, 5, MINUTE_OF_HOUR, 5},
186                 {MONTH_OF_YEAR, 5, SECOND_OF_MINUTE, 5},
187                 {MONTH_OF_YEAR, 5, NANO_OF_SECOND, 5},
188         };
189     }
190 
191     @Test(dataProvider="resolveTwoNoChange")
test_resolveTwoNoChange(TemporalField field1, long value1, TemporalField field2, long value2)192     public void test_resolveTwoNoChange(TemporalField field1, long value1, TemporalField field2, long value2) {
193         String str = value1 + " " + value2;
194         DateTimeFormatter f = new DateTimeFormatterBuilder()
195                 .appendValue(field1).appendLiteral(' ')
196                 .appendValue(field2).toFormatter();
197         TemporalAccessor accessor = f.parse(str);
198 
199         assertEquals(accessor.query(TemporalQueries.localDate()), null);
200         assertEquals(accessor.query(TemporalQueries.localTime()), null);
201         assertEquals(accessor.isSupported(field1), true);
202         assertEquals(accessor.isSupported(field2), true);
203         assertEquals(accessor.getLong(field1), value1);
204         assertEquals(accessor.getLong(field2), value2);
205     }
206 
207     //-----------------------------------------------------------------------
208     @DataProvider(name="resolveThreeNoChange")
data_resolveThreeNoChange()209     Object[][] data_resolveThreeNoChange() {
210         return new Object[][]{
211                 {YEAR, 2012, MONTH_OF_YEAR, 5, DAY_OF_WEEK, 5},
212                 {YEAR, 2012, ALIGNED_WEEK_OF_YEAR, 5, DAY_OF_MONTH, 5},
213                 {YEAR, 2012, ALIGNED_WEEK_OF_MONTH, 5, DAY_OF_MONTH, 5},
214                 {YEAR, 2012, MONTH_OF_YEAR, 5, DAY_OF_WEEK, 5},
215                 {ERA, 1, MONTH_OF_YEAR, 5, DAY_OF_MONTH, 5},
216                 {MONTH_OF_YEAR, 1, DAY_OF_MONTH, 5, IsoFields.QUARTER_OF_YEAR, 3},
217                 {HOUR_OF_DAY, 1, SECOND_OF_MINUTE, 5, NANO_OF_SECOND, 5},
218                 {MINUTE_OF_HOUR, 1, SECOND_OF_MINUTE, 5, NANO_OF_SECOND, 5},
219         };
220     }
221 
222     @Test(dataProvider="resolveThreeNoChange")
test_resolveThreeNoChange(TemporalField field1, long value1, TemporalField field2, long value2, TemporalField field3, long value3)223     public void test_resolveThreeNoChange(TemporalField field1, long value1, TemporalField field2, long value2, TemporalField field3, long value3) {
224         String str = value1 + " " + value2 + " " + value3;
225         DateTimeFormatter f = new DateTimeFormatterBuilder()
226                 .appendValue(field1).appendLiteral(' ')
227                 .appendValue(field2).appendLiteral(' ')
228                 .appendValue(field3).toFormatter();
229         TemporalAccessor accessor = f.parse(str);
230 
231         assertEquals(accessor.query(TemporalQueries.localDate()), null);
232         assertEquals(accessor.query(TemporalQueries.localTime()), null);
233         assertEquals(accessor.isSupported(field1), true);
234         assertEquals(accessor.isSupported(field2), true);
235         assertEquals(accessor.isSupported(field3), true);
236         assertEquals(accessor.getLong(field1), value1);
237         assertEquals(accessor.getLong(field2), value2);
238         assertEquals(accessor.getLong(field3), value3);
239     }
240 
241     //-----------------------------------------------------------------------
242     //-----------------------------------------------------------------------
243     //-----------------------------------------------------------------------
244     @DataProvider(name="resolveOneToField")
data_resolveOneToField()245     Object[][] data_resolveOneToField() {
246         return new Object[][]{
247                 {YEAR_OF_ERA, 2012, YEAR, 2012L, null, null},
248                 {PROLEPTIC_MONTH, 2012 * 12L + (3 - 1), YEAR, 2012L, MONTH_OF_YEAR, 3L},
249 
250                 {CLOCK_HOUR_OF_AMPM, 8, HOUR_OF_AMPM, 8L, null, null},
251                 {CLOCK_HOUR_OF_AMPM, 12, HOUR_OF_AMPM, 0L, null, null},
252                 {MICRO_OF_SECOND, 12, NANO_OF_SECOND, 12_000L, null, null},
253                 {MILLI_OF_SECOND, 12, NANO_OF_SECOND, 12_000_000L, null, null},
254         };
255     }
256 
257     @Test(dataProvider="resolveOneToField")
test_resolveOneToField(TemporalField field1, long value1, TemporalField expectedField1, Long expectedValue1, TemporalField expectedField2, Long expectedValue2)258     public void test_resolveOneToField(TemporalField field1, long value1,
259                                        TemporalField expectedField1, Long expectedValue1,
260                                        TemporalField expectedField2, Long expectedValue2) {
261         String str = Long.toString(value1);
262         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field1).toFormatter();
263 
264         TemporalAccessor accessor = f.parse(str);
265         assertEquals(accessor.query(TemporalQueries.localDate()), null);
266         assertEquals(accessor.query(TemporalQueries.localTime()), null);
267         if (expectedField1 != null) {
268             assertEquals(accessor.isSupported(expectedField1), true);
269             assertEquals(accessor.getLong(expectedField1), expectedValue1.longValue());
270         }
271         if (expectedField2 != null) {
272             assertEquals(accessor.isSupported(expectedField2), true);
273             assertEquals(accessor.getLong(expectedField2), expectedValue2.longValue());
274         }
275     }
276 
277     //-----------------------------------------------------------------------
278     @DataProvider(name="resolveOneToDate")
data_resolveOneToDate()279     Object[][] data_resolveOneToDate() {
280         return new Object[][]{
281                 {EPOCH_DAY, 32, LocalDate.of(1970, 2, 2)},
282         };
283     }
284 
285     @Test(dataProvider="resolveOneToDate")
test_resolveOneToDate(TemporalField field1, long value1, LocalDate expectedDate)286     public void test_resolveOneToDate(TemporalField field1, long value1, LocalDate expectedDate) {
287         String str = Long.toString(value1);
288         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field1).toFormatter();
289 
290         TemporalAccessor accessor = f.parse(str);
291         assertEquals(accessor.query(TemporalQueries.localDate()), expectedDate);
292         assertEquals(accessor.query(TemporalQueries.localTime()), null);
293     }
294 
295     //-----------------------------------------------------------------------
296     @DataProvider(name="resolveOneToTime")
data_resolveOneToTime()297     Object[][] data_resolveOneToTime() {
298         return new Object[][]{
299                 {HOUR_OF_DAY, 8, LocalTime.of(8, 0)},
300                 {CLOCK_HOUR_OF_DAY, 8, LocalTime.of(8, 0)},
301                 {CLOCK_HOUR_OF_DAY, 24, LocalTime.of(0, 0)},
302                 {MINUTE_OF_DAY, 650, LocalTime.of(10, 50)},
303                 {SECOND_OF_DAY, 3600 + 650, LocalTime.of(1, 10, 50)},
304                 {MILLI_OF_DAY, (3600 + 650) * 1_000L + 2, LocalTime.of(1, 10, 50, 2_000_000)},
305                 {MICRO_OF_DAY, (3600 + 650) * 1_000_000L + 2, LocalTime.of(1, 10, 50, 2_000)},
306                 {NANO_OF_DAY, (3600 + 650) * 1_000_000_000L + 2, LocalTime.of(1, 10, 50, 2)},
307         };
308     }
309 
310     @Test(dataProvider="resolveOneToTime")
test_resolveOneToTime(TemporalField field1, long value1, LocalTime expectedTime)311     public void test_resolveOneToTime(TemporalField field1, long value1, LocalTime expectedTime) {
312         String str = Long.toString(value1);
313         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field1).toFormatter();
314 
315         TemporalAccessor accessor = f.parse(str);
316         assertEquals(accessor.query(TemporalQueries.localDate()), null);
317         assertEquals(accessor.query(TemporalQueries.localTime()), expectedTime);
318     }
319 
320     //-----------------------------------------------------------------------
321     //-----------------------------------------------------------------------
322     //-----------------------------------------------------------------------
323     @DataProvider(name="resolveTwoToField")
data_resolveTwoToField()324     Object[][] data_resolveTwoToField() {
325         return new Object[][]{
326                 // cross-check
327                 {PROLEPTIC_MONTH, 2012 * 12L + (3 - 1), YEAR, 2012, YEAR, 2012L, MONTH_OF_YEAR, 3L},
328                 {PROLEPTIC_MONTH, 2012 * 12L + (3 - 1), YEAR_OF_ERA, 2012, YEAR, 2012L, MONTH_OF_YEAR, 3L},
329                 {PROLEPTIC_MONTH, 2012 * 12L + (3 - 1), ERA, 1, YEAR, 2012L, MONTH_OF_YEAR, 3L},
330                 {PROLEPTIC_MONTH, (3 - 1), YEAR, 0, YEAR, 0L, MONTH_OF_YEAR, 3L},
331                 {PROLEPTIC_MONTH, (3 - 1), YEAR_OF_ERA, 1, YEAR, 0L, MONTH_OF_YEAR, 3L},
332                 {PROLEPTIC_MONTH, (3 - 1), ERA, 0, YEAR, 0L, MONTH_OF_YEAR, 3L},
333         };
334     }
335 
336     @Test(dataProvider="resolveTwoToField")
test_resolveTwoToField(TemporalField field1, long value1, TemporalField field2, long value2, TemporalField expectedField1, Long expectedValue1, TemporalField expectedField2, Long expectedValue2)337     public void test_resolveTwoToField(TemporalField field1, long value1,
338                                        TemporalField field2, long value2,
339                                        TemporalField expectedField1, Long expectedValue1,
340                                        TemporalField expectedField2, Long expectedValue2) {
341         String str = value1 + " " + value2;
342         DateTimeFormatter f = new DateTimeFormatterBuilder()
343                 .appendValue(field1).appendLiteral(' ')
344                 .appendValue(field2).toFormatter();
345 
346         TemporalAccessor accessor = f.parse(str);
347         assertEquals(accessor.query(TemporalQueries.localDate()), null);
348         assertEquals(accessor.query(TemporalQueries.localTime()), null);
349         if (expectedField1 != null) {
350             assertEquals(accessor.isSupported(expectedField1), true);
351             assertEquals(accessor.getLong(expectedField1), expectedValue1.longValue());
352         }
353         if (expectedField2 != null) {
354             assertEquals(accessor.isSupported(expectedField2), true);
355             assertEquals(accessor.getLong(expectedField2), expectedValue2.longValue());
356         }
357     }
358 
359     //-----------------------------------------------------------------------
360     @DataProvider(name="resolveTwoToDate")
data_resolveTwoToDate()361     Object[][] data_resolveTwoToDate() {
362         return new Object[][]{
363                 // merge
364                 {YEAR, 2012, DAY_OF_YEAR, 32, LocalDate.of(2012, 2, 1)},
365                 {YEAR_OF_ERA, 2012, DAY_OF_YEAR, 32, LocalDate.of(2012, 2, 1)},
366 
367                 // merge
368                 {PROLEPTIC_MONTH, 2012 * 12 + (2 - 1), DAY_OF_MONTH, 25, LocalDate.of(2012, 2, 25)},
369                 {PROLEPTIC_MONTH, 2012 * 12 + (2 - 1), DAY_OF_YEAR, 56, LocalDate.of(2012, 2, 25)},
370 
371                 // cross-check
372                 {EPOCH_DAY, 32, ERA, 1, LocalDate.of(1970, 2, 2)},
373                 {EPOCH_DAY, -146097 * 5L, ERA, 0, LocalDate.of(1970 - (400 * 5), 1, 1)},
374                 {EPOCH_DAY, 32, YEAR, 1970, LocalDate.of(1970, 2, 2)},
375                 {EPOCH_DAY, -146097 * 5L, YEAR, 1970 - (400 * 5), LocalDate.of(1970 - (400 * 5), 1, 1)},
376                 {EPOCH_DAY, 32, YEAR_OF_ERA, 1970, LocalDate.of(1970, 2, 2)},
377                 {EPOCH_DAY, -146097 * 5L, YEAR_OF_ERA, 1 - (1970 - (400 * 5)), LocalDate.of(1970 - (400 * 5), 1, 1)},
378                 {EPOCH_DAY, 32, MONTH_OF_YEAR, 2, LocalDate.of(1970, 2, 2)},
379                 {EPOCH_DAY, 32, DAY_OF_YEAR, 33, LocalDate.of(1970, 2, 2)},
380                 {EPOCH_DAY, 32, DAY_OF_MONTH, 2, LocalDate.of(1970, 2, 2)},
381                 {EPOCH_DAY, 32, DAY_OF_WEEK, 1, LocalDate.of(1970, 2, 2)},
382         };
383     }
384 
385     @Test(dataProvider="resolveTwoToDate")
test_resolveTwoToDate(TemporalField field1, long value1, TemporalField field2, long value2, LocalDate expectedDate)386     public void test_resolveTwoToDate(TemporalField field1, long value1,
387                                       TemporalField field2, long value2,
388                                       LocalDate expectedDate) {
389         String str = value1 + " " + value2;
390         DateTimeFormatter f = new DateTimeFormatterBuilder()
391                 .appendValue(field1).appendLiteral(' ')
392                 .appendValue(field2).toFormatter();
393 
394         TemporalAccessor accessor = f.parse(str);
395         assertEquals(accessor.query(TemporalQueries.localDate()), expectedDate);
396         assertEquals(accessor.query(TemporalQueries.localTime()), null);
397     }
398 
399     //-----------------------------------------------------------------------
400     @DataProvider(name="resolveTwoToTime")
data_resolveTwoToTime()401     Object[][] data_resolveTwoToTime() {
402         return new Object[][]{
403                 // merge
404                 {HOUR_OF_DAY, 8, MINUTE_OF_HOUR, 6, LocalTime.of(8, 6)},
405 
406                 // merge
407                 {AMPM_OF_DAY, 0, HOUR_OF_AMPM, 5, LocalTime.of(5, 0)},
408                 {AMPM_OF_DAY, 1, HOUR_OF_AMPM, 5, LocalTime.of(17, 0)},
409                 {AMPM_OF_DAY, 0, CLOCK_HOUR_OF_AMPM, 5, LocalTime.of(5, 0)},
410                 {AMPM_OF_DAY, 1, CLOCK_HOUR_OF_AMPM, 5, LocalTime.of(17, 0)},
411                 {AMPM_OF_DAY, 0, HOUR_OF_DAY, 5, LocalTime.of(5, 0)},
412                 {AMPM_OF_DAY, 1, HOUR_OF_DAY, 17, LocalTime.of(17, 0)},
413                 {AMPM_OF_DAY, 0, CLOCK_HOUR_OF_DAY, 5, LocalTime.of(5, 0)},
414                 {AMPM_OF_DAY, 1, CLOCK_HOUR_OF_DAY, 17, LocalTime.of(17, 0)},
415 
416                 // merge
417                 {CLOCK_HOUR_OF_DAY, 8, MINUTE_OF_HOUR, 6, LocalTime.of(8, 6)},
418                 {CLOCK_HOUR_OF_DAY, 24, MINUTE_OF_HOUR, 6, LocalTime.of(0, 6)},
419                 // cross-check
420                 {CLOCK_HOUR_OF_DAY, 8, HOUR_OF_DAY, 8, LocalTime.of(8, 0)},
421                 {CLOCK_HOUR_OF_DAY, 8, CLOCK_HOUR_OF_AMPM, 8, LocalTime.of(8, 0)},
422                 {CLOCK_HOUR_OF_DAY, 20, CLOCK_HOUR_OF_AMPM, 8, LocalTime.of(20, 0)},
423                 {CLOCK_HOUR_OF_DAY, 8, AMPM_OF_DAY, 0, LocalTime.of(8, 0)},
424                 {CLOCK_HOUR_OF_DAY, 20, AMPM_OF_DAY, 1, LocalTime.of(20, 0)},
425 
426                 // merge
427                 {MINUTE_OF_DAY, 650, SECOND_OF_MINUTE, 8, LocalTime.of(10, 50, 8)},
428                 // cross-check
429                 {MINUTE_OF_DAY, 650, HOUR_OF_DAY, 10, LocalTime.of(10, 50)},
430                 {MINUTE_OF_DAY, 650, CLOCK_HOUR_OF_DAY, 10, LocalTime.of(10, 50)},
431                 {MINUTE_OF_DAY, 650, CLOCK_HOUR_OF_AMPM, 10, LocalTime.of(10, 50)},
432                 {MINUTE_OF_DAY, 650, AMPM_OF_DAY, 0, LocalTime.of(10, 50)},
433                 {MINUTE_OF_DAY, 650, MINUTE_OF_HOUR, 50, LocalTime.of(10, 50)},
434 
435                 // merge
436                 {SECOND_OF_DAY, 3600 + 650, MILLI_OF_SECOND, 2, LocalTime.of(1, 10, 50, 2_000_000)},
437                 {SECOND_OF_DAY, 3600 + 650, MICRO_OF_SECOND, 2, LocalTime.of(1, 10, 50, 2_000)},
438                 {SECOND_OF_DAY, 3600 + 650, NANO_OF_SECOND, 2, LocalTime.of(1, 10, 50, 2)},
439                 // cross-check
440                 {SECOND_OF_DAY, 3600 + 650, HOUR_OF_DAY, 1, LocalTime.of(1, 10, 50)},
441                 {SECOND_OF_DAY, 3600 + 650, MINUTE_OF_HOUR, 10, LocalTime.of(1, 10, 50)},
442                 {SECOND_OF_DAY, 3600 + 650, SECOND_OF_MINUTE, 50, LocalTime.of(1, 10, 50)},
443 
444                 // merge
445                 {MILLI_OF_DAY, (3600 + 650) * 1000L + 2, MICRO_OF_SECOND, 2_004, LocalTime.of(1, 10, 50, 2_004_000)},
446                 {MILLI_OF_DAY, (3600 + 650) * 1000L + 2, NANO_OF_SECOND, 2_000_004, LocalTime.of(1, 10, 50, 2_000_004)},
447                 // cross-check
448                 {MILLI_OF_DAY, (3600 + 650) * 1000L + 2, HOUR_OF_DAY, 1, LocalTime.of(1, 10, 50, 2_000_000)},
449                 {MILLI_OF_DAY, (3600 + 650) * 1000L + 2, MINUTE_OF_HOUR, 10, LocalTime.of(1, 10, 50, 2_000_000)},
450                 {MILLI_OF_DAY, (3600 + 650) * 1000L + 2, SECOND_OF_MINUTE, 50, LocalTime.of(1, 10, 50, 2_000_000)},
451                 {MILLI_OF_DAY, (3600 + 650) * 1000L + 2, MILLI_OF_SECOND, 2, LocalTime.of(1, 10, 50, 2_000_000)},
452 
453                 // merge
454                 {MICRO_OF_DAY, (3600 + 650) * 1000_000L + 2, NANO_OF_SECOND, 2_004, LocalTime.of(1, 10, 50, 2_004)},
455                 // cross-check
456                 {MICRO_OF_DAY, (3600 + 650) * 1000_000L + 2, HOUR_OF_DAY, 1, LocalTime.of(1, 10, 50, 2_000)},
457                 {MICRO_OF_DAY, (3600 + 650) * 1000_000L + 2, MINUTE_OF_HOUR, 10, LocalTime.of(1, 10, 50, 2_000)},
458                 {MICRO_OF_DAY, (3600 + 650) * 1000_000L + 2, SECOND_OF_MINUTE, 50, LocalTime.of(1, 10, 50, 2_000)},
459                 {MICRO_OF_DAY, (3600 + 650) * 1000_000L + 2, MILLI_OF_SECOND, 0, LocalTime.of(1, 10, 50, 2_000)},
460                 {MICRO_OF_DAY, (3600 + 650) * 1000_000L + 2, MICRO_OF_SECOND, 2, LocalTime.of(1, 10, 50, 2_000)},
461 
462                 // cross-check
463                 {NANO_OF_DAY, (3600 + 650) * 1000_000_000L + 2, HOUR_OF_DAY, 1, LocalTime.of(1, 10, 50, 2)},
464                 {NANO_OF_DAY, (3600 + 650) * 1000_000_000L + 2, MINUTE_OF_HOUR, 10, LocalTime.of(1, 10, 50, 2)},
465                 {NANO_OF_DAY, (3600 + 650) * 1000_000_000L + 2, SECOND_OF_MINUTE, 50, LocalTime.of(1, 10, 50, 2)},
466                 {NANO_OF_DAY, (3600 + 650) * 1000_000_000L + 2, MILLI_OF_SECOND, 0, LocalTime.of(1, 10, 50, 2)},
467                 {NANO_OF_DAY, (3600 + 650) * 1000_000_000L + 2, MICRO_OF_SECOND, 0, LocalTime.of(1, 10, 50, 2)},
468                 {NANO_OF_DAY, (3600 + 650) * 1000_000_000L + 2, NANO_OF_SECOND, 2, LocalTime.of(1, 10, 50, 2)},
469         };
470     }
471 
472     @Test(dataProvider="resolveTwoToTime")
test_resolveTwoToTime(TemporalField field1, long value1, TemporalField field2, long value2, LocalTime expectedTime)473     public void test_resolveTwoToTime(TemporalField field1, long value1,
474                                 TemporalField field2, long value2,
475                                 LocalTime expectedTime) {
476         String str = value1 + " " + value2;
477         DateTimeFormatter f = new DateTimeFormatterBuilder()
478                 .appendValue(field1).appendLiteral(' ')
479                 .appendValue(field2).toFormatter();
480 
481         TemporalAccessor accessor = f.parse(str);
482         assertEquals(accessor.query(TemporalQueries.localDate()), null);
483         assertEquals(accessor.query(TemporalQueries.localTime()), expectedTime);
484     }
485 
486     //-----------------------------------------------------------------------
487     @DataProvider(name="resolveThreeToDate")
data_resolveThreeToDate()488     Object[][] data_resolveThreeToDate() {
489         return new Object[][]{
490                 // merge
491                 {YEAR, 2012, MONTH_OF_YEAR, 2, DAY_OF_MONTH, 1, LocalDate.of(2012, 2, 1)},
492                 {YEAR, 2012, ALIGNED_WEEK_OF_YEAR, 5, ALIGNED_DAY_OF_WEEK_IN_YEAR, 4, LocalDate.of(2012, 2, 1)},
493                 {YEAR, 2012, ALIGNED_WEEK_OF_YEAR, 5, DAY_OF_WEEK, 3, LocalDate.of(2012, 2, 1)},
494 
495                 // cross-check
496                 {YEAR, 2012, DAY_OF_YEAR, 32, DAY_OF_MONTH, 1, LocalDate.of(2012, 2, 1)},
497                 {YEAR_OF_ERA, 2012, DAY_OF_YEAR, 32, DAY_OF_MONTH, 1, LocalDate.of(2012, 2, 1)},
498                 {YEAR, 2012, DAY_OF_YEAR, 32, DAY_OF_WEEK, 3, LocalDate.of(2012, 2, 1)},
499                 {PROLEPTIC_MONTH, 2012 * 12 + (2 - 1), DAY_OF_MONTH, 25, DAY_OF_WEEK, 6, LocalDate.of(2012, 2, 25)},
500         };
501     }
502 
503     @Test(dataProvider="resolveThreeToDate")
test_resolveThreeToDate(TemporalField field1, long value1, TemporalField field2, long value2, TemporalField field3, long value3, LocalDate expectedDate)504     public void test_resolveThreeToDate(TemporalField field1, long value1,
505                                       TemporalField field2, long value2,
506                                       TemporalField field3, long value3,
507                                       LocalDate expectedDate) {
508         String str = value1 + " " + value2 + " " + value3;
509         DateTimeFormatter f = new DateTimeFormatterBuilder()
510                 .appendValue(field1).appendLiteral(' ')
511                 .appendValue(field2).appendLiteral(' ')
512                 .appendValue(field3).toFormatter();
513 
514         TemporalAccessor accessor = f.parse(str);
515         assertEquals(accessor.query(TemporalQueries.localDate()), expectedDate);
516         assertEquals(accessor.query(TemporalQueries.localTime()), null);
517     }
518 
519     //-----------------------------------------------------------------------
520     @DataProvider(name="resolveFourToDate")
data_resolveFourToDate()521     Object[][] data_resolveFourToDate() {
522         return new Object[][]{
523                 // merge
524                 {YEAR, 2012, MONTH_OF_YEAR, 2, ALIGNED_WEEK_OF_MONTH, 1, ALIGNED_DAY_OF_WEEK_IN_MONTH, 1, LocalDate.of(2012, 2, 1)},
525                 {YEAR, 2012, MONTH_OF_YEAR, 2, ALIGNED_WEEK_OF_MONTH, 1, DAY_OF_WEEK, 3, LocalDate.of(2012, 2, 1)},
526 
527                 // cross-check
528                 {YEAR, 2012, MONTH_OF_YEAR, 2, DAY_OF_MONTH, 1, DAY_OF_WEEK, 3, LocalDate.of(2012, 2, 1)},
529                 {YEAR, 2012, ALIGNED_WEEK_OF_YEAR, 5, ALIGNED_DAY_OF_WEEK_IN_YEAR, 4, DAY_OF_WEEK, 3, LocalDate.of(2012, 2, 1)},
530                 {YEAR, 2012, ALIGNED_WEEK_OF_YEAR, 5, DAY_OF_WEEK, 3, DAY_OF_MONTH, 1, LocalDate.of(2012, 2, 1)},
531         };
532     }
533 
534     @Test(dataProvider="resolveFourToDate")
test_resolveFourToDate(TemporalField field1, long value1, TemporalField field2, long value2, TemporalField field3, long value3, TemporalField field4, long value4, LocalDate expectedDate)535     public void test_resolveFourToDate(TemporalField field1, long value1,
536                                         TemporalField field2, long value2,
537                                         TemporalField field3, long value3,
538                                         TemporalField field4, long value4,
539                                         LocalDate expectedDate) {
540         String str = value1 + " " + value2 + " " + value3 + " " + value4;
541         DateTimeFormatter f = new DateTimeFormatterBuilder()
542                 .appendValue(field1).appendLiteral(' ')
543                 .appendValue(field2).appendLiteral(' ')
544                 .appendValue(field3).appendLiteral(' ')
545                 .appendValue(field4).toFormatter();
546 
547         TemporalAccessor accessor = f.parse(str);
548         assertEquals(accessor.query(TemporalQueries.localDate()), expectedDate);
549         assertEquals(accessor.query(TemporalQueries.localTime()), null);
550     }
551 
552     //-----------------------------------------------------------------------
553     @DataProvider(name="resolveFourToTime")
data_resolveFourToTime()554     Object[][] data_resolveFourToTime() {
555         return new Object[][]{
556                 // merge
557                 {null, 0, 0, 0, 0, LocalTime.of(0, 0, 0, 0), Period.ZERO},
558                 {null, 1, 0, 0, 0, LocalTime.of(1, 0, 0, 0), Period.ZERO},
559                 {null, 0, 2, 0, 0, LocalTime.of(0, 2, 0, 0), Period.ZERO},
560                 {null, 0, 0, 3, 0, LocalTime.of(0, 0, 3, 0), Period.ZERO},
561                 {null, 0, 0, 0, 4, LocalTime.of(0, 0, 0, 4), Period.ZERO},
562                 {null, 1, 2, 3, 4, LocalTime.of(1, 2, 3, 4), Period.ZERO},
563                 {null, 23, 59, 59, 123456789, LocalTime.of(23, 59, 59, 123456789), Period.ZERO},
564 
565                 {ResolverStyle.STRICT, 14, 59, 60, 123456789, null, null},
566                 {ResolverStyle.SMART, 14, 59, 60, 123456789, null, null},
567                 {ResolverStyle.LENIENT, 14, 59, 60, 123456789, LocalTime.of(15, 0, 0, 123456789), Period.ZERO},
568 
569                 {ResolverStyle.STRICT, 23, 59, 60, 123456789, null, null},
570                 {ResolverStyle.SMART, 23, 59, 60, 123456789, null, null},
571                 {ResolverStyle.LENIENT, 23, 59, 60, 123456789, LocalTime.of(0, 0, 0, 123456789), Period.ofDays(1)},
572 
573                 {ResolverStyle.STRICT, 24, 0, 0, 0, null, null},
574                 {ResolverStyle.SMART, 24, 0, 0, 0, LocalTime.of(0, 0, 0, 0), Period.ofDays(1)},
575                 {ResolverStyle.LENIENT, 24, 0, 0, 0, LocalTime.of(0, 0, 0, 0), Period.ofDays(1)},
576 
577                 {ResolverStyle.STRICT, 24, 1, 0, 0, null, null},
578                 {ResolverStyle.SMART, 24, 1, 0, 0, null, null},
579                 {ResolverStyle.LENIENT, 24, 1, 0, 0, LocalTime.of(0, 1, 0, 0), Period.ofDays(1)},
580 
581                 {ResolverStyle.STRICT, 25, 0, 0, 0, null, null},
582                 {ResolverStyle.SMART, 25, 0, 0, 0, null, null},
583                 {ResolverStyle.LENIENT, 25, 0, 0, 0, LocalTime.of(1, 0, 0, 0), Period.ofDays(1)},
584 
585                 {ResolverStyle.STRICT, 49, 2, 3, 4, null, null},
586                 {ResolverStyle.SMART, 49, 2, 3, 4, null, null},
587                 {ResolverStyle.LENIENT, 49, 2, 3, 4, LocalTime.of(1, 2, 3, 4), Period.ofDays(2)},
588 
589                 {ResolverStyle.STRICT, -1, 2, 3, 4, null, null},
590                 {ResolverStyle.SMART, -1, 2, 3, 4, null, null},
591                 {ResolverStyle.LENIENT, -1, 2, 3, 4, LocalTime.of(23, 2, 3, 4), Period.ofDays(-1)},
592 
593                 {ResolverStyle.STRICT, -6, 2, 3, 4, null, null},
594                 {ResolverStyle.SMART, -6, 2, 3, 4, null, null},
595                 {ResolverStyle.LENIENT, -6, 2, 3, 4, LocalTime.of(18, 2, 3, 4), Period.ofDays(-1)},
596 
597                 {ResolverStyle.STRICT, 25, 61, 61, 1_123456789, null, null},
598                 {ResolverStyle.SMART, 25, 61, 61, 1_123456789, null, null},
599                 {ResolverStyle.LENIENT, 25, 61, 61, 1_123456789, LocalTime.of(2, 2, 2, 123456789), Period.ofDays(1)},
600         };
601     }
602 
603     @Test(dataProvider="resolveFourToTime")
test_resolveFourToTime(ResolverStyle style, long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod)604     public void test_resolveFourToTime(ResolverStyle style,
605                        long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod) {
606         DateTimeFormatter f = new DateTimeFormatterBuilder()
607                 .parseDefaulting(HOUR_OF_DAY, hour)
608                 .parseDefaulting(MINUTE_OF_HOUR, min)
609                 .parseDefaulting(SECOND_OF_MINUTE, sec)
610                 .parseDefaulting(NANO_OF_SECOND, nano).toFormatter();
611 
612         ResolverStyle[] styles = (style != null ? new ResolverStyle[] {style} : ResolverStyle.values());
613         for (ResolverStyle s : styles) {
614             if (expectedTime != null) {
615                 TemporalAccessor accessor = f.withResolverStyle(s).parse("");
616                 assertEquals(accessor.query(TemporalQueries.localDate()), null, "ResolverStyle: " + s);
617                 assertEquals(accessor.query(TemporalQueries.localTime()), expectedTime, "ResolverStyle: " + s);
618                 assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), excessPeriod, "ResolverStyle: " + s);
619             } else {
620                 try {
621                     f.withResolverStyle(style).parse("");
622                     fail();
623                 } catch (DateTimeParseException ex) {
624                     // expected
625                 }
626             }
627         }
628     }
629 
630     @Test(dataProvider="resolveFourToTime")
test_resolveThreeToTime(ResolverStyle style, long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod)631     public void test_resolveThreeToTime(ResolverStyle style,
632                                        long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod) {
633         DateTimeFormatter f = new DateTimeFormatterBuilder()
634                 .parseDefaulting(HOUR_OF_DAY, hour)
635                 .parseDefaulting(MINUTE_OF_HOUR, min)
636                 .parseDefaulting(SECOND_OF_MINUTE, sec).toFormatter();
637 
638         ResolverStyle[] styles = (style != null ? new ResolverStyle[] {style} : ResolverStyle.values());
639         for (ResolverStyle s : styles) {
640             if (expectedTime != null) {
641                 TemporalAccessor accessor = f.withResolverStyle(s).parse("");
642                 assertEquals(accessor.query(TemporalQueries.localDate()), null, "ResolverStyle: " + s);
643                 assertEquals(accessor.query(TemporalQueries.localTime()), expectedTime.minusNanos(nano), "ResolverStyle: " + s);
644                 assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), excessPeriod, "ResolverStyle: " + s);
645             } else {
646                 try {
647                     f.withResolverStyle(style).parse("");
648                     fail();
649                 } catch (DateTimeParseException ex) {
650                     // expected
651                 }
652             }
653         }
654     }
655 
656     @Test(dataProvider="resolveFourToTime")
test_resolveFourToDateTime(ResolverStyle style, long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod)657     public void test_resolveFourToDateTime(ResolverStyle style,
658                        long hour, long min, long sec, long nano, LocalTime expectedTime, Period excessPeriod) {
659         DateTimeFormatter f = new DateTimeFormatterBuilder()
660                 .parseDefaulting(YEAR, 2012).parseDefaulting(MONTH_OF_YEAR, 6).parseDefaulting(DAY_OF_MONTH, 30)
661                 .parseDefaulting(HOUR_OF_DAY, hour)
662                 .parseDefaulting(MINUTE_OF_HOUR, min)
663                 .parseDefaulting(SECOND_OF_MINUTE, sec)
664                 .parseDefaulting(NANO_OF_SECOND, nano).toFormatter();
665 
666         ResolverStyle[] styles = (style != null ? new ResolverStyle[] {style} : ResolverStyle.values());
667         if (expectedTime != null && excessPeriod != null) {
668             LocalDate expectedDate = LocalDate.of(2012, 6, 30).plus(excessPeriod);
669             for (ResolverStyle s : styles) {
670                 TemporalAccessor accessor = f.withResolverStyle(s).parse("");
671                 assertEquals(accessor.query(TemporalQueries.localDate()), expectedDate, "ResolverStyle: " + s);
672                 assertEquals(accessor.query(TemporalQueries.localTime()), expectedTime, "ResolverStyle: " + s);
673                 assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO, "ResolverStyle: " + s);
674             }
675         }
676     }
677 
678     //-----------------------------------------------------------------------
679     @DataProvider(name="resolveSecondOfDay")
data_resolveSecondOfDay()680     Object[][] data_resolveSecondOfDay() {
681         return new Object[][]{
682                 {STRICT, 0, 0, 0},
683                 {STRICT, 1, 1, 0},
684                 {STRICT, 86399, 86399, 0},
685                 {STRICT, -1, null, 0},
686                 {STRICT, 86400, null, 0},
687 
688                 {SMART, 0, 0, 0},
689                 {SMART, 1, 1, 0},
690                 {SMART, 86399, 86399, 0},
691                 {SMART, -1, null, 0},
692                 {SMART, 86400, null, 0},
693 
694                 {LENIENT, 0, 0, 0},
695                 {LENIENT, 1, 1, 0},
696                 {LENIENT, 86399, 86399, 0},
697                 {LENIENT, -1, 86399, -1},
698                 {LENIENT, 86400, 0, 1},
699         };
700     }
701 
702     @Test(dataProvider="resolveSecondOfDay")
test_resolveSecondOfDay(ResolverStyle style, long value, Integer expectedSecond, int expectedDays)703     public void test_resolveSecondOfDay(ResolverStyle style, long value, Integer expectedSecond, int expectedDays) {
704         String str = Long.toString(value);
705         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(SECOND_OF_DAY).toFormatter();
706 
707         if (expectedSecond != null) {
708             TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
709             assertEquals(accessor.query(TemporalQueries.localDate()), null);
710             assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.ofSecondOfDay(expectedSecond));
711             assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ofDays(expectedDays));
712         } else {
713             try {
714                 f.withResolverStyle(style).parse(str);
715                 fail();
716             } catch (DateTimeParseException ex) {
717                 // expected
718             }
719         }
720     }
721 
722     //-----------------------------------------------------------------------
723     @DataProvider(name="resolveMinuteOfDay")
data_resolveMinuteOfDay()724     Object[][] data_resolveMinuteOfDay() {
725         return new Object[][]{
726                 {STRICT, 0, 0, 0},
727                 {STRICT, 1, 1, 0},
728                 {STRICT, 1439, 1439, 0},
729                 {STRICT, -1, null, 0},
730                 {STRICT, 1440, null, 0},
731 
732                 {SMART, 0, 0, 0},
733                 {SMART, 1, 1, 0},
734                 {SMART, 1439, 1439, 0},
735                 {SMART, -1, null, 0},
736                 {SMART, 1440, null, 0},
737 
738                 {LENIENT, 0, 0, 0},
739                 {LENIENT, 1, 1, 0},
740                 {LENIENT, 1439, 1439, 0},
741                 {LENIENT, -1, 1439, -1},
742                 {LENIENT, 1440, 0, 1},
743         };
744     }
745 
746     @Test(dataProvider="resolveMinuteOfDay")
test_resolveMinuteOfDay(ResolverStyle style, long value, Integer expectedMinute, int expectedDays)747     public void test_resolveMinuteOfDay(ResolverStyle style, long value, Integer expectedMinute, int expectedDays) {
748         String str = Long.toString(value);
749         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(MINUTE_OF_DAY).toFormatter();
750 
751         if (expectedMinute != null) {
752             TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
753             assertEquals(accessor.query(TemporalQueries.localDate()), null);
754             assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.ofSecondOfDay(expectedMinute * 60));
755             assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ofDays(expectedDays));
756         } else {
757             try {
758                 f.withResolverStyle(style).parse(str);
759                 fail();
760             } catch (DateTimeParseException ex) {
761                 // expected
762             }
763         }
764     }
765 
766     //-----------------------------------------------------------------------
767     @DataProvider(name="resolveClockHourOfDay")
data_resolveClockHourOfDay()768     Object[][] data_resolveClockHourOfDay() {
769         return new Object[][]{
770                 {STRICT, 1, 1, 0},
771                 {STRICT, 24, 0, 0},
772                 {STRICT, 0, null, 0},
773                 {STRICT, -1, null, 0},
774                 {STRICT, 25, null, 0},
775 
776                 {SMART, 1, 1, 0},
777                 {SMART, 24, 0, 0},
778                 {SMART, 0, 0, 0},
779                 {SMART, -1, null, 0},
780                 {SMART, 25, null, 0},
781 
782                 {LENIENT, 1, 1, 0},
783                 {LENIENT, 24, 0, 0},
784                 {LENIENT, 0, 0, 0},
785                 {LENIENT, -1, 23, -1},
786                 {LENIENT, 25, 1, 1},
787         };
788     }
789 
790     @Test(dataProvider="resolveClockHourOfDay")
test_resolveClockHourOfDay(ResolverStyle style, long value, Integer expectedHour, int expectedDays)791     public void test_resolveClockHourOfDay(ResolverStyle style, long value, Integer expectedHour, int expectedDays) {
792         String str = Long.toString(value);
793         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(CLOCK_HOUR_OF_DAY).toFormatter();
794 
795         if (expectedHour != null) {
796             TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
797             assertEquals(accessor.query(TemporalQueries.localDate()), null);
798             assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.of(expectedHour, 0));
799             assertEquals(accessor.query(DateTimeFormatter.parsedExcessDays()), Period.ofDays(expectedDays));
800         } else {
801             try {
802                 f.withResolverStyle(style).parse(str);
803                 fail();
804             } catch (DateTimeParseException ex) {
805                 // expected
806             }
807         }
808     }
809 
810     //-----------------------------------------------------------------------
811     @DataProvider(name="resolveClockHourOfAmPm")
data_resolveClockHourOfAmPm()812     Object[][] data_resolveClockHourOfAmPm() {
813         return new Object[][]{
814                 {STRICT, 1, 1},
815                 {STRICT, 12, 0},
816                 {STRICT, 0, null},
817                 {STRICT, -1, null},
818                 {STRICT, 13, null},
819 
820                 {SMART, 1, 1},
821                 {SMART, 12, 0},
822                 {SMART, 0, 0},
823                 {SMART, -1, null},
824                 {SMART, 13, null},
825 
826                 {LENIENT, 1, 1},
827                 {LENIENT, 12, 0},
828                 {LENIENT, 0, 0},
829                 {LENIENT, -1, -1},
830                 {LENIENT, 13, 13},
831         };
832     }
833 
834     @Test(dataProvider="resolveClockHourOfAmPm")
test_resolveClockHourOfAmPm(ResolverStyle style, long value, Integer expectedValue)835     public void test_resolveClockHourOfAmPm(ResolverStyle style, long value, Integer expectedValue) {
836         String str = Long.toString(value);
837         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(CLOCK_HOUR_OF_AMPM).toFormatter();
838 
839         if (expectedValue != null) {
840             TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
841             assertEquals(accessor.query(TemporalQueries.localDate()), null);
842             assertEquals(accessor.query(TemporalQueries.localTime()), null);
843             assertEquals(accessor.isSupported(CLOCK_HOUR_OF_AMPM), false);
844             assertEquals(accessor.isSupported(HOUR_OF_AMPM), true);
845             assertEquals(accessor.getLong(HOUR_OF_AMPM), expectedValue.longValue());
846         } else {
847             try {
848                 f.withResolverStyle(style).parse(str);
849                 fail();
850             } catch (DateTimeParseException ex) {
851                 // expected
852             }
853         }
854     }
855 
856     //-----------------------------------------------------------------------
857     @DataProvider(name="resolveAmPm")
data_resolveAmPm()858     Object[][] data_resolveAmPm() {
859         return new Object[][]{
860                 {STRICT, 0, null, 0},
861                 {STRICT, 1, null, 1},
862                 {STRICT, -1, null, null},
863                 {STRICT, 2, null, null},
864 
865                 {SMART, 0, LocalTime.of(6, 0), 0},
866                 {SMART, 1, LocalTime.of(18, 0), 1},
867                 {SMART, -1, null, null},
868                 {SMART, 2, null, null},
869 
870                 {LENIENT, 0, LocalTime.of(6, 0), 0},
871                 {LENIENT, 1, LocalTime.of(18, 0), 1},
872                 {LENIENT, -1, LocalTime.of(18, 0), 1},
873                 {LENIENT, 2, LocalTime.of(6, 0), 0},
874         };
875     }
876 
877     @NonCts(bug = 286802267, reason = NonCtsReasons.NON_BREAKING_BEHAVIOR_FIX)
878     @Test(dataProvider="resolveAmPm")
test_resolveAmPm(ResolverStyle style, long value, LocalTime expectedTime, Integer expectedValue)879     public void test_resolveAmPm(ResolverStyle style, long value, LocalTime expectedTime, Integer expectedValue) {
880         String str = Long.toString(value);
881         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(AMPM_OF_DAY).toFormatter();
882 
883         if (expectedValue != null) {
884             TemporalAccessor accessor = f.withResolverStyle(style).parse(str);
885             assertEquals(accessor.query(TemporalQueries.localDate()), null);
886             assertEquals(accessor.query(TemporalQueries.localTime()), expectedTime);
887             assertEquals(accessor.isSupported(AMPM_OF_DAY), true);
888             assertEquals(accessor.getLong(AMPM_OF_DAY), expectedValue.longValue());
889         } else {
890             try {
891                 f.withResolverStyle(style).parse(str);
892                 fail();
893             } catch (DateTimeParseException ex) {
894                 // expected
895             }
896         }
897     }
898 
899     //-----------------------------------------------------------------------
900     // SPEC: DateTimeFormatter.withChronology()
901     @Test
test_withChronology_noOverride()902     public void test_withChronology_noOverride() {
903         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
904         TemporalAccessor accessor = f.parse("");
905         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
906         assertEquals(accessor.query(TemporalQueries.localTime()), null);
907         assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
908     }
909 
910     @Test
test_withChronology_override()911     public void test_withChronology_override() {
912         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
913         f = f.withChronology(MinguoChronology.INSTANCE);
914         TemporalAccessor accessor = f.parse("");
915         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
916         assertEquals(accessor.query(TemporalQueries.localTime()), null);
917         assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
918     }
919 
920     @Test
test_withChronology_parsedChronology_noOverride()921     public void test_withChronology_parsedChronology_noOverride() {
922         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendChronologyId().toFormatter();
923         TemporalAccessor accessor = f.parse("ThaiBuddhist");
924         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
925         assertEquals(accessor.query(TemporalQueries.localTime()), null);
926         assertEquals(accessor.query(TemporalQueries.chronology()), ThaiBuddhistChronology.INSTANCE);
927     }
928 
929     @Test
test_withChronology_parsedChronology_override()930     public void test_withChronology_parsedChronology_override() {
931         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendChronologyId().toFormatter();
932         f = f.withChronology(MinguoChronology.INSTANCE);
933         TemporalAccessor accessor = f.parse("ThaiBuddhist");
934         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
935         assertEquals(accessor.query(TemporalQueries.localTime()), null);
936         assertEquals(accessor.query(TemporalQueries.chronology()), ThaiBuddhistChronology.INSTANCE);
937     }
938 
939     //-----------------------------------------------------------------------
940     // SPEC: DateTimeFormatter.withZone()
941     @Test
test_withZone_noOverride()942     public void test_withZone_noOverride() {
943         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
944         TemporalAccessor accessor = f.parse("");
945         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
946         assertEquals(accessor.query(TemporalQueries.localTime()), null);
947         assertEquals(accessor.query(TemporalQueries.zoneId()), null);
948     }
949 
950     @Test
test_withZone_override()951     public void test_withZone_override() {
952         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).toFormatter();
953         f = f.withZone(EUROPE_ATHENS);
954         TemporalAccessor accessor = f.parse("");
955         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
956         assertEquals(accessor.query(TemporalQueries.localTime()), null);
957         assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_ATHENS);
958     }
959 
960     @Test
test_withZone_parsedZone_noOverride()961     public void test_withZone_parsedZone_noOverride() {
962         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendZoneId().toFormatter();
963         TemporalAccessor accessor = f.parse("Europe/Paris");
964         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
965         assertEquals(accessor.query(TemporalQueries.localTime()), null);
966         assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
967     }
968 
969     @Test
test_withZone_parsedZone_override()970     public void test_withZone_parsedZone_override() {
971         DateTimeFormatter f = new DateTimeFormatterBuilder().parseDefaulting(EPOCH_DAY, 2).appendZoneId().toFormatter();
972         f = f.withZone(EUROPE_ATHENS);
973         TemporalAccessor accessor = f.parse("Europe/Paris");
974         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(1970, 1, 3));
975         assertEquals(accessor.query(TemporalQueries.localTime()), null);
976         assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
977     }
978 
979     //-----------------------------------------------------------------------
980     @Test
test_fieldResolvesToLocalTime()981     public void test_fieldResolvesToLocalTime() {
982         LocalTime lt = LocalTime.of(12, 30, 40);
983         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(lt)).toFormatter();
984         TemporalAccessor accessor = f.parse("1234567890");
985         assertEquals(accessor.query(TemporalQueries.localDate()), null);
986         assertEquals(accessor.query(TemporalQueries.localTime()), lt);
987     }
988 
989     //-------------------------------------------------------------------------
990     @Test
test_fieldResolvesToChronoLocalDate_noOverrideChrono_matches()991     public void test_fieldResolvesToChronoLocalDate_noOverrideChrono_matches() {
992         LocalDate ldt = LocalDate.of(2010, 6, 30);
993         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(ldt)).toFormatter();
994         TemporalAccessor accessor = f.parse("1234567890");
995         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30));
996         assertEquals(accessor.query(TemporalQueries.localTime()), null);
997         assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
998     }
999 
1000     @Test
test_fieldResolvesToChronoLocalDate_overrideChrono_matches()1001     public void test_fieldResolvesToChronoLocalDate_overrideChrono_matches() {
1002         MinguoDate mdt = MinguoDate.of(100, 6, 30);
1003         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(mdt)).toFormatter();
1004         f = f.withChronology(MinguoChronology.INSTANCE);
1005         TemporalAccessor accessor = f.parse("1234567890");
1006         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.from(mdt));
1007         assertEquals(accessor.query(TemporalQueries.localTime()), null);
1008         assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
1009     }
1010 
1011     @Test(expectedExceptions = DateTimeParseException.class)
test_fieldResolvesToChronoLocalDate_noOverrideChrono_wrongChrono()1012     public void test_fieldResolvesToChronoLocalDate_noOverrideChrono_wrongChrono() {
1013         ChronoLocalDate cld = ThaiBuddhistChronology.INSTANCE.dateNow();
1014         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cld)).toFormatter();
1015         f.parse("1234567890");
1016     }
1017 
1018     @Test(expectedExceptions = DateTimeParseException.class)
test_fieldResolvesToChronoLocalDate_overrideChrono_wrongChrono()1019     public void test_fieldResolvesToChronoLocalDate_overrideChrono_wrongChrono() {
1020         ChronoLocalDate cld = ThaiBuddhistChronology.INSTANCE.dateNow();
1021         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cld)).toFormatter();
1022         f = f.withChronology(MinguoChronology.INSTANCE);
1023         f.parse("1234567890");
1024     }
1025 
1026     //-------------------------------------------------------------------------
1027     @Test
test_fieldResolvesToChronoLocalDateTime_noOverrideChrono_matches()1028     public void test_fieldResolvesToChronoLocalDateTime_noOverrideChrono_matches() {
1029         LocalDateTime ldt = LocalDateTime.of(2010, 6, 30, 12, 30);
1030         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(ldt)).toFormatter();
1031         TemporalAccessor accessor = f.parse("1234567890");
1032         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30));
1033         assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.of(12, 30));
1034         assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
1035     }
1036 
1037     @Test
test_fieldResolvesToChronoLocalDateTime_overrideChrono_matches()1038     public void test_fieldResolvesToChronoLocalDateTime_overrideChrono_matches() {
1039         MinguoDate mdt = MinguoDate.of(100, 6, 30);
1040         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(mdt.atTime(LocalTime.NOON))).toFormatter();
1041         f = f.withChronology(MinguoChronology.INSTANCE);
1042         TemporalAccessor accessor = f.parse("1234567890");
1043         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.from(mdt));
1044         assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.NOON);
1045         assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
1046     }
1047 
1048     @Test(expectedExceptions = DateTimeParseException.class)
test_fieldResolvesToChronoLocalDateTime_noOverrideChrono_wrongChrono()1049     public void test_fieldResolvesToChronoLocalDateTime_noOverrideChrono_wrongChrono() {
1050         ChronoLocalDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON);
1051         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
1052         f.parse("1234567890");
1053     }
1054 
1055     @Test(expectedExceptions = DateTimeParseException.class)
test_fieldResolvesToChronoLocalDateTime_overrideChrono_wrongChrono()1056     public void test_fieldResolvesToChronoLocalDateTime_overrideChrono_wrongChrono() {
1057         ChronoLocalDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON);
1058         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
1059         f = f.withChronology(MinguoChronology.INSTANCE);
1060         f.parse("1234567890");
1061     }
1062 
1063     //-------------------------------------------------------------------------
1064     @Test
test_fieldResolvesToChronoZonedDateTime_noOverrideChrono_matches()1065     public void test_fieldResolvesToChronoZonedDateTime_noOverrideChrono_matches() {
1066         ZonedDateTime zdt = ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, EUROPE_PARIS);
1067         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(zdt)).toFormatter();
1068         TemporalAccessor accessor = f.parse("1234567890");
1069         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.of(2010, 6, 30));
1070         assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.of(12, 30));
1071         assertEquals(accessor.query(TemporalQueries.chronology()), IsoChronology.INSTANCE);
1072         assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
1073     }
1074 
1075     @Test
test_fieldResolvesToChronoZonedDateTime_overrideChrono_matches()1076     public void test_fieldResolvesToChronoZonedDateTime_overrideChrono_matches() {
1077         MinguoDate mdt = MinguoDate.of(100, 6, 30);
1078         ChronoZonedDateTime<MinguoDate> mzdt = mdt.atTime(LocalTime.NOON).atZone(EUROPE_PARIS);
1079         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(mzdt)).toFormatter();
1080         f = f.withChronology(MinguoChronology.INSTANCE);
1081         TemporalAccessor accessor = f.parse("1234567890");
1082         assertEquals(accessor.query(TemporalQueries.localDate()), LocalDate.from(mdt));
1083         assertEquals(accessor.query(TemporalQueries.localTime()), LocalTime.NOON);
1084         assertEquals(accessor.query(TemporalQueries.chronology()), MinguoChronology.INSTANCE);
1085         assertEquals(accessor.query(TemporalQueries.zoneId()), EUROPE_PARIS);
1086     }
1087 
1088     @Test(expectedExceptions = DateTimeParseException.class)
test_fieldResolvesToChronoZonedDateTime_noOverrideChrono_wrongChrono()1089     public void test_fieldResolvesToChronoZonedDateTime_noOverrideChrono_wrongChrono() {
1090         ChronoZonedDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON).atZone(EUROPE_PARIS);
1091         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
1092         f.parse("1234567890");
1093     }
1094 
1095     @Test(expectedExceptions = DateTimeParseException.class)
test_fieldResolvesToChronoZonedDateTime_overrideChrono_wrongChrono()1096     public void test_fieldResolvesToChronoZonedDateTime_overrideChrono_wrongChrono() {
1097         ChronoZonedDateTime<?> cldt = ThaiBuddhistChronology.INSTANCE.dateNow().atTime(LocalTime.NOON).atZone(EUROPE_PARIS);
1098         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(cldt)).toFormatter();
1099         f = f.withChronology(MinguoChronology.INSTANCE);
1100         f.parse("1234567890");
1101     }
1102 
1103     @Test
test_fieldResolvesToChronoZonedDateTime_overrideZone_matches()1104     public void test_fieldResolvesToChronoZonedDateTime_overrideZone_matches() {
1105         ZonedDateTime zdt = ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, EUROPE_PARIS);
1106         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(zdt)).toFormatter();
1107         f = f.withZone(EUROPE_PARIS);
1108         assertEquals(f.parse("1234567890", ZonedDateTime::from), zdt);
1109     }
1110 
1111     @Test(expectedExceptions = DateTimeParseException.class)
test_fieldResolvesToChronoZonedDateTime_overrideZone_wrongZone()1112     public void test_fieldResolvesToChronoZonedDateTime_overrideZone_wrongZone() {
1113         ZonedDateTime zdt = ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, EUROPE_PARIS);
1114         DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(new ResolvingField(zdt)).toFormatter();
1115         f = f.withZone(ZoneId.of("Europe/London"));
1116         f.parse("1234567890");
1117     }
1118 
1119     //-------------------------------------------------------------------------
1120     private static class ResolvingField implements TemporalField {
1121         private final TemporalAccessor resolvedValue;
ResolvingField(TemporalAccessor resolvedValue)1122         ResolvingField(TemporalAccessor resolvedValue) {
1123             this.resolvedValue = resolvedValue;
1124         }
1125         @Override
getBaseUnit()1126         public TemporalUnit getBaseUnit() {
1127             throw new UnsupportedOperationException();
1128         }
1129         @Override
getRangeUnit()1130         public TemporalUnit getRangeUnit() {
1131             throw new UnsupportedOperationException();
1132         }
1133         @Override
range()1134         public ValueRange range() {
1135             throw new UnsupportedOperationException();
1136         }
1137         @Override
isDateBased()1138         public boolean isDateBased() {
1139             throw new UnsupportedOperationException();
1140         }
1141         @Override
isTimeBased()1142         public boolean isTimeBased() {
1143             throw new UnsupportedOperationException();
1144         }
1145         @Override
isSupportedBy(TemporalAccessor temporal)1146         public boolean isSupportedBy(TemporalAccessor temporal) {
1147             throw new UnsupportedOperationException();
1148         }
1149         @Override
rangeRefinedBy(TemporalAccessor temporal)1150         public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
1151             throw new UnsupportedOperationException();
1152         }
1153         @Override
getFrom(TemporalAccessor temporal)1154         public long getFrom(TemporalAccessor temporal) {
1155             throw new UnsupportedOperationException();
1156         }
1157         @Override
adjustInto(R temporal, long newValue)1158         public <R extends Temporal> R adjustInto(R temporal, long newValue) {
1159             throw new UnsupportedOperationException();
1160         }
1161         @Override
resolve( Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle)1162         public TemporalAccessor resolve(
1163                 Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
1164             fieldValues.remove(this);
1165             return resolvedValue;
1166         }
1167     };
1168 
1169     //-------------------------------------------------------------------------
1170     // SPEC: ChronoField.INSTANT_SECONDS
1171     @Test
test_parse_fromField_InstantSeconds()1172     public void test_parse_fromField_InstantSeconds() {
1173         DateTimeFormatter fmt = new DateTimeFormatterBuilder()
1174             .appendValue(INSTANT_SECONDS).toFormatter();
1175         TemporalAccessor acc = fmt.parse("86402");
1176         Instant expected = Instant.ofEpochSecond(86402);
1177         assertEquals(acc.isSupported(INSTANT_SECONDS), true);
1178         assertEquals(acc.isSupported(NANO_OF_SECOND), true);
1179         assertEquals(acc.isSupported(MICRO_OF_SECOND), true);
1180         assertEquals(acc.isSupported(MILLI_OF_SECOND), true);
1181         assertEquals(acc.getLong(INSTANT_SECONDS), 86402L);
1182         assertEquals(acc.getLong(NANO_OF_SECOND), 0L);
1183         assertEquals(acc.getLong(MICRO_OF_SECOND), 0L);
1184         assertEquals(acc.getLong(MILLI_OF_SECOND), 0L);
1185         assertEquals(Instant.from(acc), expected);
1186     }
1187 
1188     @Test
test_parse_fromField_InstantSeconds_NanoOfSecond()1189     public void test_parse_fromField_InstantSeconds_NanoOfSecond() {
1190         DateTimeFormatter fmt = new DateTimeFormatterBuilder()
1191             .appendValue(INSTANT_SECONDS).appendLiteral('.').appendValue(NANO_OF_SECOND).toFormatter();
1192         TemporalAccessor acc = fmt.parse("86402.123456789");
1193         Instant expected = Instant.ofEpochSecond(86402, 123456789);
1194         assertEquals(acc.isSupported(INSTANT_SECONDS), true);
1195         assertEquals(acc.isSupported(NANO_OF_SECOND), true);
1196         assertEquals(acc.isSupported(MICRO_OF_SECOND), true);
1197         assertEquals(acc.isSupported(MILLI_OF_SECOND), true);
1198         assertEquals(acc.getLong(INSTANT_SECONDS), 86402L);
1199         assertEquals(acc.getLong(NANO_OF_SECOND), 123456789L);
1200         assertEquals(acc.getLong(MICRO_OF_SECOND), 123456L);
1201         assertEquals(acc.getLong(MILLI_OF_SECOND), 123L);
1202         assertEquals(Instant.from(acc), expected);
1203     }
1204 
1205     // SPEC: ChronoField.SECOND_OF_DAY
1206     @Test
test_parse_fromField_SecondOfDay()1207     public void test_parse_fromField_SecondOfDay() {
1208         DateTimeFormatter fmt = new DateTimeFormatterBuilder()
1209             .appendValue(SECOND_OF_DAY).toFormatter();
1210         TemporalAccessor acc = fmt.parse("864");
1211         assertEquals(acc.isSupported(SECOND_OF_DAY), true);
1212         assertEquals(acc.isSupported(NANO_OF_SECOND), true);
1213         assertEquals(acc.isSupported(MICRO_OF_SECOND), true);
1214         assertEquals(acc.isSupported(MILLI_OF_SECOND), true);
1215         assertEquals(acc.getLong(SECOND_OF_DAY), 864L);
1216         assertEquals(acc.getLong(NANO_OF_SECOND), 0L);
1217         assertEquals(acc.getLong(MICRO_OF_SECOND), 0L);
1218         assertEquals(acc.getLong(MILLI_OF_SECOND), 0L);
1219     }
1220 
1221     @Test
test_parse_fromField_SecondOfDay_NanoOfSecond()1222     public void test_parse_fromField_SecondOfDay_NanoOfSecond() {
1223         DateTimeFormatter fmt = new DateTimeFormatterBuilder()
1224             .appendValue(SECOND_OF_DAY).appendLiteral('.').appendValue(NANO_OF_SECOND).toFormatter();
1225         TemporalAccessor acc = fmt.parse("864.123456789");
1226         assertEquals(acc.isSupported(SECOND_OF_DAY), true);
1227         assertEquals(acc.isSupported(NANO_OF_SECOND), true);
1228         assertEquals(acc.isSupported(MICRO_OF_SECOND), true);
1229         assertEquals(acc.isSupported(MILLI_OF_SECOND), true);
1230         assertEquals(acc.getLong(SECOND_OF_DAY), 864L);
1231         assertEquals(acc.getLong(NANO_OF_SECOND), 123456789L);
1232         assertEquals(acc.getLong(MICRO_OF_SECOND), 123456L);
1233         assertEquals(acc.getLong(MILLI_OF_SECOND), 123L);
1234     }
1235 
1236     // SPEC: ChronoField.SECOND_OF_MINUTE
1237     @Test
test_parse_fromField_SecondOfMinute()1238     public void test_parse_fromField_SecondOfMinute() {
1239         DateTimeFormatter fmt = new DateTimeFormatterBuilder()
1240             .appendValue(SECOND_OF_MINUTE).toFormatter();
1241         TemporalAccessor acc = fmt.parse("32");
1242         assertEquals(acc.isSupported(SECOND_OF_MINUTE), true);
1243         assertEquals(acc.isSupported(NANO_OF_SECOND), true);
1244         assertEquals(acc.isSupported(MICRO_OF_SECOND), true);
1245         assertEquals(acc.isSupported(MILLI_OF_SECOND), true);
1246         assertEquals(acc.getLong(SECOND_OF_MINUTE), 32L);
1247         assertEquals(acc.getLong(NANO_OF_SECOND), 0L);
1248         assertEquals(acc.getLong(MICRO_OF_SECOND), 0L);
1249         assertEquals(acc.getLong(MILLI_OF_SECOND), 0L);
1250     }
1251 
1252     @Test
test_parse_fromField_SecondOfMinute_NanoOfSecond()1253     public void test_parse_fromField_SecondOfMinute_NanoOfSecond() {
1254         DateTimeFormatter fmt = new DateTimeFormatterBuilder()
1255             .appendValue(SECOND_OF_MINUTE).appendLiteral('.').appendValue(NANO_OF_SECOND).toFormatter();
1256         TemporalAccessor acc = fmt.parse("32.123456789");
1257         assertEquals(acc.isSupported(SECOND_OF_MINUTE), true);
1258         assertEquals(acc.isSupported(NANO_OF_SECOND), true);
1259         assertEquals(acc.isSupported(MICRO_OF_SECOND), true);
1260         assertEquals(acc.isSupported(MILLI_OF_SECOND), true);
1261         assertEquals(acc.getLong(SECOND_OF_MINUTE), 32L);
1262         assertEquals(acc.getLong(NANO_OF_SECOND), 123456789L);
1263         assertEquals(acc.getLong(MICRO_OF_SECOND), 123456L);
1264         assertEquals(acc.getLong(MILLI_OF_SECOND), 123L);
1265     }
1266 
1267 }
1268