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.HOUR_OF_DAY;
  64 import static java.time.temporal.ChronoField.YEAR;
  65 import static org.testng.Assert.assertEquals;
  66 import static org.testng.Assert.assertNull;
  67 import static org.testng.Assert.assertTrue;
  68 
  69 import java.io.IOException;
  70 import java.text.Format;
  71 import java.text.ParseException;
  72 import java.text.ParsePosition;
  73 import java.util.Locale;
  74 
  75 import java.time.DateTimeException;
  76 import java.time.Instant;
  77 import java.time.LocalDate;
  78 import java.time.LocalDateTime;
  79 import java.time.LocalTime;
  80 import java.time.ZoneId;
  81 import java.time.ZoneOffset;
  82 import java.time.ZonedDateTime;
  83 import java.time.calendar.ThaiBuddhistChrono;
  84 import java.time.format.DateTimeFormatSymbols;
  85 import java.time.format.DateTimeFormatter;
  86 import java.time.format.DateTimeFormatterBuilder;
  87 import java.time.format.DateTimeFormatters;
  88 import java.time.format.DateTimeParseException;
  89 import java.time.format.DateTimePrintException;
  90 import java.time.format.SignStyle;
  91 import java.time.format.DateTimeBuilder;
  92 import java.time.temporal.Chrono;
  93 import java.time.temporal.ISOChrono;
  94 import java.time.temporal.OffsetDate;
  95 import java.time.temporal.OffsetDateTime;
  96 import java.time.temporal.OffsetTime;
  97 import java.time.temporal.Temporal;
  98 import java.time.temporal.TemporalAccessor;
  99 import java.time.temporal.TemporalQuery;
 100 
 101 import org.testng.annotations.BeforeMethod;
 102 import org.testng.annotations.DataProvider;
 103 import org.testng.annotations.Test;
 104 import test.java.time.format.MockIOExceptionAppendable;
 105 
 106 /**
 107  * Test DateTimeFormatter.
 108  */
 109 @Test(groups={"tck"})
 110 public class TCKDateTimeFormatter {
 111 
 112     private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
 113     private static final ZoneOffset OFFSET_PTHREE = ZoneOffset.ofHours(3);
 114     private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris");
 115 
 116     private static final DateTimeFormatter BASIC_FORMATTER = DateTimeFormatters.pattern("'ONE'd");
 117     private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatters.pattern("'ONE'yyyy MM dd");
 118 
 119     private DateTimeFormatter fmt;
 120 
 121     @BeforeMethod
 122     public void setUp() {
 123         fmt = new DateTimeFormatterBuilder().appendLiteral("ONE")
 124                                             .appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE)
 125                                             .toFormatter();
 126     }
 127 
 128     //-----------------------------------------------------------------------
 129     @Test
 130     public void test_withLocale() {
 131         DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 132         DateTimeFormatter test = base.withLocale(Locale.GERMAN);
 133         assertEquals(test.getLocale(), Locale.GERMAN);
 134     }
 135 
 136     @Test(expectedExceptions=NullPointerException.class)
 137     public void test_withLocale_null() {
 138         DateTimeFormatter base = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 139         base.withLocale((Locale) null);
 140     }
 141 
 142     //-----------------------------------------------------------------------
 143     @Test
 144     public void test_withChrono() {
 145         DateTimeFormatter test = fmt;
 146         assertEquals(test.getChrono(), null);
 147         test = test.withChrono(ISOChrono.INSTANCE);
 148         assertEquals(test.getChrono(), ISOChrono.INSTANCE);
 149         test = test.withChrono(null);
 150         assertEquals(test.getChrono(), null);
 151     }
 152 
 153     //-----------------------------------------------------------------------
 154     @Test
 155     public void test_withZone() {
 156         DateTimeFormatter test = fmt;
 157         assertEquals(test.getZone(), null);
 158         test = test.withZone(ZoneId.of("Europe/Paris"));
 159         assertEquals(test.getZone(), ZoneId.of("Europe/Paris"));
 160         test = test.withZone(ZoneOffset.UTC);
 161         assertEquals(test.getZone(), ZoneOffset.UTC);
 162         test = test.withZone(null);
 163         assertEquals(test.getZone(), null);
 164     }
 165 
 166     //-----------------------------------------------------------------------
 167     // print
 168     //-----------------------------------------------------------------------
 169     @DataProvider(name="print")
 170     Object[][] data_print() {
 171         LocalDate ld = LocalDate.of(2008, 6, 30);
 172         LocalTime lt = LocalTime.of(11, 30);
 173         LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 11, 30);
 174         OffsetDate od = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE);
 175         OffsetTime ot = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE);
 176         OffsetDateTime odt = OffsetDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30), OFFSET_PONE);
 177         ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30), ZONE_PARIS);
 178         Instant instant = Instant.ofEpochSecond(3600);
 179         return new Object[][] {
 180                 {null, null, ld, "2008::"},
 181                 {null, null, lt, ":11:"},
 182                 {null, null, ldt, "2008:11:"},
 183                 {null, null, od, "2008::+01:00"},
 184                 {null, null, ot, ":11:+01:00"},
 185                 {null, null, odt, "2008:11:+01:00"},
 186                 {null, null, zdt, "2008:11:+02:00Europe/Paris"},
 187                 {null, null, instant, "::"},
 188 
 189                 {null, ZONE_PARIS, ld, "2008::"},
 190                 {null, ZONE_PARIS, lt, ":11:"},
 191                 {null, ZONE_PARIS, ldt, "2008:11:"},
 192                 {null, ZONE_PARIS, od, "2008::+01:00"},
 193                 {null, ZONE_PARIS, ot, ":11:+01:00"},
 194                 {null, ZONE_PARIS, odt, "2008:12:+02:00Europe/Paris"},
 195                 {null, ZONE_PARIS, zdt, "2008:11:+02:00Europe/Paris"},
 196                 {null, ZONE_PARIS, instant, "1970:02:+01:00Europe/Paris"},
 197 
 198                 {null, OFFSET_PTHREE, ld, "2008::"},
 199                 {null, OFFSET_PTHREE, lt, ":11:"},
 200                 {null, OFFSET_PTHREE, ldt, "2008:11:"},
 201                 {null, OFFSET_PTHREE, od, "2008::+01:00"},
 202                 {null, OFFSET_PTHREE, ot, ":11:+01:00"},
 203                 {null, OFFSET_PTHREE, odt, "2008:13:+03:00"},
 204                 {null, OFFSET_PTHREE, zdt, "2008:12:+03:00"},
 205                 {null, OFFSET_PTHREE, instant, "1970:04:+03:00"},
 206 
 207                 {ThaiBuddhistChrono.INSTANCE, null, ld, "2551::"},
 208                 {ThaiBuddhistChrono.INSTANCE, null, lt, ":11:"},
 209                 {ThaiBuddhistChrono.INSTANCE, null, ldt, "2551:11:"},
 210                 {ThaiBuddhistChrono.INSTANCE, null, od, "2551::+01:00"},
 211                 {ThaiBuddhistChrono.INSTANCE, null, ot, ":11:+01:00"},
 212                 {ThaiBuddhistChrono.INSTANCE, null, odt, "2551:11:+01:00"},
 213                 {ThaiBuddhistChrono.INSTANCE, null, zdt, "2551:11:+02:00Europe/Paris"},
 214                 {ThaiBuddhistChrono.INSTANCE, null, instant, "::"},
 215 
 216                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, ld, "2551::"},
 217                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, lt, ":11:"},
 218                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, ldt, "2551:11:"},
 219                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, od, "2551::+01:00"},
 220                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, ot, ":11:+01:00"},
 221                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, odt, "2551:12:+02:00Europe/Paris"},
 222                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, zdt, "2551:11:+02:00Europe/Paris"},
 223                 {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, instant, "1970:02:+01:00Europe/Paris"},
 224         };
 225     }
 226 
 227     @Test(dataProvider="print")
 228     public void test_print_Temporal(Chrono<?> overrideChrono, ZoneId overrideZone, Temporal temporal, String expected) {
 229         DateTimeFormatter test = new DateTimeFormatterBuilder()
 230                 .optionalStart().appendValue(YEAR, 4).optionalEnd()
 231                 .appendLiteral(':').optionalStart().appendValue(HOUR_OF_DAY, 2).optionalEnd()
 232                 .appendLiteral(':').optionalStart().appendOffsetId().optionalStart().appendZoneRegionId().optionalEnd().optionalEnd()
 233                 .toFormatter(Locale.ENGLISH)
 234                 .withChrono(overrideChrono).withZone(overrideZone);
 235         String result = test.print(temporal);
 236         assertEquals(result, expected);
 237     }
 238 
 239     @Test
 240     public void test_print_Temporal_simple() throws Exception {
 241         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 242         String result = test.print(LocalDate.of(2008, 6, 30));
 243         assertEquals(result, "ONE30");
 244     }
 245 
 246     @Test(expectedExceptions=DateTimeException.class)
 247     public void test_print_Temporal_noSuchField() throws Exception {
 248         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 249         test.print(LocalTime.of(11, 30));
 250     }
 251 
 252     @Test(expectedExceptions=NullPointerException.class)
 253     public void test_print_Temporal_null() throws Exception {
 254         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 255         test.print((TemporalAccessor) null);
 256     }
 257 
 258     //-----------------------------------------------------------------------
 259     @Test
 260     public void test_print_TemporalAppendable() throws Exception {
 261         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 262         StringBuilder buf = new StringBuilder();
 263         test.printTo(LocalDate.of(2008, 6, 30), buf);
 264         assertEquals(buf.toString(), "ONE30");
 265     }
 266 
 267     @Test(expectedExceptions=DateTimeException.class)
 268     public void test_print_TemporalAppendable_noSuchField() throws Exception {
 269         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 270         StringBuilder buf = new StringBuilder();
 271         test.printTo(LocalTime.of(11, 30), buf);
 272     }
 273 
 274     @Test(expectedExceptions=NullPointerException.class)
 275     public void test_print_TemporalAppendable_nullTemporal() throws Exception {
 276         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 277         StringBuilder buf = new StringBuilder();
 278         test.printTo((TemporalAccessor) null, buf);
 279     }
 280 
 281     @Test(expectedExceptions=NullPointerException.class)
 282     public void test_print_TemporalAppendable_nullAppendable() throws Exception {
 283         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 284         test.printTo(LocalDate.of(2008, 6, 30), (Appendable) null);
 285     }
 286 
 287     @Test(expectedExceptions=IOException.class)  // IOException
 288     public void test_print_TemporalAppendable_ioError() throws Exception {
 289         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 290         try {
 291             test.printTo(LocalDate.of(2008, 6, 30), new MockIOExceptionAppendable());
 292         } catch (DateTimePrintException ex) {
 293             assertEquals(ex.getCause() instanceof IOException, true);
 294             ex.rethrowIOException();
 295         }
 296     }
 297 
 298     //-----------------------------------------------------------------------
 299     // parse(Query)
 300     //-----------------------------------------------------------------------
 301     @Test
 302     public void test_parse_Query_String() throws Exception {
 303         LocalDate result = DATE_FORMATTER.parse("ONE2012 07 27", LocalDate::from);
 304         assertEquals(result, LocalDate.of(2012, 7, 27));
 305     }
 306 
 307     @Test
 308     public void test_parse_Query_CharSequence() throws Exception {
 309         LocalDate result = DATE_FORMATTER.parse(new StringBuilder("ONE2012 07 27"), LocalDate::from);
 310         assertEquals(result, LocalDate.of(2012, 7, 27));
 311     }
 312 
 313     @Test(expectedExceptions=DateTimeParseException.class)
 314     public void test_parse_Query_String_parseError() throws Exception {
 315         try {
 316             DATE_FORMATTER.parse("ONE2012 07 XX", LocalDate::from);
 317         } catch (DateTimeParseException ex) {
 318             assertEquals(ex.getMessage().contains("could not be parsed"), true);
 319             assertEquals(ex.getMessage().contains("ONE2012 07 XX"), true);
 320             assertEquals(ex.getParsedString(), "ONE2012 07 XX");
 321             assertEquals(ex.getErrorIndex(), 11);
 322             throw ex;
 323         }
 324     }
 325 
 326     @Test(expectedExceptions=DateTimeParseException.class)
 327     public void test_parse_Query_String_parseErrorLongText() throws Exception {
 328         try {
 329             DATE_FORMATTER.parse("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789", LocalDate::from);
 330         } catch (DateTimeParseException ex) {
 331             assertEquals(ex.getMessage().contains("could not be parsed"), true);
 332             assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true);
 333             assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
 334             assertEquals(ex.getErrorIndex(), 3);
 335             throw ex;
 336         }
 337     }
 338 
 339     @Test(expectedExceptions=DateTimeParseException.class)
 340     public void test_parse_Query_String_parseIncomplete() throws Exception {
 341         try {
 342             DATE_FORMATTER.parse("ONE2012 07 27SomethingElse", LocalDate::from);
 343         } catch (DateTimeParseException ex) {
 344             assertEquals(ex.getMessage().contains("could not be parsed"), true);
 345             assertEquals(ex.getMessage().contains("ONE2012 07 27SomethingElse"), true);
 346             assertEquals(ex.getParsedString(), "ONE2012 07 27SomethingElse");
 347             assertEquals(ex.getErrorIndex(), 13);
 348             throw ex;
 349         }
 350     }
 351 
 352     @Test(expectedExceptions=NullPointerException.class)
 353     public void test_parse_Query_String_nullText() throws Exception {
 354         DATE_FORMATTER.parse((String) null, LocalDate::from);
 355     }
 356 
 357     @Test(expectedExceptions=NullPointerException.class)
 358     public void test_parse_Query_String_nullRule() throws Exception {
 359         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 360         test.parse("30", (TemporalQuery<?>) null);
 361     }
 362 
 363     //-----------------------------------------------------------------------
 364     @Test
 365     public void test_parseBest_firstOption() throws Exception {
 366         DateTimeFormatter test = DateTimeFormatters.pattern("yyyy-MM-dd[ZZZ]");
 367         TemporalAccessor result = test.parseBest("2011-06-30+03:00", OffsetDate::from, LocalDate::from);
 368         assertEquals(result, OffsetDate.of(LocalDate.of(2011, 6, 30), ZoneOffset.ofHours(3)));
 369     }
 370 
 371     @Test
 372     public void test_parseBest_secondOption() throws Exception {
 373         DateTimeFormatter test = DateTimeFormatters.pattern("yyyy-MM-dd[ZZZ]");
 374         TemporalAccessor result = test.parseBest("2011-06-30", OffsetDate::from, LocalDate::from);
 375         assertEquals(result, LocalDate.of(2011, 6, 30));
 376     }
 377 
 378     @Test(expectedExceptions=DateTimeParseException.class)
 379     public void test_parseBest_String_parseError() throws Exception {
 380         DateTimeFormatter test = DateTimeFormatters.pattern("yyyy-MM-dd[ZZZ]");
 381         try {
 382             test.parseBest("2011-06-XX", OffsetDate::from, LocalDate::from);
 383         } catch (DateTimeParseException ex) {
 384             assertEquals(ex.getMessage().contains("could not be parsed"), true);
 385             assertEquals(ex.getMessage().contains("XX"), true);
 386             assertEquals(ex.getParsedString(), "2011-06-XX");
 387             assertEquals(ex.getErrorIndex(), 8);
 388             throw ex;
 389         }
 390     }
 391 
 392     @Test(expectedExceptions=DateTimeParseException.class)
 393     public void test_parseBest_String_parseErrorLongText() throws Exception {
 394         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 395         try {
 396             test.parseBest("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789", LocalDate::from, OffsetDate::from);
 397         } catch (DateTimeParseException ex) {
 398             assertEquals(ex.getMessage().contains("could not be parsed"), true);
 399             assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true);
 400             assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
 401             assertEquals(ex.getErrorIndex(), 3);
 402             throw ex;
 403         }
 404     }
 405 
 406     @Test(expectedExceptions=DateTimeParseException.class)
 407     public void test_parseBest_String_parseIncomplete() throws Exception {
 408         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 409         try {
 410             test.parseBest("ONE30SomethingElse", LocalDate::from, OffsetDate::from);
 411         } catch (DateTimeParseException ex) {
 412             assertEquals(ex.getMessage().contains("could not be parsed"), true);
 413             assertEquals(ex.getMessage().contains("ONE30SomethingElse"), true);
 414             assertEquals(ex.getParsedString(), "ONE30SomethingElse");
 415             assertEquals(ex.getErrorIndex(), 5);
 416             throw ex;
 417         }
 418     }
 419 
 420     @Test(expectedExceptions=NullPointerException.class)
 421     public void test_parseBest_String_nullText() throws Exception {
 422         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 423         test.parseBest((String) null, LocalDate::from, OffsetDate::from);
 424     }
 425 
 426     @Test(expectedExceptions=NullPointerException.class)
 427     public void test_parseBest_String_nullRules() throws Exception {
 428         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 429         test.parseBest("30", (TemporalQuery<?>[]) null);
 430     }
 431 
 432     @Test(expectedExceptions=IllegalArgumentException.class)
 433     public void test_parseBest_String_zeroRules() throws Exception {
 434         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 435         test.parseBest("30", new TemporalQuery<?>[0]);
 436     }
 437 
 438     @Test(expectedExceptions=IllegalArgumentException.class)
 439     public void test_parseBest_String_oneRule() throws Exception {
 440         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 441         test.parseBest("30", LocalDate::from);
 442     }
 443 
 444     //-----------------------------------------------------------------------
 445     @Test
 446     public void test_parseToBuilder_String() throws Exception {
 447         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 448         DateTimeBuilder result = test.parseToBuilder("ONE30");
 449         assertEquals(result.getFieldValueMap().size(), 1);
 450         assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L);
 451         assertEquals(result.getCalendricalList().size(), 0);
 452     }
 453 
 454     @Test
 455     public void test_parseToBuilder_CharSequence() throws Exception {
 456         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 457         DateTimeBuilder result = test.parseToBuilder(new StringBuilder("ONE30"));
 458         assertEquals(result.getFieldValueMap().size(), 1);
 459         assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L);
 460         assertEquals(result.getCalendricalList().size(), 0);
 461     }
 462 
 463     @Test(expectedExceptions=DateTimeParseException.class)
 464     public void test_parseToBuilder_String_parseError() throws Exception {
 465         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 466         try {
 467             test.parseToBuilder("ONEXXX");
 468         } catch (DateTimeParseException ex) {
 469             assertEquals(ex.getMessage().contains("ONEXXX"), true);
 470             assertEquals(ex.getParsedString(), "ONEXXX");
 471             assertEquals(ex.getErrorIndex(), 3);
 472             throw ex;
 473         }
 474     }
 475 
 476     @Test(expectedExceptions=DateTimeParseException.class)
 477     public void test_parseToBuilder_String_parseErrorLongText() throws Exception {
 478         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 479         try {
 480             test.parseToBuilder("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
 481         } catch (DateTimeParseException ex) {
 482             assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true);
 483             assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
 484             assertEquals(ex.getErrorIndex(), 3);
 485             throw ex;
 486         }
 487     }
 488 
 489     @Test(expectedExceptions=DateTimeParseException.class)
 490     public void test_parseToBuilder_String_parseIncomplete() throws Exception {
 491         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 492         try {
 493             test.parseToBuilder("ONE30SomethingElse");
 494         } catch (DateTimeParseException ex) {
 495             assertEquals(ex.getMessage().contains("ONE30SomethingElse"), true);
 496             assertEquals(ex.getParsedString(), "ONE30SomethingElse");
 497             assertEquals(ex.getErrorIndex(), 5);
 498             throw ex;
 499         }
 500     }
 501 
 502     @Test(expectedExceptions=NullPointerException.class)
 503     public void test_parseToBuilder_String_null() throws Exception {
 504         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 505         test.parseToBuilder((String) null);
 506     }
 507 
 508     //-----------------------------------------------------------------------
 509     @Test
 510     public void test_parseToBuilder_StringParsePosition() throws Exception {
 511         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 512         ParsePosition pos = new ParsePosition(0);
 513         DateTimeBuilder result = test.parseToBuilder("ONE30XXX", pos);
 514         assertEquals(pos.getIndex(), 5);
 515         assertEquals(pos.getErrorIndex(), -1);
 516         assertEquals(result.getFieldValueMap().size(), 1);
 517         assertEquals(result.getFieldValueMap().get(DAY_OF_MONTH), Long.valueOf(30));
 518     }
 519 
 520     @Test
 521     public void test_parseToBuilder_StringParsePosition_parseError() throws Exception {
 522         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 523         ParsePosition pos = new ParsePosition(0);
 524         DateTimeBuilder result = test.parseToBuilder("ONEXXX", pos);
 525         assertEquals(pos.getIndex(), 0);  // TODO: is this right?
 526         assertEquals(pos.getErrorIndex(), 3);
 527         assertEquals(result, null);
 528     }
 529 
 530     @Test(expectedExceptions=NullPointerException.class)
 531     public void test_parseToBuilder_StringParsePosition_nullString() throws Exception {
 532         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 533         ParsePosition pos = new ParsePosition(0);
 534         test.parseToBuilder((String) null, pos);
 535     }
 536 
 537     @Test(expectedExceptions=NullPointerException.class)
 538     public void test_parseToBuilder_StringParsePosition_nullParsePosition() throws Exception {
 539         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 540         test.parseToBuilder("ONE30", (ParsePosition) null);
 541     }
 542 
 543     @Test(expectedExceptions=IndexOutOfBoundsException.class)
 544     public void test_parseToBuilder_StringParsePosition_invalidPosition() throws Exception {
 545         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 546         ParsePosition pos = new ParsePosition(6);
 547         test.parseToBuilder("ONE30", pos);
 548     }
 549 
 550     //-----------------------------------------------------------------------
 551     //-----------------------------------------------------------------------
 552     @Test
 553     public void test_toFormat_format() throws Exception {
 554         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 555         Format format = test.toFormat();
 556         String result = format.format(LocalDate.of(2008, 6, 30));
 557         assertEquals(result, "ONE30");
 558     }
 559 
 560     @Test(expectedExceptions=NullPointerException.class)
 561     public void test_toFormat_format_null() throws Exception {
 562         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 563         Format format = test.toFormat();
 564         format.format(null);
 565     }
 566 
 567     @Test(expectedExceptions=IllegalArgumentException.class)
 568     public void test_toFormat_format_notTemporal() throws Exception {
 569         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 570         Format format = test.toFormat();
 571         format.format("Not a Temporal");
 572     }
 573 
 574     //-----------------------------------------------------------------------
 575     @Test
 576     public void test_toFormat_parseObject_String() throws Exception {
 577         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 578         Format format = test.toFormat();
 579         DateTimeBuilder result = (DateTimeBuilder) format.parseObject("ONE30");
 580         assertEquals(result.getFieldValueMap().size(), 1);
 581         assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L);
 582     }
 583 
 584     @Test(expectedExceptions=ParseException.class)
 585     public void test_toFormat_parseObject_String_parseError() throws Exception {
 586         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 587         Format format = test.toFormat();
 588         try {
 589             format.parseObject("ONEXXX");
 590         } catch (ParseException ex) {
 591             assertEquals(ex.getMessage().contains("ONEXXX"), true);
 592             assertEquals(ex.getErrorOffset(), 3);
 593             throw ex;
 594         }
 595     }
 596 
 597     @Test(expectedExceptions=ParseException.class)
 598     public void test_toFormat_parseObject_String_parseErrorLongText() throws Exception {
 599         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 600         Format format = test.toFormat();
 601         try {
 602             format.parseObject("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
 603         } catch (DateTimeParseException ex) {
 604             assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true);
 605             assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789");
 606             assertEquals(ex.getErrorIndex(), 3);
 607             throw ex;
 608         }
 609     }
 610 
 611     @Test(expectedExceptions=NullPointerException.class)
 612     public void test_toFormat_parseObject_String_null() throws Exception {
 613         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 614         Format format = test.toFormat();
 615         format.parseObject((String) null);
 616     }
 617 
 618     //-----------------------------------------------------------------------
 619     @Test
 620     public void test_toFormat_parseObject_StringParsePosition() throws Exception {
 621         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 622         Format format = test.toFormat();
 623         ParsePosition pos = new ParsePosition(0);
 624         DateTimeBuilder result = (DateTimeBuilder) format.parseObject("ONE30XXX", pos);
 625         assertEquals(pos.getIndex(), 5);
 626         assertEquals(pos.getErrorIndex(), -1);
 627         assertEquals(result.getFieldValueMap().size(), 1);
 628         assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L);
 629     }
 630 
 631     @Test
 632     public void test_toFormat_parseObject_StringParsePosition_parseError() throws Exception {
 633         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 634         Format format = test.toFormat();
 635         ParsePosition pos = new ParsePosition(0);
 636         TemporalAccessor result = (TemporalAccessor) format.parseObject("ONEXXX", pos);
 637         assertEquals(pos.getIndex(), 0);  // TODO: is this right?
 638         assertEquals(pos.getErrorIndex(), 3);
 639         assertEquals(result, null);
 640     }
 641 
 642     @Test(expectedExceptions=NullPointerException.class)
 643     public void test_toFormat_parseObject_StringParsePosition_nullString() throws Exception {
 644         // SimpleDateFormat has this behavior
 645         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 646         Format format = test.toFormat();
 647         ParsePosition pos = new ParsePosition(0);
 648         format.parseObject((String) null, pos);
 649     }
 650 
 651     @Test(expectedExceptions=NullPointerException.class)
 652     public void test_toFormat_parseObject_StringParsePosition_nullParsePosition() throws Exception {
 653         // SimpleDateFormat has this behavior
 654         DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 655         Format format = test.toFormat();
 656         format.parseObject("ONE30", (ParsePosition) null);
 657     }
 658 
 659     @Test
 660     public void test_toFormat_parseObject_StringParsePosition_invalidPosition_tooBig() throws Exception {
 661         // SimpleDateFormat has this behavior
 662         DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 663         ParsePosition pos = new ParsePosition(6);
 664         Format test = dtf.toFormat();
 665         assertNull(test.parseObject("ONE30", pos));
 666         assertTrue(pos.getErrorIndex() >= 0);
 667     }
 668 
 669     @Test
 670     public void test_toFormat_parseObject_StringParsePosition_invalidPosition_tooSmall() throws Exception {
 671         // SimpleDateFormat throws StringIndexOutOfBoundException
 672         DateTimeFormatter dtf = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD);
 673         ParsePosition pos = new ParsePosition(-1);
 674         Format test = dtf.toFormat();
 675         assertNull(test.parseObject("ONE30", pos));
 676         assertTrue(pos.getErrorIndex() >= 0);
 677     }
 678 
 679     //-----------------------------------------------------------------------
 680     @Test
 681     public void test_toFormat_Query_format() throws Exception {
 682         Format format = BASIC_FORMATTER.toFormat();
 683         String result = format.format(LocalDate.of(2008, 6, 30));
 684         assertEquals(result, "ONE30");
 685     }
 686 
 687     @Test
 688     public void test_toFormat_Query_parseObject_String() throws Exception {
 689         Format format = DATE_FORMATTER.toFormat(LocalDate::from);
 690         LocalDate result = (LocalDate) format.parseObject("ONE2012 07 27");
 691         assertEquals(result, LocalDate.of(2012, 7, 27));
 692     }
 693 
 694     @Test(expectedExceptions=ParseException.class)
 695     public void test_toFormat_parseObject_StringParsePosition_dateTimeError() throws Exception {
 696         Format format = DATE_FORMATTER.toFormat(LocalDate::from);
 697         format.parseObject("ONE2012 07 32");
 698     }
 699 
 700     @Test(expectedExceptions=NullPointerException.class)
 701     public void test_toFormat_Query() throws Exception {
 702         BASIC_FORMATTER.toFormat(null);
 703     }
 704 
 705 }