Home | History | Annotate | Download | only in format
      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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    276     Object[][] data_resolveOneToDate() {
    277         return new Object[][]{
    278                 {EPOCH_DAY, 32, LocalDate.of(1970, 2, 2)},
    279         };
    280     }
    281 
    282     @Test(dataProvider="resolveOneToDate")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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)
   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)
   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
   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
   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)
   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)
   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
   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
   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)
   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)
   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
   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)
   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;
   1118         ResolvingField(TemporalAccessor resolvedValue) {
   1119             this.resolvedValue = resolvedValue;
   1120         }
   1121         @Override
   1122         public TemporalUnit getBaseUnit() {
   1123             throw new UnsupportedOperationException();
   1124         }
   1125         @Override
   1126         public TemporalUnit getRangeUnit() {
   1127             throw new UnsupportedOperationException();
   1128         }
   1129         @Override
   1130         public ValueRange range() {
   1131             throw new UnsupportedOperationException();
   1132         }
   1133         @Override
   1134         public boolean isDateBased() {
   1135             throw new UnsupportedOperationException();
   1136         }
   1137         @Override
   1138         public boolean isTimeBased() {
   1139             throw new UnsupportedOperationException();
   1140         }
   1141         @Override
   1142         public boolean isSupportedBy(TemporalAccessor temporal) {
   1143             throw new UnsupportedOperationException();
   1144         }
   1145         @Override
   1146         public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
   1147             throw new UnsupportedOperationException();
   1148         }
   1149         @Override
   1150         public long getFrom(TemporalAccessor temporal) {
   1151             throw new UnsupportedOperationException();
   1152         }
   1153         @Override
   1154         public <R extends Temporal> R adjustInto(R temporal, long newValue) {
   1155             throw new UnsupportedOperationException();
   1156         }
   1157         @Override
   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
   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
   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
   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
   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
   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
   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