1/*
2 * Copyright (c) 2012, 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-2012, 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 */
60package tck.java.time.format;
61
62import static java.time.temporal.ChronoField.DAY_OF_MONTH;
63import static java.time.temporal.ChronoField.DAY_OF_WEEK;
64import static java.time.temporal.ChronoField.DAY_OF_YEAR;
65import static java.time.temporal.ChronoField.HOUR_OF_DAY;
66import static java.time.temporal.ChronoField.INSTANT_SECONDS;
67import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
68import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
69import static java.time.temporal.ChronoField.NANO_OF_SECOND;
70import static java.time.temporal.ChronoField.OFFSET_SECONDS;
71import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
72import static java.time.temporal.ChronoField.YEAR;
73import static org.testng.Assert.assertEquals;
74import static org.testng.Assert.assertTrue;
75import static org.testng.Assert.fail;
76
77import java.text.ParsePosition;
78import java.time.DateTimeException;
79import java.time.LocalDate;
80import java.time.LocalDateTime;
81import java.time.Month;
82import java.time.Year;
83import java.time.YearMonth;
84import java.time.ZoneId;
85import java.time.ZoneOffset;
86import java.time.ZonedDateTime;
87import java.time.chrono.Chronology;
88import java.time.chrono.IsoChronology;
89import java.time.format.DateTimeFormatter;
90import java.time.format.DateTimeParseException;
91import java.time.format.FormatStyle;
92import java.time.format.ResolverStyle;
93import java.time.format.TextStyle;
94import java.time.temporal.IsoFields;
95import java.time.temporal.TemporalAccessor;
96import java.time.temporal.TemporalField;
97import java.time.temporal.TemporalQueries;
98import java.time.temporal.TemporalQuery;
99import java.util.HashMap;
100import java.util.Iterator;
101import java.util.Locale;
102import java.util.Map;
103
104import org.testng.annotations.BeforeMethod;
105import org.testng.annotations.DataProvider;
106import org.testng.annotations.Test;
107
108/**
109 * Test DateTimeFormatter.
110 */
111@Test
112public class TCKDateTimeFormatters {
113
114    @BeforeMethod
115    public void setUp() {
116    }
117
118    //-----------------------------------------------------------------------
119    @Test(expectedExceptions=NullPointerException.class)
120    public void test_format_nullTemporalAccessor() {
121        DateTimeFormatter.ISO_DATE.format((TemporalAccessor) null);
122    }
123
124    //-----------------------------------------------------------------------
125    //-----------------------------------------------------------------------
126    //-----------------------------------------------------------------------
127    @Test
128    public void test_pattern_String() {
129        DateTimeFormatter test = DateTimeFormatter.ofPattern("d MMM yyyy");
130        Locale fmtLocale = Locale.getDefault(Locale.Category.FORMAT);
131        assertEquals(test.format(LocalDate.of(2012, 6, 30)), "30 " +
132                Month.JUNE.getDisplayName(TextStyle.SHORT, fmtLocale) + " 2012");
133        assertEquals(test.getLocale(), fmtLocale, "Locale.Category.FORMAT");
134    }
135
136    @Test(expectedExceptions=IllegalArgumentException.class)
137    public void test_pattern_String_invalid() {
138        DateTimeFormatter.ofPattern("p");
139    }
140
141    @Test(expectedExceptions=NullPointerException.class)
142    public void test_pattern_String_null() {
143        DateTimeFormatter.ofPattern(null);
144    }
145
146    //-----------------------------------------------------------------------
147    //-----------------------------------------------------------------------
148    //-----------------------------------------------------------------------
149    @Test
150    public void test_pattern_StringLocale() {
151        DateTimeFormatter test = DateTimeFormatter.ofPattern("d MMM yyyy", Locale.UK);
152        assertEquals(test.format(LocalDate.of(2012, 6, 30)), "30 Jun 2012");
153        assertEquals(test.getLocale(), Locale.UK);
154    }
155
156    @Test(expectedExceptions=IllegalArgumentException.class)
157    public void test_pattern_StringLocale_invalid() {
158        DateTimeFormatter.ofPattern("p", Locale.UK);
159    }
160
161    @Test(expectedExceptions=NullPointerException.class)
162    public void test_pattern_StringLocale_nullPattern() {
163        DateTimeFormatter.ofPattern(null, Locale.UK);
164    }
165
166    @Test(expectedExceptions=NullPointerException.class)
167    public void test_pattern_StringLocale_nullLocale() {
168        DateTimeFormatter.ofPattern("yyyy", null);
169    }
170
171    //-----------------------------------------------------------------------
172    //-----------------------------------------------------------------------
173    //-----------------------------------------------------------------------
174    @Test
175    public void test_ofLocalizedDate_basics() {
176        assertEquals(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).getChronology(), IsoChronology.INSTANCE);
177        assertEquals(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).getZone(), null);
178        assertEquals(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).getResolverStyle(), ResolverStyle.SMART);
179    }
180
181    @Test
182    public void test_ofLocalizedTime_basics() {
183        assertEquals(DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).getChronology(), IsoChronology.INSTANCE);
184        assertEquals(DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).getZone(), null);
185        assertEquals(DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).getResolverStyle(), ResolverStyle.SMART);
186    }
187
188    @Test
189    public void test_ofLocalizedDateTime1_basics() {
190        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).getChronology(), IsoChronology.INSTANCE);
191        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).getZone(), null);
192        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).getResolverStyle(), ResolverStyle.SMART);
193    }
194
195    @Test
196    public void test_ofLocalizedDateTime2_basics() {
197        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM).getChronology(), IsoChronology.INSTANCE);
198        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM).getZone(), null);
199        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM).getResolverStyle(), ResolverStyle.SMART);
200    }
201
202    //-----------------------------------------------------------------------
203    //-----------------------------------------------------------------------
204    //-----------------------------------------------------------------------
205    @DataProvider(name="sample_isoLocalDate")
206    Object[][] provider_sample_isoLocalDate() {
207        return new Object[][]{
208                {2008, null, null, null, null, null, DateTimeException.class},
209                {null, 6, null, null, null, null, DateTimeException.class},
210                {null, null, 30, null, null, null, DateTimeException.class},
211                {null, null, null, "+01:00", null, null, DateTimeException.class},
212                {null, null, null, null, "Europe/Paris", null, DateTimeException.class},
213                {2008, 6, null, null, null, null, DateTimeException.class},
214                {null, 6, 30, null, null, null, DateTimeException.class},
215
216                {2008, 6, 30, null, null,                   "2008-06-30", null},
217                {2008, 6, 30, "+01:00", null,               "2008-06-30", null},
218                {2008, 6, 30, "+01:00", "Europe/Paris",     "2008-06-30", null},
219                {2008, 6, 30, null, "Europe/Paris",         "2008-06-30", null},
220
221                {123456, 6, 30, null, null,                 "+123456-06-30", null},
222        };
223    }
224
225    @Test(dataProvider="sample_isoLocalDate")
226    public void test_print_isoLocalDate(
227            Integer year, Integer month, Integer day, String offsetId, String zoneId,
228            String expected, Class<?> expectedEx) {
229        TemporalAccessor test = buildAccessor(year, month, day, null, null, null, null, offsetId, zoneId);
230        if (expectedEx == null) {
231            assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.format(test), expected);
232        } else {
233            try {
234                DateTimeFormatter.ISO_LOCAL_DATE.format(test);
235                fail();
236            } catch (Exception ex) {
237                assertTrue(expectedEx.isInstance(ex));
238            }
239        }
240    }
241
242    @Test(dataProvider="sample_isoLocalDate")
243    public void test_parse_isoLocalDate(
244            Integer year, Integer month, Integer day, String offsetId, String zoneId,
245            String input, Class<?> invalid) {
246        if (input != null) {
247            Expected expected = createDate(year, month, day);
248            // offset/zone not expected to be parsed
249            assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved(input, new ParsePosition(0)), expected);
250        }
251    }
252
253    @Test
254    public void test_parse_isoLocalDate_999999999() {
255        Expected expected = createDate(999999999, 8, 6);
256        assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("+999999999-08-06", new ParsePosition(0)), expected);
257        assertEquals(LocalDate.parse("+999999999-08-06"), LocalDate.of(999999999, 8, 6));
258    }
259
260    @Test
261    public void test_parse_isoLocalDate_1000000000() {
262        Expected expected = createDate(1000000000, 8, 6);
263        assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("+1000000000-08-06", new ParsePosition(0)), expected);
264    }
265
266    @Test(expectedExceptions = DateTimeException.class)
267    public void test_parse_isoLocalDate_1000000000_failedCreate() {
268        LocalDate.parse("+1000000000-08-06");
269    }
270
271    @Test
272    public void test_parse_isoLocalDate_M999999999() {
273        Expected expected = createDate(-999999999, 8, 6);
274        assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("-999999999-08-06", new ParsePosition(0)), expected);
275        assertEquals(LocalDate.parse("-999999999-08-06"), LocalDate.of(-999999999, 8, 6));
276    }
277
278    @Test
279    public void test_parse_isoLocalDate_M1000000000() {
280        Expected expected = createDate(-1000000000, 8, 6);
281        assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("-1000000000-08-06", new ParsePosition(0)), expected);
282    }
283
284    @Test(expectedExceptions = DateTimeException.class)
285    public void test_parse_isoLocalDate_M1000000000_failedCreate() {
286        LocalDate.parse("-1000000000-08-06");
287    }
288
289    @Test
290    public void test_isoLocalDate_basics() {
291        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.getChronology(), IsoChronology.INSTANCE);
292        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.getZone(), null);
293        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.getResolverStyle(), ResolverStyle.STRICT);
294    }
295
296    //-----------------------------------------------------------------------
297    //-----------------------------------------------------------------------
298    //-----------------------------------------------------------------------
299    @DataProvider(name="sample_isoOffsetDate")
300    Object[][] provider_sample_isoOffsetDate() {
301        return new Object[][]{
302                {2008, null, null, null, null, null, DateTimeException.class},
303                {null, 6, null, null, null, null, DateTimeException.class},
304                {null, null, 30, null, null, null, DateTimeException.class},
305                {null, null, null, "+01:00", null, null, DateTimeException.class},
306                {null, null, null, null, "Europe/Paris", null, DateTimeException.class},
307                {2008, 6, null, null, null, null, DateTimeException.class},
308                {null, 6, 30, null, null, null, DateTimeException.class},
309
310                {2008, 6, 30, null, null,                   null, DateTimeException.class},
311                {2008, 6, 30, "+01:00", null,               "2008-06-30+01:00", null},
312                {2008, 6, 30, "+01:00", "Europe/Paris",     "2008-06-30+01:00", null},
313                {2008, 6, 30, null, "Europe/Paris",         null, DateTimeException.class},
314
315                {123456, 6, 30, "+01:00", null,             "+123456-06-30+01:00", null},
316        };
317    }
318
319    @Test(dataProvider="sample_isoOffsetDate")
320    public void test_print_isoOffsetDate(
321            Integer year, Integer month, Integer day, String offsetId, String zoneId,
322            String expected, Class<?> expectedEx) {
323        TemporalAccessor test = buildAccessor(year, month, day, null, null, null, null, offsetId, zoneId);
324        if (expectedEx == null) {
325            assertEquals(DateTimeFormatter.ISO_OFFSET_DATE.format(test), expected);
326        } else {
327            try {
328                DateTimeFormatter.ISO_OFFSET_DATE.format(test);
329                fail();
330            } catch (Exception ex) {
331                assertTrue(expectedEx.isInstance(ex));
332            }
333        }
334    }
335
336    @Test(dataProvider="sample_isoOffsetDate")
337    public void test_parse_isoOffsetDate(
338            Integer year, Integer month, Integer day, String offsetId, String zoneId,
339            String input, Class<?> invalid) {
340        if (input != null) {
341            Expected expected = createDate(year, month, day);
342            buildCalendrical(expected, offsetId, null);  // zone not expected to be parsed
343            assertParseMatch(DateTimeFormatter.ISO_OFFSET_DATE.parseUnresolved(input, new ParsePosition(0)), expected);
344        }
345    }
346
347    @Test
348    public void test_isoOffsetDate_basics() {
349        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE.getChronology(), IsoChronology.INSTANCE);
350        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE.getZone(), null);
351        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE.getResolverStyle(), ResolverStyle.STRICT);
352    }
353
354    //-----------------------------------------------------------------------
355    //-----------------------------------------------------------------------
356    //-----------------------------------------------------------------------
357    @DataProvider(name="sample_isoDate")
358    Object[][] provider_sample_isoDate() {
359        return new Object[][]{
360                {2008, null, null, null, null, null, DateTimeException.class},
361                {null, 6, null, null, null, null, DateTimeException.class},
362                {null, null, 30, null, null, null, DateTimeException.class},
363                {null, null, null, "+01:00", null, null, DateTimeException.class},
364                {null, null, null, null, "Europe/Paris", null, DateTimeException.class},
365                {2008, 6, null, null, null, null, DateTimeException.class},
366                {null, 6, 30, null, null, null, DateTimeException.class},
367
368                {2008, 6, 30, null, null,                   "2008-06-30", null},
369                {2008, 6, 30, "+01:00", null,               "2008-06-30+01:00", null},
370                {2008, 6, 30, "+01:00", "Europe/Paris",     "2008-06-30+01:00", null},
371                {2008, 6, 30, null, "Europe/Paris",         "2008-06-30", null},
372
373                {123456, 6, 30, "+01:00", "Europe/Paris",   "+123456-06-30+01:00", null},
374        };
375    }
376
377    @Test(dataProvider="sample_isoDate")
378    public void test_print_isoDate(
379            Integer year, Integer month, Integer day, String offsetId, String zoneId,
380            String expected, Class<?> expectedEx) {
381        TemporalAccessor test = buildAccessor(year, month, day, null, null, null, null, offsetId, zoneId);
382        if (expectedEx == null) {
383            assertEquals(DateTimeFormatter.ISO_DATE.format(test), expected);
384        } else {
385            try {
386                DateTimeFormatter.ISO_DATE.format(test);
387                fail();
388            } catch (Exception ex) {
389                assertTrue(expectedEx.isInstance(ex));
390            }
391        }
392    }
393
394    @Test(dataProvider="sample_isoDate")
395    public void test_parse_isoDate(
396            Integer year, Integer month, Integer day, String offsetId, String zoneId,
397            String input, Class<?> invalid) {
398        if (input != null) {
399            Expected expected = createDate(year, month, day);
400            if (offsetId != null) {
401                expected.add(ZoneOffset.of(offsetId));
402            }
403            assertParseMatch(DateTimeFormatter.ISO_DATE.parseUnresolved(input, new ParsePosition(0)), expected);
404        }
405    }
406
407    @Test
408    public void test_isoDate_basics() {
409        assertEquals(DateTimeFormatter.ISO_DATE.getChronology(), IsoChronology.INSTANCE);
410        assertEquals(DateTimeFormatter.ISO_DATE.getZone(), null);
411        assertEquals(DateTimeFormatter.ISO_DATE.getResolverStyle(), ResolverStyle.STRICT);
412    }
413
414    //-----------------------------------------------------------------------
415    //-----------------------------------------------------------------------
416    //-----------------------------------------------------------------------
417    @DataProvider(name="sample_isoLocalTime")
418    Object[][] provider_sample_isoLocalTime() {
419        return new Object[][]{
420                {11, null, null, null, null, null, null, DateTimeException.class},
421                {null, 5, null, null, null, null, null, DateTimeException.class},
422                {null, null, 30, null, null, null, null, DateTimeException.class},
423                {null, null, null, 1, null, null, null, DateTimeException.class},
424                {null, null, null, null, "+01:00", null, null, DateTimeException.class},
425                {null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
426
427                {11, 5, null, null, null, null,     "11:05", null},
428                {11, 5, 30, null, null, null,       "11:05:30", null},
429                {11, 5, 30, 500000000, null, null,  "11:05:30.5", null},
430                {11, 5, 30, 1, null, null,          "11:05:30.000000001", null},
431
432                {11, 5, null, null, "+01:00", null,     "11:05", null},
433                {11, 5, 30, null, "+01:00", null,       "11:05:30", null},
434                {11, 5, 30, 500000000, "+01:00", null,  "11:05:30.5", null},
435                {11, 5, 30, 1, "+01:00", null,          "11:05:30.000000001", null},
436
437                {11, 5, null, null, "+01:00", "Europe/Paris",       "11:05", null},
438                {11, 5, 30, null, "+01:00", "Europe/Paris",         "11:05:30", null},
439                {11, 5, 30, 500000000, "+01:00", "Europe/Paris",    "11:05:30.5", null},
440                {11, 5, 30, 1, "+01:00", "Europe/Paris",            "11:05:30.000000001", null},
441
442                {11, 5, null, null, null, "Europe/Paris",       "11:05", null},
443                {11, 5, 30, null, null, "Europe/Paris",         "11:05:30", null},
444                {11, 5, 30, 500000000, null, "Europe/Paris",    "11:05:30.5", null},
445                {11, 5, 30, 1, null, "Europe/Paris",            "11:05:30.000000001", null},
446        };
447    }
448
449    @Test(dataProvider="sample_isoLocalTime")
450    public void test_print_isoLocalTime(
451            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
452            String expected, Class<?> expectedEx) {
453        TemporalAccessor test = buildAccessor(null, null, null, hour, min, sec, nano, offsetId, zoneId);
454        if (expectedEx == null) {
455            assertEquals(DateTimeFormatter.ISO_LOCAL_TIME.format(test), expected);
456        } else {
457            try {
458                DateTimeFormatter.ISO_LOCAL_TIME.format(test);
459                fail();
460            } catch (Exception ex) {
461                assertTrue(expectedEx.isInstance(ex));
462            }
463        }
464    }
465
466    @Test(dataProvider="sample_isoLocalTime")
467    public void test_parse_isoLocalTime(
468            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
469            String input, Class<?> invalid) {
470        if (input != null) {
471            Expected expected = createTime(hour, min, sec, nano);
472            // offset/zone not expected to be parsed
473            assertParseMatch(DateTimeFormatter.ISO_LOCAL_TIME.parseUnresolved(input, new ParsePosition(0)), expected);
474        }
475    }
476
477    @Test
478    public void test_isoLocalTime_basics() {
479        assertEquals(DateTimeFormatter.ISO_LOCAL_TIME.getChronology(), null);
480        assertEquals(DateTimeFormatter.ISO_LOCAL_TIME.getZone(), null);
481        assertEquals(DateTimeFormatter.ISO_LOCAL_TIME.getResolverStyle(), ResolverStyle.STRICT);
482    }
483
484    //-----------------------------------------------------------------------
485    //-----------------------------------------------------------------------
486    //-----------------------------------------------------------------------
487    @DataProvider(name="sample_isoOffsetTime")
488    Object[][] provider_sample_isoOffsetTime() {
489        return new Object[][]{
490                {11, null, null, null, null, null, null, DateTimeException.class},
491                {null, 5, null, null, null, null, null, DateTimeException.class},
492                {null, null, 30, null, null, null, null, DateTimeException.class},
493                {null, null, null, 1, null, null, null, DateTimeException.class},
494                {null, null, null, null, "+01:00", null, null, DateTimeException.class},
495                {null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
496
497                {11, 5, null, null, null, null,     null, DateTimeException.class},
498                {11, 5, 30, null, null, null,       null, DateTimeException.class},
499                {11, 5, 30, 500000000, null, null,  null, DateTimeException.class},
500                {11, 5, 30, 1, null, null,          null, DateTimeException.class},
501
502                {11, 5, null, null, "+01:00", null,     "11:05+01:00", null},
503                {11, 5, 30, null, "+01:00", null,       "11:05:30+01:00", null},
504                {11, 5, 30, 500000000, "+01:00", null,  "11:05:30.5+01:00", null},
505                {11, 5, 30, 1, "+01:00", null,          "11:05:30.000000001+01:00", null},
506
507                {11, 5, null, null, "+01:00", "Europe/Paris",       "11:05+01:00", null},
508                {11, 5, 30, null, "+01:00", "Europe/Paris",         "11:05:30+01:00", null},
509                {11, 5, 30, 500000000, "+01:00", "Europe/Paris",    "11:05:30.5+01:00", null},
510                {11, 5, 30, 1, "+01:00", "Europe/Paris",            "11:05:30.000000001+01:00", null},
511
512                {11, 5, null, null, null, "Europe/Paris",       null, DateTimeException.class},
513                {11, 5, 30, null, null, "Europe/Paris",         null, DateTimeException.class},
514                {11, 5, 30, 500000000, null, "Europe/Paris",    null, DateTimeException.class},
515                {11, 5, 30, 1, null, "Europe/Paris",            null, DateTimeException.class},
516        };
517    }
518
519    @Test(dataProvider="sample_isoOffsetTime")
520    public void test_print_isoOffsetTime(
521            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
522            String expected, Class<?> expectedEx) {
523        TemporalAccessor test = buildAccessor(null, null, null, hour, min, sec, nano, offsetId, zoneId);
524        if (expectedEx == null) {
525            assertEquals(DateTimeFormatter.ISO_OFFSET_TIME.format(test), expected);
526        } else {
527            try {
528                DateTimeFormatter.ISO_OFFSET_TIME.format(test);
529                fail();
530            } catch (Exception ex) {
531                assertTrue(expectedEx.isInstance(ex));
532            }
533        }
534    }
535
536    @Test(dataProvider="sample_isoOffsetTime")
537    public void test_parse_isoOffsetTime(
538            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
539            String input, Class<?> invalid) {
540        if (input != null) {
541            Expected expected = createTime(hour, min, sec, nano);
542            buildCalendrical(expected, offsetId, null);  // zoneId is not expected from parse
543            assertParseMatch(DateTimeFormatter.ISO_OFFSET_TIME.parseUnresolved(input, new ParsePosition(0)), expected);
544        }
545    }
546
547    @Test
548    public void test_isoOffsetTime_basics() {
549        assertEquals(DateTimeFormatter.ISO_OFFSET_TIME.getChronology(), null);
550        assertEquals(DateTimeFormatter.ISO_OFFSET_TIME.getZone(), null);
551        assertEquals(DateTimeFormatter.ISO_OFFSET_TIME.getResolverStyle(), ResolverStyle.STRICT);
552    }
553
554    //-----------------------------------------------------------------------
555    //-----------------------------------------------------------------------
556    //-----------------------------------------------------------------------
557    @DataProvider(name="sample_isoTime")
558    Object[][] provider_sample_isoTime() {
559        return new Object[][]{
560                {11, null, null, null, null, null, null, DateTimeException.class},
561                {null, 5, null, null, null, null, null, DateTimeException.class},
562                {null, null, 30, null, null, null, null, DateTimeException.class},
563                {null, null, null, 1, null, null, null, DateTimeException.class},
564                {null, null, null, null, "+01:00", null, null, DateTimeException.class},
565                {null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
566
567                {11, 5, null, null, null, null,     "11:05", null},
568                {11, 5, 30, null, null, null,       "11:05:30", null},
569                {11, 5, 30, 500000000, null, null,  "11:05:30.5", null},
570                {11, 5, 30, 1, null, null,          "11:05:30.000000001", null},
571
572                {11, 5, null, null, "+01:00", null,     "11:05+01:00", null},
573                {11, 5, 30, null, "+01:00", null,       "11:05:30+01:00", null},
574                {11, 5, 30, 500000000, "+01:00", null,  "11:05:30.5+01:00", null},
575                {11, 5, 30, 1, "+01:00", null,          "11:05:30.000000001+01:00", null},
576
577                {11, 5, null, null, "+01:00", "Europe/Paris",       "11:05+01:00", null},
578                {11, 5, 30, null, "+01:00", "Europe/Paris",         "11:05:30+01:00", null},
579                {11, 5, 30, 500000000, "+01:00", "Europe/Paris",    "11:05:30.5+01:00", null},
580                {11, 5, 30, 1, "+01:00", "Europe/Paris",            "11:05:30.000000001+01:00", null},
581
582                {11, 5, null, null, null, "Europe/Paris",       "11:05", null},
583                {11, 5, 30, null, null, "Europe/Paris",         "11:05:30", null},
584                {11, 5, 30, 500000000, null, "Europe/Paris",    "11:05:30.5", null},
585                {11, 5, 30, 1, null, "Europe/Paris",            "11:05:30.000000001", null},
586        };
587    }
588
589    @Test(dataProvider="sample_isoTime")
590    public void test_print_isoTime(
591            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
592            String expected, Class<?> expectedEx) {
593        TemporalAccessor test = buildAccessor(null, null, null, hour, min, sec, nano, offsetId, zoneId);
594        if (expectedEx == null) {
595            assertEquals(DateTimeFormatter.ISO_TIME.format(test), expected);
596        } else {
597            try {
598                DateTimeFormatter.ISO_TIME.format(test);
599                fail();
600            } catch (Exception ex) {
601                assertTrue(expectedEx.isInstance(ex));
602            }
603        }
604    }
605
606    @Test(dataProvider="sample_isoTime")
607    public void test_parse_isoTime(
608            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
609            String input, Class<?> invalid) {
610        if (input != null) {
611            Expected expected = createTime(hour, min, sec, nano);
612            if (offsetId != null) {
613                expected.add(ZoneOffset.of(offsetId));
614            }
615            assertParseMatch(DateTimeFormatter.ISO_TIME.parseUnresolved(input, new ParsePosition(0)), expected);
616        }
617    }
618
619    @Test
620    public void test_isoTime_basics() {
621        assertEquals(DateTimeFormatter.ISO_TIME.getChronology(), null);
622        assertEquals(DateTimeFormatter.ISO_TIME.getZone(), null);
623        assertEquals(DateTimeFormatter.ISO_TIME.getResolverStyle(), ResolverStyle.STRICT);
624    }
625
626    //-----------------------------------------------------------------------
627    //-----------------------------------------------------------------------
628    //-----------------------------------------------------------------------
629    @DataProvider(name="sample_isoLocalDateTime")
630    Object[][] provider_sample_isoLocalDateTime() {
631        return new Object[][]{
632                {2008, null, null, null, null, null, null, null, null, null, DateTimeException.class},
633                {null, 6, null, null, null, null, null, null, null, null, DateTimeException.class},
634                {null, null, 30, null, null, null, null, null, null, null, DateTimeException.class},
635                {null, null, null, 11, null, null, null, null, null, null, DateTimeException.class},
636                {null, null, null, null, 5, null, null, null, null, null, DateTimeException.class},
637                {null, null, null, null, null, null, null, "+01:00", null, null, DateTimeException.class},
638                {null, null, null, null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
639                {2008, 6, 30, 11, null, null, null, null, null, null, DateTimeException.class},
640                {2008, 6, 30, null, 5, null, null, null, null, null, DateTimeException.class},
641                {2008, 6, null, 11, 5, null, null, null, null, null, DateTimeException.class},
642                {2008, null, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
643                {null, 6, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
644
645                {2008, 6, 30, 11, 5, null, null, null, null,                    "2008-06-30T11:05", null},
646                {2008, 6, 30, 11, 5, 30, null, null, null,                      "2008-06-30T11:05:30", null},
647                {2008, 6, 30, 11, 5, 30, 500000000, null, null,                 "2008-06-30T11:05:30.5", null},
648                {2008, 6, 30, 11, 5, 30, 1, null, null,                         "2008-06-30T11:05:30.000000001", null},
649
650                {2008, 6, 30, 11, 5, null, null, "+01:00", null,                "2008-06-30T11:05", null},
651                {2008, 6, 30, 11, 5, 30, null, "+01:00", null,                  "2008-06-30T11:05:30", null},
652                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", null,             "2008-06-30T11:05:30.5", null},
653                {2008, 6, 30, 11, 5, 30, 1, "+01:00", null,                     "2008-06-30T11:05:30.000000001", null},
654
655                {2008, 6, 30, 11, 5, null, null, "+01:00", "Europe/Paris",      "2008-06-30T11:05", null},
656                {2008, 6, 30, 11, 5, 30, null, "+01:00", "Europe/Paris",        "2008-06-30T11:05:30", null},
657                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", "Europe/Paris",   "2008-06-30T11:05:30.5", null},
658                {2008, 6, 30, 11, 5, 30, 1, "+01:00", "Europe/Paris",           "2008-06-30T11:05:30.000000001", null},
659
660                {2008, 6, 30, 11, 5, null, null, null, "Europe/Paris",          "2008-06-30T11:05", null},
661                {2008, 6, 30, 11, 5, 30, null, null, "Europe/Paris",            "2008-06-30T11:05:30", null},
662                {2008, 6, 30, 11, 5, 30, 500000000, null, "Europe/Paris",       "2008-06-30T11:05:30.5", null},
663                {2008, 6, 30, 11, 5, 30, 1, null, "Europe/Paris",               "2008-06-30T11:05:30.000000001", null},
664
665                {123456, 6, 30, 11, 5, null, null, null, null,                  "+123456-06-30T11:05", null},
666        };
667    }
668
669    @Test(dataProvider="sample_isoLocalDateTime")
670    public void test_print_isoLocalDateTime(
671            Integer year, Integer month, Integer day,
672            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
673            String expected, Class<?> expectedEx) {
674        TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId);
675        if (expectedEx == null) {
676            assertEquals(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(test), expected);
677        } else {
678            try {
679                DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(test);
680                fail();
681            } catch (Exception ex) {
682                assertTrue(expectedEx.isInstance(ex));
683            }
684        }
685    }
686
687    @Test(dataProvider="sample_isoLocalDateTime")
688    public void test_parse_isoLocalDateTime(
689            Integer year, Integer month, Integer day,
690            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
691            String input, Class<?> invalid) {
692        if (input != null) {
693            Expected expected = createDateTime(year, month, day, hour, min, sec, nano);
694            assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected);
695        }
696    }
697
698    @Test
699    public void test_isoLocalDateTime_basics() {
700        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
701        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE_TIME.getZone(), null);
702        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE_TIME.getResolverStyle(), ResolverStyle.STRICT);
703    }
704
705    //-----------------------------------------------------------------------
706    //-----------------------------------------------------------------------
707    //-----------------------------------------------------------------------
708    @DataProvider(name="sample_isoOffsetDateTime")
709    Object[][] provider_sample_isoOffsetDateTime() {
710        return new Object[][]{
711                {2008, null, null, null, null, null, null, null, null, null, DateTimeException.class},
712                {null, 6, null, null, null, null, null, null, null, null, DateTimeException.class},
713                {null, null, 30, null, null, null, null, null, null, null, DateTimeException.class},
714                {null, null, null, 11, null, null, null, null, null, null, DateTimeException.class},
715                {null, null, null, null, 5, null, null, null, null, null, DateTimeException.class},
716                {null, null, null, null, null, null, null, "+01:00", null, null, DateTimeException.class},
717                {null, null, null, null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
718                {2008, 6, 30, 11, null, null, null, null, null, null, DateTimeException.class},
719                {2008, 6, 30, null, 5, null, null, null, null, null, DateTimeException.class},
720                {2008, 6, null, 11, 5, null, null, null, null, null, DateTimeException.class},
721                {2008, null, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
722                {null, 6, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
723
724                {2008, 6, 30, 11, 5, null, null, null, null,                    null, DateTimeException.class},
725                {2008, 6, 30, 11, 5, 30, null, null, null,                      null, DateTimeException.class},
726                {2008, 6, 30, 11, 5, 30, 500000000, null, null,                 null, DateTimeException.class},
727                {2008, 6, 30, 11, 5, 30, 1, null, null,                         null, DateTimeException.class},
728
729                {2008, 6, 30, 11, 5, null, null, "+01:00", null,                "2008-06-30T11:05+01:00", null},
730                {2008, 6, 30, 11, 5, 30, null, "+01:00", null,                  "2008-06-30T11:05:30+01:00", null},
731                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", null,             "2008-06-30T11:05:30.5+01:00", null},
732                {2008, 6, 30, 11, 5, 30, 1, "+01:00", null,                     "2008-06-30T11:05:30.000000001+01:00", null},
733
734                {2008, 6, 30, 11, 5, null, null, "+01:00", "Europe/Paris",      "2008-06-30T11:05+01:00", null},
735                {2008, 6, 30, 11, 5, 30, null, "+01:00", "Europe/Paris",        "2008-06-30T11:05:30+01:00", null},
736                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", "Europe/Paris",   "2008-06-30T11:05:30.5+01:00", null},
737                {2008, 6, 30, 11, 5, 30, 1, "+01:00", "Europe/Paris",           "2008-06-30T11:05:30.000000001+01:00", null},
738
739                {2008, 6, 30, 11, 5, null, null, null, "Europe/Paris",          null, DateTimeException.class},
740                {2008, 6, 30, 11, 5, 30, null, null, "Europe/Paris",            null, DateTimeException.class},
741                {2008, 6, 30, 11, 5, 30, 500000000, null, "Europe/Paris",       null, DateTimeException.class},
742                {2008, 6, 30, 11, 5, 30, 1, null, "Europe/Paris",               null, DateTimeException.class},
743
744                {123456, 6, 30, 11, 5, null, null, "+01:00", null,              "+123456-06-30T11:05+01:00", null},
745        };
746    }
747
748    @Test(dataProvider="sample_isoOffsetDateTime")
749    public void test_print_isoOffsetDateTime(
750            Integer year, Integer month, Integer day,
751            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
752            String expected, Class<?> expectedEx) {
753        TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId);
754        if (expectedEx == null) {
755            assertEquals(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(test), expected);
756        } else {
757            try {
758                DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(test);
759                fail();
760            } catch (Exception ex) {
761                assertTrue(expectedEx.isInstance(ex));
762            }
763        }
764    }
765
766    @Test(dataProvider="sample_isoOffsetDateTime")
767    public void test_parse_isoOffsetDateTime(
768            Integer year, Integer month, Integer day,
769            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
770            String input, Class<?> invalid) {
771        if (input != null) {
772            Expected expected = createDateTime(year, month, day, hour, min, sec, nano);
773            buildCalendrical(expected, offsetId, null);  // zone not expected to be parsed
774            assertParseMatch(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected);
775        }
776    }
777
778    @Test
779    public void test_isoOffsetDateTime_basics() {
780        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
781        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE_TIME.getZone(), null);
782        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE_TIME.getResolverStyle(), ResolverStyle.STRICT);
783    }
784
785    //-----------------------------------------------------------------------
786    //-----------------------------------------------------------------------
787    //-----------------------------------------------------------------------
788    @DataProvider(name="sample_isoZonedDateTime")
789    Object[][] provider_sample_isoZonedDateTime() {
790        return new Object[][]{
791                {2008, null, null, null, null, null, null, null, null, null, DateTimeException.class},
792                {null, 6, null, null, null, null, null, null, null, null, DateTimeException.class},
793                {null, null, 30, null, null, null, null, null, null, null, DateTimeException.class},
794                {null, null, null, 11, null, null, null, null, null, null, DateTimeException.class},
795                {null, null, null, null, 5, null, null, null, null, null, DateTimeException.class},
796                {null, null, null, null, null, null, null, "+01:00", null, null, DateTimeException.class},
797                {null, null, null, null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
798                {2008, 6, 30, 11, null, null, null, null, null, null, DateTimeException.class},
799                {2008, 6, 30, null, 5, null, null, null, null, null, DateTimeException.class},
800                {2008, 6, null, 11, 5, null, null, null, null, null, DateTimeException.class},
801                {2008, null, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
802                {null, 6, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
803
804                {2008, 6, 30, 11, 5, null, null, null, null,                    null, DateTimeException.class},
805                {2008, 6, 30, 11, 5, 30, null, null, null,                      null, DateTimeException.class},
806                {2008, 6, 30, 11, 5, 30, 500000000, null, null,                 null, DateTimeException.class},
807                {2008, 6, 30, 11, 5, 30, 1, null, null,                         null, DateTimeException.class},
808
809                // allow OffsetDateTime (no harm comes of this AFAICT)
810                {2008, 6, 30, 11, 5, null, null, "+01:00", null,                "2008-06-30T11:05+01:00", null},
811                {2008, 6, 30, 11, 5, 30, null, "+01:00", null,                  "2008-06-30T11:05:30+01:00", null},
812                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", null,             "2008-06-30T11:05:30.5+01:00", null},
813                {2008, 6, 30, 11, 5, 30, 1, "+01:00", null,                     "2008-06-30T11:05:30.000000001+01:00", null},
814
815                // ZonedDateTime with ZoneId of ZoneOffset
816                {2008, 6, 30, 11, 5, null, null, "+01:00", "+01:00",            "2008-06-30T11:05+01:00", null},
817                {2008, 6, 30, 11, 5, 30, null, "+01:00", "+01:00",              "2008-06-30T11:05:30+01:00", null},
818                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", "+01:00",         "2008-06-30T11:05:30.5+01:00", null},
819                {2008, 6, 30, 11, 5, 30, 1, "+01:00", "+01:00",                 "2008-06-30T11:05:30.000000001+01:00", null},
820
821                // ZonedDateTime with ZoneId of ZoneRegion
822                {2008, 6, 30, 11, 5, null, null, "+01:00", "Europe/Paris",      "2008-06-30T11:05+01:00[Europe/Paris]", null},
823                {2008, 6, 30, 11, 5, 30, null, "+01:00", "Europe/Paris",        "2008-06-30T11:05:30+01:00[Europe/Paris]", null},
824                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", "Europe/Paris",   "2008-06-30T11:05:30.5+01:00[Europe/Paris]", null},
825                {2008, 6, 30, 11, 5, 30, 1, "+01:00", "Europe/Paris",           "2008-06-30T11:05:30.000000001+01:00[Europe/Paris]", null},
826
827                // offset required
828                {2008, 6, 30, 11, 5, null, null, null, "Europe/Paris",          null, DateTimeException.class},
829                {2008, 6, 30, 11, 5, 30, null, null, "Europe/Paris",            null, DateTimeException.class},
830                {2008, 6, 30, 11, 5, 30, 500000000, null, "Europe/Paris",       null, DateTimeException.class},
831                {2008, 6, 30, 11, 5, 30, 1, null, "Europe/Paris",               null, DateTimeException.class},
832
833                {123456, 6, 30, 11, 5, null, null, "+01:00", "Europe/Paris",    "+123456-06-30T11:05+01:00[Europe/Paris]", null},
834        };
835    }
836
837    @Test(dataProvider="sample_isoZonedDateTime")
838    public void test_print_isoZonedDateTime(
839            Integer year, Integer month, Integer day,
840            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
841            String expected, Class<?> expectedEx) {
842        TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId);
843        if (expectedEx == null) {
844            assertEquals(DateTimeFormatter.ISO_ZONED_DATE_TIME.format(test), expected);
845        } else {
846            try {
847                DateTimeFormatter.ISO_ZONED_DATE_TIME.format(test);
848                fail(test.toString());
849            } catch (Exception ex) {
850                assertTrue(expectedEx.isInstance(ex));
851            }
852        }
853    }
854
855    @Test(dataProvider="sample_isoZonedDateTime")
856    public void test_parse_isoZonedDateTime(
857            Integer year, Integer month, Integer day,
858            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
859            String input, Class<?> invalid) {
860        if (input != null) {
861            Expected expected = createDateTime(year, month, day, hour, min, sec, nano);
862            if (offsetId.equals(zoneId)) {
863                buildCalendrical(expected, offsetId, null);
864            } else {
865                buildCalendrical(expected, offsetId, zoneId);
866            }
867            assertParseMatch(DateTimeFormatter.ISO_ZONED_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected);
868        }
869    }
870
871    @Test
872    public void test_isoZonedDateTime_basics() {
873        assertEquals(DateTimeFormatter.ISO_ZONED_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
874        assertEquals(DateTimeFormatter.ISO_ZONED_DATE_TIME.getZone(), null);
875        assertEquals(DateTimeFormatter.ISO_ZONED_DATE_TIME.getResolverStyle(), ResolverStyle.STRICT);
876    }
877
878    //-----------------------------------------------------------------------
879    //-----------------------------------------------------------------------
880    //-----------------------------------------------------------------------
881    @DataProvider(name="sample_isoDateTime")
882    Object[][] provider_sample_isoDateTime() {
883        return new Object[][]{
884                {2008, null, null, null, null, null, null, null, null, null, DateTimeException.class},
885                {null, 6, null, null, null, null, null, null, null, null, DateTimeException.class},
886                {null, null, 30, null, null, null, null, null, null, null, DateTimeException.class},
887                {null, null, null, 11, null, null, null, null, null, null, DateTimeException.class},
888                {null, null, null, null, 5, null, null, null, null, null, DateTimeException.class},
889                {null, null, null, null, null, null, null, "+01:00", null, null, DateTimeException.class},
890                {null, null, null, null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
891                {2008, 6, 30, 11, null, null, null, null, null, null, DateTimeException.class},
892                {2008, 6, 30, null, 5, null, null, null, null, null, DateTimeException.class},
893                {2008, 6, null, 11, 5, null, null, null, null, null, DateTimeException.class},
894                {2008, null, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
895                {null, 6, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
896
897                {2008, 6, 30, 11, 5, null, null, null, null,                    "2008-06-30T11:05", null},
898                {2008, 6, 30, 11, 5, 30, null, null, null,                      "2008-06-30T11:05:30", null},
899                {2008, 6, 30, 11, 5, 30, 500000000, null, null,                 "2008-06-30T11:05:30.5", null},
900                {2008, 6, 30, 11, 5, 30, 1, null, null,                         "2008-06-30T11:05:30.000000001", null},
901
902                {2008, 6, 30, 11, 5, null, null, "+01:00", null,                "2008-06-30T11:05+01:00", null},
903                {2008, 6, 30, 11, 5, 30, null, "+01:00", null,                  "2008-06-30T11:05:30+01:00", null},
904                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", null,             "2008-06-30T11:05:30.5+01:00", null},
905                {2008, 6, 30, 11, 5, 30, 1, "+01:00", null,                     "2008-06-30T11:05:30.000000001+01:00", null},
906
907                {2008, 6, 30, 11, 5, null, null, "+01:00", "Europe/Paris",      "2008-06-30T11:05+01:00[Europe/Paris]", null},
908                {2008, 6, 30, 11, 5, 30, null, "+01:00", "Europe/Paris",        "2008-06-30T11:05:30+01:00[Europe/Paris]", null},
909                {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", "Europe/Paris",   "2008-06-30T11:05:30.5+01:00[Europe/Paris]", null},
910                {2008, 6, 30, 11, 5, 30, 1, "+01:00", "Europe/Paris",           "2008-06-30T11:05:30.000000001+01:00[Europe/Paris]", null},
911
912                {2008, 6, 30, 11, 5, null, null, null, "Europe/Paris",          "2008-06-30T11:05", null},
913                {2008, 6, 30, 11, 5, 30, null, null, "Europe/Paris",            "2008-06-30T11:05:30", null},
914                {2008, 6, 30, 11, 5, 30, 500000000, null, "Europe/Paris",       "2008-06-30T11:05:30.5", null},
915                {2008, 6, 30, 11, 5, 30, 1, null, "Europe/Paris",               "2008-06-30T11:05:30.000000001", null},
916
917                {123456, 6, 30, 11, 5, null, null, null, null,                  "+123456-06-30T11:05", null},
918        };
919    }
920
921    @Test(dataProvider="sample_isoDateTime")
922    public void test_print_isoDateTime(
923            Integer year, Integer month, Integer day,
924            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
925            String expected, Class<?> expectedEx) {
926        TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId);
927        if (expectedEx == null) {
928            assertEquals(DateTimeFormatter.ISO_DATE_TIME.format(test), expected);
929        } else {
930            try {
931                DateTimeFormatter.ISO_DATE_TIME.format(test);
932                fail();
933            } catch (Exception ex) {
934                assertTrue(expectedEx.isInstance(ex));
935            }
936        }
937    }
938
939    @Test(dataProvider="sample_isoDateTime")
940    public void test_parse_isoDateTime(
941            Integer year, Integer month, Integer day,
942            Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId,
943            String input, Class<?> invalid) {
944        if (input != null) {
945            Expected expected = createDateTime(year, month, day, hour, min, sec, nano);
946            if (offsetId != null) {
947                expected.add(ZoneOffset.of(offsetId));
948                if (zoneId != null) {
949                    expected.zone = ZoneId.of(zoneId);
950                }
951            }
952            assertParseMatch(DateTimeFormatter.ISO_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected);
953        }
954    }
955
956    @Test
957    public void test_isoDateTime_basics() {
958        assertEquals(DateTimeFormatter.ISO_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
959        assertEquals(DateTimeFormatter.ISO_DATE_TIME.getZone(), null);
960        assertEquals(DateTimeFormatter.ISO_DATE_TIME.getResolverStyle(), ResolverStyle.STRICT);
961    }
962
963    //-----------------------------------------------------------------------
964    //-----------------------------------------------------------------------
965    //-----------------------------------------------------------------------
966    @Test
967    public void test_print_isoOrdinalDate() {
968        TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), null, null);
969        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-155");
970    }
971
972    @Test
973    public void test_print_isoOrdinalDate_offset() {
974        TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "Z", null);
975        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-155Z");
976    }
977
978    @Test
979    public void test_print_isoOrdinalDate_zoned() {
980        TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "+02:00", "Europe/Paris");
981        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-155+02:00");
982    }
983
984    @Test
985    public void test_print_isoOrdinalDate_zoned_largeYear() {
986        TemporalAccessor test = buildAccessor(LocalDateTime.of(123456, 6, 3, 11, 5, 30), "Z", null);
987        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "+123456-155Z");
988    }
989
990    @Test
991    public void test_print_isoOrdinalDate_fields() {
992        // mock for testing that does not fully comply with TemporalAccessor contract
993        TemporalAccessor test = new TemporalAccessor() {
994            @Override
995            public boolean isSupported(TemporalField field) {
996                return field == YEAR || field == DAY_OF_YEAR;
997            }
998            @Override
999            public long getLong(TemporalField field) {
1000                if (field == YEAR) {
1001                    return 2008;
1002                }
1003                if (field == DAY_OF_YEAR) {
1004                    return 231;
1005                }
1006                throw new DateTimeException("Unsupported");
1007            }
1008        };
1009        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-231");
1010    }
1011
1012    @Test(expectedExceptions=DateTimeException.class)
1013    public void test_print_isoOrdinalDate_missingField() {
1014        TemporalAccessor test = Year.of(2008);
1015        DateTimeFormatter.ISO_ORDINAL_DATE.format(test);
1016    }
1017
1018    //-----------------------------------------------------------------------
1019    @Test
1020    public void test_parse_isoOrdinalDate() {
1021        Expected expected = new Expected(YEAR, 2008, DAY_OF_YEAR, 123);
1022        assertParseMatch(DateTimeFormatter.ISO_ORDINAL_DATE.parseUnresolved("2008-123", new ParsePosition(0)), expected);
1023    }
1024
1025    @Test
1026    public void test_parse_isoOrdinalDate_largeYear() {
1027        Expected expected = new Expected(YEAR, 123456, DAY_OF_YEAR, 123);
1028        assertParseMatch(DateTimeFormatter.ISO_ORDINAL_DATE.parseUnresolved("+123456-123", new ParsePosition(0)), expected);
1029    }
1030
1031    @Test
1032    public void test_isoOrdinalDate_basics() {
1033        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.getChronology(), IsoChronology.INSTANCE);
1034        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.getZone(), null);
1035        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.getResolverStyle(), ResolverStyle.STRICT);
1036    }
1037
1038    //-----------------------------------------------------------------------
1039    //-----------------------------------------------------------------------
1040    //-----------------------------------------------------------------------
1041    @Test
1042    public void test_print_basicIsoDate() {
1043        TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), null, null);
1044        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603");
1045    }
1046
1047    @Test
1048    public void test_print_basicIsoDate_offset() {
1049        TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "Z", null);
1050        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603Z");
1051    }
1052
1053    @Test
1054    public void test_print_basicIsoDate_zoned() {
1055        TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "+02:00", "Europe/Paris");
1056        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603+0200");
1057    }
1058
1059    @Test(expectedExceptions=DateTimeException.class)
1060    public void test_print_basicIsoDate_largeYear() {
1061        TemporalAccessor test = buildAccessor(LocalDateTime.of(123456, 6, 3, 11, 5, 30), "Z", null);
1062        DateTimeFormatter.BASIC_ISO_DATE.format(test);
1063    }
1064
1065    @Test
1066    public void test_print_basicIsoDate_fields() {
1067        TemporalAccessor test = buildAccessor(LocalDate.of(2008, 6, 3), null, null);
1068        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603");
1069    }
1070
1071    @Test(expectedExceptions=DateTimeException.class)
1072    public void test_print_basicIsoDate_missingField() {
1073        TemporalAccessor test = YearMonth.of(2008, 6);
1074        DateTimeFormatter.BASIC_ISO_DATE.format(test);
1075    }
1076
1077    //-----------------------------------------------------------------------
1078    @Test
1079    public void test_parse_basicIsoDate() {
1080        LocalDate expected = LocalDate.of(2008, 6, 3);
1081        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.parse("20080603", LocalDate::from), expected);
1082    }
1083
1084    @Test(expectedExceptions=DateTimeParseException.class)
1085    public void test_parse_basicIsoDate_largeYear() {
1086        try {
1087            LocalDate expected = LocalDate.of(123456, 6, 3);
1088            assertEquals(DateTimeFormatter.BASIC_ISO_DATE.parse("+1234560603", LocalDate::from), expected);
1089        } catch (DateTimeParseException ex) {
1090            assertEquals(ex.getErrorIndex(), 0);
1091            assertEquals(ex.getParsedString(), "+1234560603");
1092            throw ex;
1093        }
1094    }
1095
1096    @Test
1097    public void test_basicIsoDate_basics() {
1098        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.getChronology(), IsoChronology.INSTANCE);
1099        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.getZone(), null);
1100        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.getResolverStyle(), ResolverStyle.STRICT);
1101    }
1102
1103    //-----------------------------------------------------------------------
1104    //-----------------------------------------------------------------------
1105    //-----------------------------------------------------------------------
1106    @DataProvider(name="weekDate")
1107    Iterator<Object[]> weekDate() {
1108        return new Iterator<Object[]>() {
1109            private ZonedDateTime date = ZonedDateTime.of(LocalDateTime.of(2003, 12, 29, 11, 5, 30), ZoneId.of("Europe/Paris"));
1110            private ZonedDateTime endDate = date.withYear(2005).withMonth(1).withDayOfMonth(2);
1111            private int week = 1;
1112            private int day = 1;
1113
1114            public boolean hasNext() {
1115                return !date.isAfter(endDate);
1116            }
1117            public Object[] next() {
1118                StringBuilder sb = new StringBuilder("2004-W");
1119                if (week < 10) {
1120                    sb.append('0');
1121                }
1122                sb.append(week).append('-').append(day).append(date.getOffset());
1123                Object[] ret = new Object[] {date, sb.toString()};
1124                date = date.plusDays(1);
1125                day += 1;
1126                if (day == 8) {
1127                    day = 1;
1128                    week++;
1129                }
1130                return ret;
1131            }
1132            public void remove() {
1133                throw new UnsupportedOperationException();
1134            }
1135        };
1136    }
1137
1138    @Test(dataProvider="weekDate")
1139    public void test_print_isoWeekDate(TemporalAccessor test, String expected) {
1140        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.format(test), expected);
1141    }
1142
1143    @Test
1144    public void test_print_isoWeekDate_zoned_largeYear() {
1145        TemporalAccessor test = buildAccessor(LocalDateTime.of(123456, 6, 3, 11, 5, 30), "Z", null);
1146        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.format(test), "+123456-W23-2Z");
1147    }
1148
1149    @Test
1150    public void test_print_isoWeekDate_fields() {
1151        TemporalAccessor test = buildAccessor(LocalDate.of(2004, 1, 27), null, null);
1152        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.format(test), "2004-W05-2");
1153    }
1154
1155    @Test(expectedExceptions=DateTimeException.class)
1156    public void test_print_isoWeekDate_missingField() {
1157        TemporalAccessor test = YearMonth.of(2008, 6);
1158        DateTimeFormatter.ISO_WEEK_DATE.format(test);
1159    }
1160
1161    //-----------------------------------------------------------------------
1162    @Test
1163    public void test_parse_weekDate() {
1164        LocalDate expected = LocalDate.of(2004, 1, 28);
1165        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.parse("2004-W05-3", LocalDate::from), expected);
1166    }
1167
1168    @Test
1169    public void test_parse_weekDate_largeYear() {
1170        TemporalAccessor parsed = DateTimeFormatter.ISO_WEEK_DATE.parseUnresolved("+123456-W04-5", new ParsePosition(0));
1171        assertEquals(parsed.getLong(IsoFields.WEEK_BASED_YEAR), 123456L);
1172        assertEquals(parsed.getLong(IsoFields.WEEK_OF_WEEK_BASED_YEAR), 4L);
1173        assertEquals(parsed.getLong(DAY_OF_WEEK), 5L);
1174    }
1175
1176    @Test
1177    public void test_isoWeekDate_basics() {
1178        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.getChronology(), IsoChronology.INSTANCE);
1179        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.getZone(), null);
1180        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.getResolverStyle(), ResolverStyle.STRICT);
1181    }
1182
1183    //-----------------------------------------------------------------------
1184    //-----------------------------------------------------------------------
1185    //-----------------------------------------------------------------------
1186    @DataProvider(name="sample_isoInstant")
1187    Object[][] provider_sample_isoInstant() {
1188        return new Object[][]{
1189                {0, 0, "1970-01-01T00:00:00Z", null},
1190                {0, null, "1970-01-01T00:00:00Z", null},
1191                {0, -1, null, DateTimeException.class},
1192
1193                {-1, 0, "1969-12-31T23:59:59Z", null},
1194                {1, 0, "1970-01-01T00:00:01Z", null},
1195                {60, 0, "1970-01-01T00:01:00Z", null},
1196                {3600, 0, "1970-01-01T01:00:00Z", null},
1197                {86400, 0, "1970-01-02T00:00:00Z", null},
1198
1199                {0, 1, "1970-01-01T00:00:00.000000001Z", null},
1200                {0, 2, "1970-01-01T00:00:00.000000002Z", null},
1201                {0, 10, "1970-01-01T00:00:00.000000010Z", null},
1202                {0, 100, "1970-01-01T00:00:00.000000100Z", null},
1203        };
1204    }
1205
1206    @Test(dataProvider="sample_isoInstant")
1207    public void test_print_isoInstant(
1208            long instantSecs, Integer nano, String expected, Class<?> expectedEx) {
1209        TemporalAccessor test = buildAccessorInstant(instantSecs, nano);
1210        if (expectedEx == null) {
1211            assertEquals(DateTimeFormatter.ISO_INSTANT.format(test), expected);
1212        } else {
1213            try {
1214                DateTimeFormatter.ISO_INSTANT.format(test);
1215                fail();
1216            } catch (Exception ex) {
1217                assertTrue(expectedEx.isInstance(ex));
1218            }
1219        }
1220    }
1221
1222    @Test(dataProvider="sample_isoInstant")
1223    public void test_parse_isoInstant(
1224            long instantSecs, Integer nano, String input, Class<?> invalid) {
1225        if (input != null) {
1226            TemporalAccessor parsed = DateTimeFormatter.ISO_INSTANT.parseUnresolved(input, new ParsePosition(0));
1227            assertEquals(parsed.getLong(INSTANT_SECONDS), instantSecs);
1228            assertEquals(parsed.getLong(NANO_OF_SECOND), (nano == null ? 0 : nano));
1229        }
1230    }
1231
1232    @Test
1233    public void test_isoInstant_basics() {
1234        assertEquals(DateTimeFormatter.ISO_INSTANT.getChronology(), null);
1235        assertEquals(DateTimeFormatter.ISO_INSTANT.getZone(), null);
1236        assertEquals(DateTimeFormatter.ISO_INSTANT.getResolverStyle(), ResolverStyle.STRICT);
1237    }
1238
1239    //-----------------------------------------------------------------------
1240    //-----------------------------------------------------------------------
1241    //-----------------------------------------------------------------------
1242    @DataProvider(name="rfc")
1243    Object[][] data_rfc() {
1244        return new Object[][] {
1245            {LocalDateTime.of(2008, 6, 3, 11, 5, 30), "Z", "Tue, 3 Jun 2008 11:05:30 GMT"},
1246            {LocalDateTime.of(2008, 6, 30, 11, 5, 30), "Z", "Mon, 30 Jun 2008 11:05:30 GMT"},
1247            {LocalDateTime.of(2008, 6, 3, 11, 5, 30), "+02:00", "Tue, 3 Jun 2008 11:05:30 +0200"},
1248            {LocalDateTime.of(2008, 6, 30, 11, 5, 30), "-03:00", "Mon, 30 Jun 2008 11:05:30 -0300"},
1249        };
1250    }
1251
1252    @Test(dataProvider="rfc")
1253    public void test_print_rfc1123(LocalDateTime base, String offsetId, String expected) {
1254        TemporalAccessor test = buildAccessor(base, offsetId, null);
1255        assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.format(test), expected);
1256    }
1257
1258    @Test(dataProvider="rfc")
1259    public void test_print_rfc1123_french(LocalDateTime base, String offsetId, String expected) {
1260        TemporalAccessor test = buildAccessor(base, offsetId, null);
1261        assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.FRENCH).format(test), expected);
1262    }
1263
1264    @Test(expectedExceptions=DateTimeException.class)
1265    public void test_print_rfc1123_missingField() {
1266        TemporalAccessor test = YearMonth.of(2008, 6);
1267        DateTimeFormatter.RFC_1123_DATE_TIME.format(test);
1268    }
1269
1270    @Test
1271    public void test_rfc1123_basics() {
1272        assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
1273        assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.getZone(), null);
1274        assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.getResolverStyle(), ResolverStyle.SMART);
1275    }
1276
1277    //-----------------------------------------------------------------------
1278    //-----------------------------------------------------------------------
1279    //-----------------------------------------------------------------------
1280    private Expected createDate(Integer year, Integer month, Integer day) {
1281        Expected test = new Expected();
1282        if (year != null) {
1283            test.fieldValues.put(YEAR, (long) year);
1284        }
1285        if (month != null) {
1286            test.fieldValues.put(MONTH_OF_YEAR, (long) month);
1287        }
1288        if (day != null) {
1289            test.fieldValues.put(DAY_OF_MONTH, (long) day);
1290        }
1291        return test;
1292    }
1293
1294    private Expected createTime(Integer hour, Integer min, Integer sec, Integer nano) {
1295        Expected test = new Expected();
1296        if (hour != null) {
1297            test.fieldValues.put(HOUR_OF_DAY, (long) hour);
1298        }
1299        if (min != null) {
1300            test.fieldValues.put(MINUTE_OF_HOUR, (long) min);
1301        }
1302        if (sec != null) {
1303            test.fieldValues.put(SECOND_OF_MINUTE, (long) sec);
1304        }
1305        if (nano != null) {
1306            test.fieldValues.put(NANO_OF_SECOND, (long) nano);
1307        }
1308        return test;
1309    }
1310
1311    private Expected createDateTime(
1312            Integer year, Integer month, Integer day,
1313            Integer hour, Integer min, Integer sec, Integer nano) {
1314        Expected test = new Expected();
1315        if (year != null) {
1316            test.fieldValues.put(YEAR, (long) year);
1317        }
1318        if (month != null) {
1319            test.fieldValues.put(MONTH_OF_YEAR, (long) month);
1320        }
1321        if (day != null) {
1322            test.fieldValues.put(DAY_OF_MONTH, (long) day);
1323        }
1324        if (hour != null) {
1325            test.fieldValues.put(HOUR_OF_DAY, (long) hour);
1326        }
1327        if (min != null) {
1328            test.fieldValues.put(MINUTE_OF_HOUR, (long) min);
1329        }
1330        if (sec != null) {
1331            test.fieldValues.put(SECOND_OF_MINUTE, (long) sec);
1332        }
1333        if (nano != null) {
1334            test.fieldValues.put(NANO_OF_SECOND, (long) nano);
1335        }
1336        return test;
1337    }
1338
1339    private TemporalAccessor buildAccessor(
1340                    Integer year, Integer month, Integer day,
1341                    Integer hour, Integer min, Integer sec, Integer nano,
1342                    String offsetId, String zoneId) {
1343        MockAccessor mock = new MockAccessor();
1344        if (year != null) {
1345            mock.fields.put(YEAR, (long) year);
1346        }
1347        if (month != null) {
1348            mock.fields.put(MONTH_OF_YEAR, (long) month);
1349        }
1350        if (day != null) {
1351            mock.fields.put(DAY_OF_MONTH, (long) day);
1352        }
1353        if (hour != null) {
1354            mock.fields.put(HOUR_OF_DAY, (long) hour);
1355        }
1356        if (min != null) {
1357            mock.fields.put(MINUTE_OF_HOUR, (long) min);
1358        }
1359        if (sec != null) {
1360            mock.fields.put(SECOND_OF_MINUTE, (long) sec);
1361        }
1362        if (nano != null) {
1363            mock.fields.put(NANO_OF_SECOND, (long) nano);
1364        }
1365        mock.setOffset(offsetId);
1366        mock.setZone(zoneId);
1367        return mock;
1368    }
1369
1370    private TemporalAccessor buildAccessor(LocalDateTime base, String offsetId, String zoneId) {
1371        MockAccessor mock = new MockAccessor();
1372        mock.setFields(base);
1373        mock.setOffset(offsetId);
1374        mock.setZone(zoneId);
1375        return mock;
1376    }
1377
1378    private TemporalAccessor buildAccessor(LocalDate base, String offsetId, String zoneId) {
1379        MockAccessor mock = new MockAccessor();
1380        mock.setFields(base);
1381        mock.setOffset(offsetId);
1382        mock.setZone(zoneId);
1383        return mock;
1384    }
1385
1386    private TemporalAccessor buildAccessorInstant(long instantSecs, Integer nano) {
1387        MockAccessor mock = new MockAccessor();
1388        mock.fields.put(INSTANT_SECONDS, instantSecs);
1389        if (nano != null) {
1390            mock.fields.put(NANO_OF_SECOND, (long) nano);
1391        }
1392        return mock;
1393    }
1394
1395    private void buildCalendrical(Expected expected, String offsetId, String zoneId) {
1396        if (offsetId != null) {
1397            expected.add(ZoneOffset.of(offsetId));
1398        }
1399        if (zoneId != null) {
1400            expected.zone = ZoneId.of(zoneId);
1401        }
1402    }
1403
1404    private void assertParseMatch(TemporalAccessor parsed, Expected expected) {
1405        for (TemporalField field : expected.fieldValues.keySet()) {
1406            assertEquals(parsed.isSupported(field), true);
1407            parsed.getLong(field);
1408        }
1409        assertEquals(parsed.query(TemporalQueries.chronology()), expected.chrono);
1410        assertEquals(parsed.query(TemporalQueries.zoneId()), expected.zone);
1411    }
1412
1413    //-------------------------------------------------------------------------
1414    static class MockAccessor implements TemporalAccessor {
1415        Map<TemporalField, Long> fields = new HashMap<>();
1416        ZoneId zoneId;
1417
1418        void setFields(LocalDate dt) {
1419            if (dt != null) {
1420                fields.put(YEAR, (long) dt.getYear());
1421                fields.put(MONTH_OF_YEAR, (long) dt.getMonthValue());
1422                fields.put(DAY_OF_MONTH, (long) dt.getDayOfMonth());
1423                fields.put(DAY_OF_YEAR, (long) dt.getDayOfYear());
1424                fields.put(DAY_OF_WEEK, (long) dt.getDayOfWeek().getValue());
1425                fields.put(IsoFields.WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_BASED_YEAR));
1426                fields.put(IsoFields.WEEK_OF_WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
1427            }
1428        }
1429
1430        void setFields(LocalDateTime dt) {
1431            if (dt != null) {
1432                fields.put(YEAR, (long) dt.getYear());
1433                fields.put(MONTH_OF_YEAR, (long) dt.getMonthValue());
1434                fields.put(DAY_OF_MONTH, (long) dt.getDayOfMonth());
1435                fields.put(DAY_OF_YEAR, (long) dt.getDayOfYear());
1436                fields.put(DAY_OF_WEEK, (long) dt.getDayOfWeek().getValue());
1437                fields.put(IsoFields.WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_BASED_YEAR));
1438                fields.put(IsoFields.WEEK_OF_WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
1439                fields.put(HOUR_OF_DAY, (long) dt.getHour());
1440                fields.put(MINUTE_OF_HOUR, (long) dt.getMinute());
1441                fields.put(SECOND_OF_MINUTE, (long) dt.getSecond());
1442                fields.put(NANO_OF_SECOND, (long) dt.getNano());
1443            }
1444        }
1445
1446        void setOffset(String offsetId) {
1447            if (offsetId != null) {
1448                this.fields.put(OFFSET_SECONDS, (long) ZoneOffset.of(offsetId).getTotalSeconds());
1449            }
1450        }
1451
1452        void setZone(String zoneId) {
1453            if (zoneId != null) {
1454                this.zoneId = ZoneId.of(zoneId);
1455            }
1456        }
1457
1458        @Override
1459        public boolean isSupported(TemporalField field) {
1460            return fields.containsKey(field);
1461        }
1462
1463        @Override
1464        public long getLong(TemporalField field) {
1465            try {
1466                return fields.get(field);
1467            } catch (NullPointerException ex) {
1468                throw new DateTimeException("Field missing: " + field);
1469            }
1470        }
1471
1472        @SuppressWarnings("unchecked")
1473        @Override
1474        public <R> R query(TemporalQuery<R> query) {
1475            if (query == TemporalQueries.zoneId()) {
1476                return (R) zoneId;
1477            }
1478            return TemporalAccessor.super.query(query);
1479        }
1480
1481        @Override
1482        public String toString() {
1483            return fields + (zoneId != null ? " " + zoneId : "");
1484        }
1485    }
1486
1487    //-----------------------------------------------------------------------
1488    static class Expected {
1489        Map<TemporalField, Long> fieldValues = new HashMap<>();
1490        ZoneId zone;
1491        Chronology chrono;
1492
1493        Expected() {
1494        }
1495
1496        Expected(TemporalField field1, long value1, TemporalField field2, long value2) {
1497            fieldValues.put(field1, value1);
1498            fieldValues.put(field2, value2);
1499        }
1500
1501        void add(ZoneOffset offset) {
1502            fieldValues.put(OFFSET_SECONDS, (long) offset.getTotalSeconds());
1503        }
1504    }
1505}
1506