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  */
60 package tck.java.time.format;
61 
62 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
63 import static java.time.temporal.ChronoField.DAY_OF_WEEK;
64 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
65 import static java.time.temporal.ChronoField.HOUR_OF_DAY;
66 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
67 import static java.time.temporal.ChronoField.YEAR;
68 import static org.testng.Assert.assertEquals;
69 import static org.testng.Assert.assertNull;
70 import static org.testng.Assert.assertTrue;
71 import static org.testng.Assert.fail;
72 
73 import java.text.Format;
74 import java.text.ParseException;
75 import java.text.ParsePosition;
76 import java.time.DateTimeException;
77 import java.time.DayOfWeek;
78 import java.time.Instant;
79 import java.time.LocalDate;
80 import java.time.LocalDateTime;
81 import java.time.LocalTime;
82 import java.time.OffsetDateTime;
83 import java.time.OffsetTime;
84 import java.time.YearMonth;
85 import java.time.ZoneId;
86 import java.time.ZoneOffset;
87 import java.time.ZonedDateTime;
88 import java.time.chrono.ChronoZonedDateTime;
89 import java.time.chrono.Chronology;
90 import java.time.chrono.IsoChronology;
91 import java.time.chrono.ThaiBuddhistChronology;
92 import java.time.chrono.ThaiBuddhistDate;
93 import java.time.format.DecimalStyle;
94 import java.time.format.DateTimeFormatter;
95 import java.time.format.DateTimeFormatterBuilder;
96 import java.time.format.DateTimeParseException;
97 import java.time.format.SignStyle;
98 import java.time.temporal.IsoFields;
99 import java.time.temporal.TemporalAccessor;
100 import java.time.temporal.TemporalField;
101 import java.time.temporal.TemporalQuery;
102 import java.time.temporal.UnsupportedTemporalTypeException;
103 import java.util.Arrays;
104 import java.util.HashSet;
105 import java.util.Locale;
106 import java.util.Set;
107 
108 import org.testng.annotations.BeforeMethod;
109 import org.testng.annotations.DataProvider;
110 import org.testng.annotations.Test;
111 
112 /**
113  * Test DateTimeFormatter.
114  */
115 @Test
116 public class TCKDateTimeFormatter {
117 
118     private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
119     private static final ZoneOffset OFFSET_PTHREE = ZoneOffset.ofHours(3);
120     private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris");
121 
122     private static final DateTimeFormatter BASIC_FORMATTER = DateTimeFormatter.ofPattern("'ONE'd");
123     private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("'ONE'yyyy MM dd");
124 
125     private DateTimeFormatter fmt;
126 
127     @BeforeMethod
setUp()128     public void setUp() {
129         fmt = new DateTimeFormatterBuilder().appendLiteral("ONE")
130                                             .appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE)
131                                             .toFormatter();
132     }
133 
134     //-----------------------------------------------------------------------
135     @Test
test_withLocale()136     public void test_withLocale() {
137         DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
138         DateTimeFormatter test = base.withLocale(Locale.GERMAN);
139         assertEquals(test.getLocale(), Locale.GERMAN);
140     }
141 
142     @Test(expectedExceptions=NullPointerException.class)
test_withLocale_null()143     public void test_withLocale_null() {
144         DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
145         base.withLocale((Locale) null);
146     }
147 
148     //-----------------------------------------------------------------------
149     @Test
test_withChronology()150     public void test_withChronology() {
151         DateTimeFormatter test = fmt;
152         assertEquals(test.getChronology(), null);
153         test = test.withChronology(IsoChronology.INSTANCE);
154         assertEquals(test.getChronology(), IsoChronology.INSTANCE);
155         test = test.withChronology(null);
156         assertEquals(test.getChronology(), null);
157     }
158 
159     //-----------------------------------------------------------------------
160     @Test
test_withZone()161     public void test_withZone() {
162         DateTimeFormatter test = fmt;
163         assertEquals(test.getZone(), null);
164         test = test.withZone(ZoneId.of("Europe/Paris"));
165         assertEquals(test.getZone(), ZoneId.of("Europe/Paris"));
166         test = test.withZone(ZoneOffset.UTC);
167         assertEquals(test.getZone(), ZoneOffset.UTC);
168         test = test.withZone(null);
169         assertEquals(test.getZone(), null);
170     }
171 
172     //-----------------------------------------------------------------------
173     @Test
test_resolverFields_selectOneDateResolveYMD()174     public void test_resolverFields_selectOneDateResolveYMD() throws Exception {
175         DateTimeFormatter base = new DateTimeFormatterBuilder()
176                 .appendValue(YEAR).appendLiteral('-').appendValue(MONTH_OF_YEAR).appendLiteral('-')
177                 .appendValue(DAY_OF_MONTH).appendLiteral('-').appendValue(DAY_OF_YEAR).toFormatter();
178         DateTimeFormatter f = base.withResolverFields(YEAR, MONTH_OF_YEAR, DAY_OF_MONTH);
179         try {
180             base.parse("2012-6-30-321", LocalDate::from);  // wrong day-of-year
181             fail();
182         } catch (DateTimeException ex) {
183             // expected, fails as it produces two different dates
184         }
185         LocalDate parsed = f.parse("2012-6-30-321", LocalDate::from);  // ignored day-of-year
186         assertEquals(parsed, LocalDate.of(2012, 6, 30));
187     }
188 
189     @Test
test_resolverFields_selectOneDateResolveYD()190     public void test_resolverFields_selectOneDateResolveYD() throws Exception {
191         DateTimeFormatter base = new DateTimeFormatterBuilder()
192                 .appendValue(YEAR).appendLiteral('-').appendValue(MONTH_OF_YEAR).appendLiteral('-')
193                 .appendValue(DAY_OF_MONTH).appendLiteral('-').appendValue(DAY_OF_YEAR).toFormatter();
194         DateTimeFormatter f = base.withResolverFields(YEAR, DAY_OF_YEAR);
195         Set<TemporalField> expected = new HashSet<>(Arrays.asList(YEAR, DAY_OF_YEAR));
196         // Use set.equals();  testNG comparison of Collections is ordered
197         assertTrue(f.getResolverFields().equals(expected), "ResolveFields: " + f.getResolverFields());
198         try {
199             base.parse("2012-6-30-321", LocalDate::from);  // wrong month/day-of-month
200             fail();
201         } catch (DateTimeException ex) {
202             // expected, fails as it produces two different dates
203         }
204         LocalDate parsed = f.parse("2012-6-30-321", LocalDate::from);  // ignored month/day-of-month
205         assertEquals(parsed, LocalDate.of(2012, 11, 16));
206     }
207 
208     @Test
test_resolverFields_ignoreCrossCheck()209     public void test_resolverFields_ignoreCrossCheck() throws Exception {
210         DateTimeFormatter base = new DateTimeFormatterBuilder()
211                 .appendValue(YEAR).appendLiteral('-').appendValue(DAY_OF_YEAR).appendLiteral('-')
212                 .appendValue(DAY_OF_WEEK).toFormatter();
213         DateTimeFormatter f = base.withResolverFields(YEAR, DAY_OF_YEAR);
214         try {
215             base.parse("2012-321-1", LocalDate::from);  // wrong day-of-week
216             fail();
217         } catch (DateTimeException ex) {
218             // expected, should fail in cross-check of day-of-week
219         }
220         LocalDate parsed = f.parse("2012-321-1", LocalDate::from);  // ignored wrong day-of-week
221         assertEquals(parsed, LocalDate.of(2012, 11, 16));
222     }
223 
224     @Test
test_resolverFields_emptyList()225     public void test_resolverFields_emptyList() throws Exception {
226         DateTimeFormatter f = new DateTimeFormatterBuilder()
227                 .appendValue(YEAR).toFormatter().withResolverFields();
228         TemporalAccessor parsed = f.parse("2012");
229         assertEquals(parsed.isSupported(YEAR), false);  // not in the list of resolverFields
230     }
231 
232     @Test
test_resolverFields_listOfOneMatching()233     public void test_resolverFields_listOfOneMatching() throws Exception {
234         DateTimeFormatter f = new DateTimeFormatterBuilder()
235                 .appendValue(YEAR).toFormatter().withResolverFields(YEAR);
236         TemporalAccessor parsed = f.parse("2012");
237         assertEquals(parsed.isSupported(YEAR), true);
238     }
239 
240     @Test
test_resolverFields_listOfOneNotMatching()241     public void test_resolverFields_listOfOneNotMatching() throws Exception {
242         DateTimeFormatter f = new DateTimeFormatterBuilder()
243                 .appendValue(YEAR).toFormatter().withResolverFields(MONTH_OF_YEAR);
244         TemporalAccessor parsed = f.parse("2012");
245         assertEquals(parsed.isSupported(YEAR), false);  // not in the list of resolverFields
246         assertEquals(parsed.isSupported(MONTH_OF_YEAR), false);
247     }
248 
249     @Test
test_resolverFields_listOfOneNull()250     public void test_resolverFields_listOfOneNull() throws Exception {
251         DateTimeFormatter f = new DateTimeFormatterBuilder()
252                 .appendValue(YEAR).toFormatter().withResolverFields((TemporalField) null);
253         TemporalAccessor parsed = f.parse("2012");
254         assertEquals(parsed.isSupported(YEAR), false);  // not in the list of resolverFields
255     }
256 
257     @Test
test_resolverFields_Array_null()258     public void test_resolverFields_Array_null() throws Exception {
259         DateTimeFormatter f = DateTimeFormatter.ISO_DATE.withResolverFields(MONTH_OF_YEAR);
260         assertEquals(f.getResolverFields().size(), 1);
261         f = f.withResolverFields((TemporalField[]) null);
262         assertEquals(f.getResolverFields(), null);
263     }
264 
265     @Test
test_resolverFields_Set_null()266     public void test_resolverFields_Set_null() throws Exception {
267         DateTimeFormatter f = DateTimeFormatter.ISO_DATE.withResolverFields(MONTH_OF_YEAR);
268         assertEquals(f.getResolverFields().size(), 1);
269         f = f.withResolverFields((Set<TemporalField>) null);
270         assertEquals(f.getResolverFields(), null);
271     }
272 
273     //-----------------------------------------------------------------------
274     // format
275     //-----------------------------------------------------------------------
276     @DataProvider(name="formatWithZoneWithChronology")
data_format_withZone_withChronology()277     Object[][] data_format_withZone_withChronology() {
278         YearMonth ym = YearMonth.of(2008, 6);
279         LocalDate ld = LocalDate.of(2008, 6, 30);
280         LocalTime lt = LocalTime.of(11, 30);
281         LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 11, 30);
282         OffsetTime ot = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE);
283         OffsetDateTime odt = OffsetDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30), OFFSET_PONE);
284         ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30), ZONE_PARIS);
285         ChronoZonedDateTime<ThaiBuddhistDate> thaiZdt = ThaiBuddhistChronology.INSTANCE.zonedDateTime(zdt);
286         Instant instant = Instant.ofEpochSecond(3600);
287         return new Object[][] {
288                 {null, null, DayOfWeek.MONDAY, "::::"},
289                 {null, null, ym, "2008::::ISO"},
290                 {null, null, ld, "2008::::ISO"},
291                 {null, null, lt, ":11:::"},
292                 {null, null, ldt, "2008:11:::ISO"},
293                 {null, null, ot, ":11:+01:00::"},
294                 {null, null, odt, "2008:11:+01:00::ISO"},
295                 {null, null, zdt, "2008:11:+02:00:Europe/Paris:ISO"},
296                 {null, null, instant, "::::"},
297 
298                 {IsoChronology.INSTANCE, null, DayOfWeek.MONDAY, "::::ISO"},
299                 {IsoChronology.INSTANCE, null, ym, "2008::::ISO"},
300                 {IsoChronology.INSTANCE, null, ld, "2008::::ISO"},
301                 {IsoChronology.INSTANCE, null, lt, ":11:::ISO"},
302                 {IsoChronology.INSTANCE, null, ldt, "2008:11:::ISO"},
303                 {IsoChronology.INSTANCE, null, ot, ":11:+01:00::ISO"},
304                 {IsoChronology.INSTANCE, null, odt, "2008:11:+01:00::ISO"},
305                 {IsoChronology.INSTANCE, null, zdt, "2008:11:+02:00:Europe/Paris:ISO"},
306                 {IsoChronology.INSTANCE, null, instant, "::::ISO"},
307 
308                 {null, ZONE_PARIS, DayOfWeek.MONDAY, ":::Europe/Paris:"},
309                 {null, ZONE_PARIS, ym, "2008:::Europe/Paris:ISO"},
310                 {null, ZONE_PARIS, ld, "2008:::Europe/Paris:ISO"},
311                 {null, ZONE_PARIS, lt, ":11::Europe/Paris:"},
312                 {null, ZONE_PARIS, ldt, "2008:11::Europe/Paris:ISO"},
313                 {null, ZONE_PARIS, ot, ":11:+01:00:Europe/Paris:"},
314                 {null, ZONE_PARIS, odt, "2008:12:+02:00:Europe/Paris:ISO"},
315                 {null, ZONE_PARIS, zdt, "2008:11:+02:00:Europe/Paris:ISO"},
316                 {null, ZONE_PARIS, instant, "1970:02:+01:00:Europe/Paris:ISO"},
317 
318                 {null, OFFSET_PTHREE, DayOfWeek.MONDAY, ":::+03:00:"},
319                 {null, OFFSET_PTHREE, ym, "2008:::+03:00:ISO"},
320                 {null, OFFSET_PTHREE, ld, "2008:::+03:00:ISO"},
321                 {null, OFFSET_PTHREE, lt, ":11::+03:00:"},
322                 {null, OFFSET_PTHREE, ldt, "2008:11::+03:00:ISO"},
323                 {null, OFFSET_PTHREE, ot, null},  // offset and zone clash
324                 {null, OFFSET_PTHREE, odt, "2008:13:+03:00:+03:00:ISO"},
325                 {null, OFFSET_PTHREE, zdt, "2008:12:+03:00:+03:00:ISO"},
326                 {null, OFFSET_PTHREE, instant, "1970:04:+03:00:+03:00:ISO"},
327 
328                 {ThaiBuddhistChronology.INSTANCE, null, DayOfWeek.MONDAY, null},  // not a complete date
329                 {ThaiBuddhistChronology.INSTANCE, null, ym, null},  // not a complete date
330                 {ThaiBuddhistChronology.INSTANCE, null, ld, "2551::::ThaiBuddhist"},
331                 {ThaiBuddhistChronology.INSTANCE, null, lt, ":11:::ThaiBuddhist"},
332                 {ThaiBuddhistChronology.INSTANCE, null, ldt, "2551:11:::ThaiBuddhist"},
333                 {ThaiBuddhistChronology.INSTANCE, null, ot, ":11:+01:00::ThaiBuddhist"},
334                 {ThaiBuddhistChronology.INSTANCE, null, odt, "2551:11:+01:00::ThaiBuddhist"},
335                 {ThaiBuddhistChronology.INSTANCE, null, zdt, "2551:11:+02:00:Europe/Paris:ThaiBuddhist"},
336                 {ThaiBuddhistChronology.INSTANCE, null, instant, "::::ThaiBuddhist"},
337 
338                 {ThaiBuddhistChronology.INSTANCE, null, DayOfWeek.MONDAY, null},  // not a complete date
339                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, ym, null},  // not a complete date
340                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, ld, "2551:::Europe/Paris:ThaiBuddhist"},
341                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, lt, ":11::Europe/Paris:ThaiBuddhist"},
342                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, ldt, "2551:11::Europe/Paris:ThaiBuddhist"},
343                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, ot, ":11:+01:00:Europe/Paris:ThaiBuddhist"},
344                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, odt, "2551:12:+02:00:Europe/Paris:ThaiBuddhist"},
345                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, zdt, "2551:11:+02:00:Europe/Paris:ThaiBuddhist"},
346                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, instant, "2513:02:+01:00:Europe/Paris:ThaiBuddhist"},
347 
348                 {null, ZONE_PARIS, thaiZdt, "2551:11:+02:00:Europe/Paris:ThaiBuddhist"},
349                 {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, thaiZdt, "2551:11:+02:00:Europe/Paris:ThaiBuddhist"},
350                 {IsoChronology.INSTANCE, ZONE_PARIS, thaiZdt, "2008:11:+02:00:Europe/Paris:ISO"},
351         };
352     }
353 
354     @Test(dataProvider="formatWithZoneWithChronology")
test_format_withZone_withChronology(Chronology overrideChrono, ZoneId overrideZone, TemporalAccessor temporal, String expected)355     public void test_format_withZone_withChronology(Chronology overrideChrono, ZoneId overrideZone, TemporalAccessor temporal, String expected) {
356         DateTimeFormatter test = new DateTimeFormatterBuilder()
357                 .optionalStart().appendValue(YEAR, 4).optionalEnd()
358                 .appendLiteral(':').optionalStart().appendValue(HOUR_OF_DAY, 2).optionalEnd()
359                 .appendLiteral(':').optionalStart().appendOffsetId().optionalEnd()
360                 .appendLiteral(':').optionalStart().appendZoneId().optionalEnd()
361                 .appendLiteral(':').optionalStart().appendChronologyId().optionalEnd()
362                 .toFormatter(Locale.ENGLISH)
363                 .withChronology(overrideChrono).withZone(overrideZone);
364         if (expected != null) {
365             String result = test.format(temporal);
366             assertEquals(result, expected);
367         } else {
368             try {
369                 test.format(temporal);
370                 fail("Formatting should have failed");
371             } catch (DateTimeException ex) {
372                 // expected
373             }
374         }
375     }
376 
377     @Test
test_format_withChronology_nonChronoFieldMapLink()378     public void test_format_withChronology_nonChronoFieldMapLink() {
379         TemporalAccessor temporal = new TemporalAccessor() {
380             @Override
381             public boolean isSupported(TemporalField field) {
382                 return field == IsoFields.WEEK_BASED_YEAR;
383             }
384             @Override
385             public long getLong(TemporalField field) {
386                 if (field == IsoFields.WEEK_BASED_YEAR) {
387                     return 2345;
388                 }
389                 throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
390             }
391         };
392         DateTimeFormatter test = new DateTimeFormatterBuilder()
393                 .appendValue(IsoFields.WEEK_BASED_YEAR, 4)
394                 .toFormatter(Locale.ENGLISH)
395                 .withChronology(IsoChronology.INSTANCE);
396         String result = test.format(temporal);
397         assertEquals(result, "2345");
398     }
399 
400     //-----------------------------------------------------------------------
401     @Test
test_format_TemporalAccessor_simple()402     public void test_format_TemporalAccessor_simple() {
403         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
404         String result = test.format(LocalDate.of(2008, 6, 30));
405         assertEquals(result, "ONE30");
406     }
407 
408     @Test(expectedExceptions = DateTimeException.class)
test_format_TemporalAccessor_noSuchField()409     public void test_format_TemporalAccessor_noSuchField() {
410         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
411         test.format(LocalTime.of(11, 30));
412     }
413 
414     @Test(expectedExceptions = NullPointerException.class)
test_format_TemporalAccessor_null()415     public void test_format_TemporalAccessor_null() {
416         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
417         test.format((TemporalAccessor) null);
418     }
419 
420     //-----------------------------------------------------------------------
421     @Test
test_print_TemporalAppendable()422     public void test_print_TemporalAppendable() throws Exception {
423         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
424         StringBuilder buf = new StringBuilder();
425         test.formatTo(LocalDate.of(2008, 6, 30), buf);
426         assertEquals(buf.toString(), "ONE30");
427     }
428 
429     @Test(expectedExceptions=DateTimeException.class)
test_print_TemporalAppendable_noSuchField()430     public void test_print_TemporalAppendable_noSuchField() throws Exception {
431         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
432         StringBuilder buf = new StringBuilder();
433         test.formatTo(LocalTime.of(11, 30), buf);
434     }
435 
436     @Test(expectedExceptions=NullPointerException.class)
test_print_TemporalAppendable_nullTemporal()437     public void test_print_TemporalAppendable_nullTemporal() throws Exception {
438         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
439         StringBuilder buf = new StringBuilder();
440         test.formatTo((TemporalAccessor) null, buf);
441     }
442 
443     @Test(expectedExceptions=NullPointerException.class)
test_print_TemporalAppendable_nullAppendable()444     public void test_print_TemporalAppendable_nullAppendable() throws Exception {
445         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
446         test.formatTo(LocalDate.of(2008, 6, 30), (Appendable) null);
447     }
448 
449     //-----------------------------------------------------------------------
450     // parse(CharSequence)
451     //-----------------------------------------------------------------------
452     @Test
test_parse_CharSequence()453     public void test_parse_CharSequence() {
454         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
455         TemporalAccessor result = test.parse("ONE30");
456         assertEquals(result.isSupported(DAY_OF_MONTH), true);
457         assertEquals(result.getLong(DAY_OF_MONTH), 30L);
458         assertEquals(result.isSupported(HOUR_OF_DAY), false);
459     }
460 
461     @Test
test_parse_CharSequence_resolved()462     public void test_parse_CharSequence_resolved() {
463         DateTimeFormatter test = DateTimeFormatter.ISO_DATE;
464         TemporalAccessor result = test.parse("2012-06-30");
465         assertEquals(result.isSupported(YEAR), true);
466         assertEquals(result.isSupported(MONTH_OF_YEAR), true);
467         assertEquals(result.isSupported(DAY_OF_MONTH), true);
468         assertEquals(result.isSupported(HOUR_OF_DAY), false);
469         assertEquals(result.getLong(YEAR), 2012L);
470         assertEquals(result.getLong(MONTH_OF_YEAR), 6L);
471         assertEquals(result.getLong(DAY_OF_MONTH), 30L);
472         assertEquals(result.query(LocalDate::from), LocalDate.of(2012, 6, 30));
473     }
474 
475     @Test(expectedExceptions=NullPointerException.class)
test_parse_CharSequence_null()476     public void test_parse_CharSequence_null() {
477         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
478         test.parse((String) null);
479     }
480 
481     //-----------------------------------------------------------------------
482     // parse(CharSequence)
483     //-----------------------------------------------------------------------
484     @Test
test_parse_CharSequence_ParsePosition()485     public void test_parse_CharSequence_ParsePosition() {
486         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
487         ParsePosition pos = new ParsePosition(3);
488         TemporalAccessor result = test.parse("XXXONE30XXX", pos);
489         assertEquals(pos.getIndex(), 8);
490         assertEquals(pos.getErrorIndex(), -1);
491         assertEquals(result.isSupported(DAY_OF_MONTH), true);
492         assertEquals(result.getLong(DAY_OF_MONTH), 30L);
493         assertEquals(result.isSupported(HOUR_OF_DAY), false);
494     }
495 
496     @Test
test_parse_CharSequence_ParsePosition_resolved()497     public void test_parse_CharSequence_ParsePosition_resolved() {
498         DateTimeFormatter test = DateTimeFormatter.ISO_DATE;
499         ParsePosition pos = new ParsePosition(3);
500         TemporalAccessor result = test.parse("XXX2012-06-30XXX", pos);
501         assertEquals(pos.getIndex(), 13);
502         assertEquals(pos.getErrorIndex(), -1);
503         assertEquals(result.isSupported(YEAR), true);
504         assertEquals(result.isSupported(MONTH_OF_YEAR), true);
505         assertEquals(result.isSupported(DAY_OF_MONTH), true);
506         assertEquals(result.isSupported(HOUR_OF_DAY), false);
507         assertEquals(result.getLong(YEAR), 2012L);
508         assertEquals(result.getLong(MONTH_OF_YEAR), 6L);
509         assertEquals(result.getLong(DAY_OF_MONTH), 30L);
510         assertEquals(result.query(LocalDate::from), LocalDate.of(2012, 6, 30));
511     }
512 
513     @Test(expectedExceptions=DateTimeParseException.class)
test_parse_CharSequence_ParsePosition_parseError()514     public void test_parse_CharSequence_ParsePosition_parseError() {
515         DateTimeFormatter test = DateTimeFormatter.ISO_DATE;
516         ParsePosition pos = new ParsePosition(3);
517         try {
518             test.parse("XXX2012XXX", pos);
519             fail();
520         } catch (DateTimeParseException ex) {
521             assertEquals(ex.getErrorIndex(), 7);
522             throw ex;
523         }
524     }
525 
526     @Test(expectedExceptions=IndexOutOfBoundsException.class)
test_parse_CharSequence_ParsePosition_indexTooBig()527     public void test_parse_CharSequence_ParsePosition_indexTooBig() {
528         DateTimeFormatter test = DateTimeFormatter.ISO_DATE;
529         test.parse("Text", new ParsePosition(5));
530     }
531 
532     @Test(expectedExceptions=NullPointerException.class)
test_parse_CharSequence_ParsePosition_nullText()533     public void test_parse_CharSequence_ParsePosition_nullText() {
534         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
535         test.parse((CharSequence) null, new ParsePosition(0));
536     }
537 
538     @Test(expectedExceptions=NullPointerException.class)
test_parse_CharSequence_ParsePosition_nullParsePosition()539     public void test_parse_CharSequence_ParsePosition_nullParsePosition() {
540         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
541         test.parse("Text", (ParsePosition) null);
542     }
543 
544     //-----------------------------------------------------------------------
545     // parse(Query)
546     //-----------------------------------------------------------------------
547     @Test
test_parse_Query_String()548     public void test_parse_Query_String() throws Exception {
549         LocalDate result = DATE_FORMATTER.parse("ONE2012 07 27", LocalDate::from);
550         assertEquals(result, LocalDate.of(2012, 7, 27));
551     }
552 
553     @Test
test_parse_Query_CharSequence()554     public void test_parse_Query_CharSequence() throws Exception {
555         LocalDate result = DATE_FORMATTER.parse(new StringBuilder("ONE2012 07 27"), LocalDate::from);
556         assertEquals(result, LocalDate.of(2012, 7, 27));
557     }
558 
559     @Test(expectedExceptions=DateTimeParseException.class)
test_parse_Query_String_parseError()560     public void test_parse_Query_String_parseError() throws Exception {
561         try {
562             DATE_FORMATTER.parse("ONE2012 07 XX", LocalDate::from);
563         } catch (DateTimeParseException ex) {
564             assertEquals(ex.getMessage().contains("could not be parsed"), true);
565             assertEquals(ex.getMessage().contains("ONE2012 07 XX"), true);
566             assertEquals(ex.getParsedString(), "ONE2012 07 XX");
567             assertEquals(ex.getErrorIndex(), 11);
568             throw ex;
569         }
570     }
571 
572     @Test(expectedExceptions=DateTimeParseException.class)
test_parse_Query_String_parseErrorLongText()573     public void test_parse_Query_String_parseErrorLongText() throws Exception {
574         try {
575             DATE_FORMATTER.parse("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789", LocalDate::from);
576         } catch (DateTimeParseException ex) {
577             assertEquals(ex.getMessage().contains("could not be parsed"), true);
578             assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true);
579             assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
580             assertEquals(ex.getErrorIndex(), 3);
581             throw ex;
582         }
583     }
584 
585     @Test(expectedExceptions=DateTimeParseException.class)
test_parse_Query_String_parseIncomplete()586     public void test_parse_Query_String_parseIncomplete() throws Exception {
587         try {
588             DATE_FORMATTER.parse("ONE2012 07 27SomethingElse", LocalDate::from);
589         } catch (DateTimeParseException ex) {
590             assertEquals(ex.getMessage().contains("could not be parsed"), true);
591             assertEquals(ex.getMessage().contains("ONE2012 07 27SomethingElse"), true);
592             assertEquals(ex.getParsedString(), "ONE2012 07 27SomethingElse");
593             assertEquals(ex.getErrorIndex(), 13);
594             throw ex;
595         }
596     }
597 
598     @Test(expectedExceptions=NullPointerException.class)
test_parse_Query_String_nullText()599     public void test_parse_Query_String_nullText() throws Exception {
600         DATE_FORMATTER.parse((String) null, LocalDate::from);
601     }
602 
603     @Test(expectedExceptions=NullPointerException.class)
test_parse_Query_String_nullRule()604     public void test_parse_Query_String_nullRule() throws Exception {
605         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
606         test.parse("30", (TemporalQuery<?>) null);
607     }
608 
609     //-----------------------------------------------------------------------
610     @Test
test_parseBest_firstOption()611     public void test_parseBest_firstOption() throws Exception {
612         DateTimeFormatter test = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm[XXX]");
613         TemporalAccessor result = test.parseBest("2011-06-30 12:30+03:00", ZonedDateTime::from, LocalDateTime::from);
614         LocalDateTime ldt = LocalDateTime.of(2011, 6, 30, 12, 30);
615         assertEquals(result, ZonedDateTime.of(ldt, ZoneOffset.ofHours(3)));
616     }
617 
618     @Test
test_parseBest_secondOption()619     public void test_parseBest_secondOption() throws Exception {
620         DateTimeFormatter test = DateTimeFormatter.ofPattern("yyyy-MM-dd[ HH:mm[XXX]]");
621         TemporalAccessor result = test.parseBest("2011-06-30", ZonedDateTime::from, LocalDate::from);
622         assertEquals(result, LocalDate.of(2011, 6, 30));
623     }
624 
625     @Test(expectedExceptions=DateTimeParseException.class)
test_parseBest_String_parseError()626     public void test_parseBest_String_parseError() throws Exception {
627         DateTimeFormatter test = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm[XXX]");
628         try {
629             test.parseBest("2011-06-XX", ZonedDateTime::from, LocalDateTime::from);
630         } catch (DateTimeParseException ex) {
631             assertEquals(ex.getMessage().contains("could not be parsed"), true);
632             assertEquals(ex.getMessage().contains("XX"), true);
633             assertEquals(ex.getParsedString(), "2011-06-XX");
634             assertEquals(ex.getErrorIndex(), 8);
635             throw ex;
636         }
637     }
638 
639     @Test(expectedExceptions=DateTimeParseException.class)
test_parseBest_String_parseErrorLongText()640     public void test_parseBest_String_parseErrorLongText() throws Exception {
641         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
642         try {
643             test.parseBest("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789", ZonedDateTime::from, LocalDate::from);
644         } catch (DateTimeParseException ex) {
645             assertEquals(ex.getMessage().contains("could not be parsed"), true);
646             assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true);
647             assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
648             assertEquals(ex.getErrorIndex(), 3);
649             throw ex;
650         }
651     }
652 
653     @Test(expectedExceptions=DateTimeParseException.class)
test_parseBest_String_parseIncomplete()654     public void test_parseBest_String_parseIncomplete() throws Exception {
655         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
656         try {
657             test.parseBest("ONE30SomethingElse", ZonedDateTime::from, LocalDate::from);
658         } catch (DateTimeParseException ex) {
659             assertEquals(ex.getMessage().contains("could not be parsed"), true);
660             assertEquals(ex.getMessage().contains("ONE30SomethingElse"), true);
661             assertEquals(ex.getParsedString(), "ONE30SomethingElse");
662             assertEquals(ex.getErrorIndex(), 5);
663             throw ex;
664         }
665     }
666 
667     @Test(expectedExceptions=NullPointerException.class)
test_parseBest_String_nullText()668     public void test_parseBest_String_nullText() throws Exception {
669         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
670         test.parseBest((String) null, ZonedDateTime::from, LocalDate::from);
671     }
672 
673     @Test(expectedExceptions=NullPointerException.class)
test_parseBest_String_nullRules()674     public void test_parseBest_String_nullRules() throws Exception {
675         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
676         test.parseBest("30", (TemporalQuery<?>[]) null);
677     }
678 
679     @Test(expectedExceptions=IllegalArgumentException.class)
test_parseBest_String_zeroRules()680     public void test_parseBest_String_zeroRules() throws Exception {
681         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
682         test.parseBest("30", new TemporalQuery<?>[0]);
683     }
684 
685     @Test(expectedExceptions=IllegalArgumentException.class)
test_parseBest_String_oneRule()686     public void test_parseBest_String_oneRule() throws Exception {
687         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
688         test.parseBest("30", LocalDate::from);
689     }
690 
691     //-----------------------------------------------------------------------
692     @Test
test_parseUnresolved_StringParsePosition()693     public void test_parseUnresolved_StringParsePosition() {
694         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
695         ParsePosition pos = new ParsePosition(0);
696         TemporalAccessor result = test.parseUnresolved("ONE30XXX", pos);
697         assertEquals(pos.getIndex(), 5);
698         assertEquals(pos.getErrorIndex(), -1);
699         assertEquals(result.getLong(DAY_OF_MONTH), 30L);
700     }
701 
702     @Test
test_parseUnresolved_StringParsePosition_parseError()703     public void test_parseUnresolved_StringParsePosition_parseError() {
704         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
705         ParsePosition pos = new ParsePosition(0);
706         TemporalAccessor result = test.parseUnresolved("ONEXXX", pos);
707         assertEquals(pos.getIndex(), 0);
708         assertEquals(pos.getErrorIndex(), 3);
709         assertEquals(result, null);
710     }
711 
712     @Test
test_parseUnresolved_StringParsePosition_duplicateFieldSameValue()713     public void test_parseUnresolved_StringParsePosition_duplicateFieldSameValue() {
714         DateTimeFormatter test = new DateTimeFormatterBuilder()
715                 .appendValue(MONTH_OF_YEAR).appendLiteral('-').appendValue(MONTH_OF_YEAR).toFormatter();
716         ParsePosition pos = new ParsePosition(3);
717         TemporalAccessor result = test.parseUnresolved("XXX6-6", pos);
718         assertEquals(pos.getIndex(), 6);
719         assertEquals(pos.getErrorIndex(), -1);
720         assertEquals(result.getLong(MONTH_OF_YEAR), 6);
721     }
722 
723     @Test
test_parseUnresolved_StringParsePosition_duplicateFieldDifferentValue()724     public void test_parseUnresolved_StringParsePosition_duplicateFieldDifferentValue() {
725         DateTimeFormatter test = new DateTimeFormatterBuilder()
726                 .appendValue(MONTH_OF_YEAR).appendLiteral('-').appendValue(MONTH_OF_YEAR).toFormatter();
727         ParsePosition pos = new ParsePosition(3);
728         TemporalAccessor result = test.parseUnresolved("XXX6-7", pos);
729         assertEquals(pos.getIndex(), 3);
730         assertEquals(pos.getErrorIndex(), 5);
731         assertEquals(result, null);
732     }
733 
734     @Test(expectedExceptions=NullPointerException.class)
test_parseUnresolved_StringParsePosition_nullString()735     public void test_parseUnresolved_StringParsePosition_nullString() {
736         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
737         ParsePosition pos = new ParsePosition(0);
738         test.parseUnresolved((String) null, pos);
739     }
740 
741     @Test(expectedExceptions=NullPointerException.class)
test_parseUnresolved_StringParsePosition_nullParsePosition()742     public void test_parseUnresolved_StringParsePosition_nullParsePosition() {
743         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
744         test.parseUnresolved("ONE30", (ParsePosition) null);
745     }
746 
747     @Test(expectedExceptions=IndexOutOfBoundsException.class)
test_parseUnresolved_StringParsePosition_invalidPosition()748     public void test_parseUnresolved_StringParsePosition_invalidPosition() {
749         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
750         ParsePosition pos = new ParsePosition(6);
751         test.parseUnresolved("ONE30", pos);
752     }
753 
754     //-----------------------------------------------------------------------
755     //-----------------------------------------------------------------------
756     @Test
test_toFormat_format()757     public void test_toFormat_format() throws Exception {
758         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
759         Format format = test.toFormat();
760         String result = format.format(LocalDate.of(2008, 6, 30));
761         assertEquals(result, "ONE30");
762     }
763 
764     @Test(expectedExceptions=NullPointerException.class)
test_toFormat_format_null()765     public void test_toFormat_format_null() throws Exception {
766         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
767         Format format = test.toFormat();
768         format.format(null);
769     }
770 
771     @Test(expectedExceptions=IllegalArgumentException.class)
test_toFormat_format_notTemporal()772     public void test_toFormat_format_notTemporal() throws Exception {
773         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
774         Format format = test.toFormat();
775         format.format("Not a Temporal");
776     }
777 
778     //-----------------------------------------------------------------------
779     @Test
test_toFormat_parseObject_String()780     public void test_toFormat_parseObject_String() throws Exception {
781         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
782         Format format = test.toFormat();
783         TemporalAccessor result = (TemporalAccessor) format.parseObject("ONE30");
784         assertEquals(result.isSupported(DAY_OF_MONTH), true);
785         assertEquals(result.getLong(DAY_OF_MONTH), 30L);
786     }
787 
788     @Test(expectedExceptions=ParseException.class)
test_toFormat_parseObject_String_parseError()789     public void test_toFormat_parseObject_String_parseError() throws Exception {
790         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
791         Format format = test.toFormat();
792         try {
793             format.parseObject("ONEXXX");
794         } catch (ParseException ex) {
795             assertEquals(ex.getMessage().contains("ONEXXX"), true);
796             assertEquals(ex.getErrorOffset(), 3);
797             throw ex;
798         }
799     }
800 
801     @Test(expectedExceptions=ParseException.class)
test_toFormat_parseObject_String_parseErrorLongText()802     public void test_toFormat_parseObject_String_parseErrorLongText() throws Exception {
803         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
804         Format format = test.toFormat();
805         try {
806             format.parseObject("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
807         } catch (DateTimeParseException ex) {
808             assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true);
809             assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
810             assertEquals(ex.getErrorIndex(), 3);
811             throw ex;
812         }
813     }
814 
815     @Test(expectedExceptions=NullPointerException.class)
test_toFormat_parseObject_String_null()816     public void test_toFormat_parseObject_String_null() throws Exception {
817         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
818         Format format = test.toFormat();
819         format.parseObject((String) null);
820     }
821 
822     //-----------------------------------------------------------------------
823     @Test
test_toFormat_parseObject_StringParsePosition()824     public void test_toFormat_parseObject_StringParsePosition() throws Exception {
825         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
826         Format format = test.toFormat();
827         ParsePosition pos = new ParsePosition(0);
828         TemporalAccessor result = (TemporalAccessor) format.parseObject("ONE30XXX", pos);
829         assertEquals(pos.getIndex(), 5);
830         assertEquals(pos.getErrorIndex(), -1);
831         assertEquals(result.isSupported(DAY_OF_MONTH), true);
832         assertEquals(result.getLong(DAY_OF_MONTH), 30L);
833     }
834 
835     @Test
test_toFormat_parseObject_StringParsePosition_parseError()836     public void test_toFormat_parseObject_StringParsePosition_parseError() throws Exception {
837         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
838         Format format = test.toFormat();
839         ParsePosition pos = new ParsePosition(0);
840         TemporalAccessor result = (TemporalAccessor) format.parseObject("ONEXXX", pos);
841         assertEquals(pos.getIndex(), 0);  // TODO: is this right?
842         assertEquals(pos.getErrorIndex(), 3);
843         assertEquals(result, null);
844     }
845 
846     @Test(expectedExceptions=NullPointerException.class)
test_toFormat_parseObject_StringParsePosition_nullString()847     public void test_toFormat_parseObject_StringParsePosition_nullString() throws Exception {
848         // SimpleDateFormat has this behavior
849         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
850         Format format = test.toFormat();
851         ParsePosition pos = new ParsePosition(0);
852         format.parseObject((String) null, pos);
853     }
854 
855     @Test(expectedExceptions=NullPointerException.class)
test_toFormat_parseObject_StringParsePosition_nullParsePosition()856     public void test_toFormat_parseObject_StringParsePosition_nullParsePosition() throws Exception {
857         // SimpleDateFormat has this behavior
858         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
859         Format format = test.toFormat();
860         format.parseObject("ONE30", (ParsePosition) null);
861     }
862 
863     @Test
test_toFormat_parseObject_StringParsePosition_invalidPosition_tooBig()864     public void test_toFormat_parseObject_StringParsePosition_invalidPosition_tooBig() throws Exception {
865         // SimpleDateFormat has this behavior
866         DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
867         ParsePosition pos = new ParsePosition(6);
868         Format test = dtf.toFormat();
869         assertNull(test.parseObject("ONE30", pos));
870         assertTrue(pos.getErrorIndex() >= 0);
871     }
872 
873     @Test
test_toFormat_parseObject_StringParsePosition_invalidPosition_tooSmall()874     public void test_toFormat_parseObject_StringParsePosition_invalidPosition_tooSmall() throws Exception {
875         // SimpleDateFormat throws StringIndexOutOfBoundException
876         DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withDecimalStyle(DecimalStyle.STANDARD);
877         ParsePosition pos = new ParsePosition(-1);
878         Format test = dtf.toFormat();
879         assertNull(test.parseObject("ONE30", pos));
880         assertTrue(pos.getErrorIndex() >= 0);
881     }
882 
883     //-----------------------------------------------------------------------
884     @Test
test_toFormat_Query_format()885     public void test_toFormat_Query_format() throws Exception {
886         Format format = BASIC_FORMATTER.toFormat();
887         String result = format.format(LocalDate.of(2008, 6, 30));
888         assertEquals(result, "ONE30");
889     }
890 
891     @Test
test_toFormat_Query_parseObject_String()892     public void test_toFormat_Query_parseObject_String() throws Exception {
893         Format format = DATE_FORMATTER.toFormat(LocalDate::from);
894         LocalDate result = (LocalDate) format.parseObject("ONE2012 07 27");
895         assertEquals(result, LocalDate.of(2012, 7, 27));
896     }
897 
898     @Test(expectedExceptions=ParseException.class)
test_toFormat_parseObject_StringParsePosition_dateTimeError()899     public void test_toFormat_parseObject_StringParsePosition_dateTimeError() throws Exception {
900         Format format = DATE_FORMATTER.toFormat(LocalDate::from);
901         format.parseObject("ONE2012 07 32");
902     }
903 
904     @Test(expectedExceptions=NullPointerException.class)
test_toFormat_Query()905     public void test_toFormat_Query() throws Exception {
906         BASIC_FORMATTER.toFormat(null);
907     }
908 
909 }
910