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