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) 2009-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.MINUTE_OF_HOUR; 65 import static java.time.temporal.ChronoField.MONTH_OF_YEAR; 66 import static java.time.temporal.ChronoField.NANO_OF_SECOND; 67 import static java.time.temporal.ChronoField.YEAR; 68 import static org.testng.Assert.assertEquals; 69 70 import java.text.ParsePosition; 71 import java.time.LocalDate; 72 import java.time.YearMonth; 73 import java.time.ZoneOffset; 74 import java.time.format.DateTimeFormatter; 75 import java.time.format.DateTimeFormatterBuilder; 76 import java.time.format.SignStyle; 77 import java.time.format.TextStyle; 78 import java.time.temporal.Temporal; 79 import java.time.temporal.TemporalAccessor; 80 import java.util.HashMap; 81 import java.util.Locale; 82 import java.util.Map; 83 84 import org.testng.annotations.BeforeMethod; 85 import org.testng.annotations.DataProvider; 86 import org.testng.annotations.Test; 87 88 /** 89 * Test DateTimeFormatterBuilder. 90 */ 91 @Test 92 public class TCKDateTimeFormatterBuilder { 93 94 private DateTimeFormatterBuilder builder; 95 96 @BeforeMethod setUp()97 public void setUp() { 98 builder = new DateTimeFormatterBuilder(); 99 } 100 101 //----------------------------------------------------------------------- 102 @Test test_toFormatter_empty()103 public void test_toFormatter_empty() throws Exception { 104 DateTimeFormatter f = builder.toFormatter(); 105 assertEquals(f.format(LocalDate.of(2012, 6, 30)), ""); 106 } 107 108 //----------------------------------------------------------------------- 109 @Test test_parseDefaulting_entireDate()110 public void test_parseDefaulting_entireDate() { 111 DateTimeFormatter f = builder 112 .parseDefaulting(YEAR, 2012).parseDefaulting(MONTH_OF_YEAR, 6) 113 .parseDefaulting(DAY_OF_MONTH, 30).toFormatter(); 114 LocalDate parsed = f.parse("", LocalDate::from); // blank string can be parsed 115 assertEquals(parsed, LocalDate.of(2012, 6, 30)); 116 } 117 118 @Test test_parseDefaulting_yearOptionalMonthOptionalDay()119 public void test_parseDefaulting_yearOptionalMonthOptionalDay() { 120 DateTimeFormatter f = builder 121 .appendValue(YEAR) 122 .optionalStart().appendLiteral('-').appendValue(MONTH_OF_YEAR) 123 .optionalStart().appendLiteral('-').appendValue(DAY_OF_MONTH) 124 .optionalEnd().optionalEnd() 125 .parseDefaulting(MONTH_OF_YEAR, 1) 126 .parseDefaulting(DAY_OF_MONTH, 1).toFormatter(); 127 assertEquals(f.parse("2012", LocalDate::from), LocalDate.of(2012, 1, 1)); 128 assertEquals(f.parse("2012-6", LocalDate::from), LocalDate.of(2012, 6, 1)); 129 assertEquals(f.parse("2012-6-30", LocalDate::from), LocalDate.of(2012, 6, 30)); 130 } 131 132 @Test(expectedExceptions = NullPointerException.class) test_parseDefaulting_null()133 public void test_parseDefaulting_null() { 134 builder.parseDefaulting(null, 1); 135 } 136 137 //----------------------------------------------------------------------- 138 @Test(expectedExceptions=NullPointerException.class) test_appendValue_1arg_null()139 public void test_appendValue_1arg_null() throws Exception { 140 builder.appendValue(null); 141 } 142 143 //----------------------------------------------------------------------- 144 @Test(expectedExceptions=NullPointerException.class) test_appendValue_2arg_null()145 public void test_appendValue_2arg_null() throws Exception { 146 builder.appendValue(null, 3); 147 } 148 149 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_2arg_widthTooSmall()150 public void test_appendValue_2arg_widthTooSmall() throws Exception { 151 builder.appendValue(DAY_OF_MONTH, 0); 152 } 153 154 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_2arg_widthTooBig()155 public void test_appendValue_2arg_widthTooBig() throws Exception { 156 builder.appendValue(DAY_OF_MONTH, 20); 157 } 158 159 //----------------------------------------------------------------------- 160 @Test(expectedExceptions=NullPointerException.class) test_appendValue_3arg_nullField()161 public void test_appendValue_3arg_nullField() throws Exception { 162 builder.appendValue(null, 2, 3, SignStyle.NORMAL); 163 } 164 165 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_minWidthTooSmall()166 public void test_appendValue_3arg_minWidthTooSmall() throws Exception { 167 builder.appendValue(DAY_OF_MONTH, 0, 2, SignStyle.NORMAL); 168 } 169 170 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_minWidthTooBig()171 public void test_appendValue_3arg_minWidthTooBig() throws Exception { 172 builder.appendValue(DAY_OF_MONTH, 20, 2, SignStyle.NORMAL); 173 } 174 175 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_maxWidthTooSmall()176 public void test_appendValue_3arg_maxWidthTooSmall() throws Exception { 177 builder.appendValue(DAY_OF_MONTH, 2, 0, SignStyle.NORMAL); 178 } 179 180 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_maxWidthTooBig()181 public void test_appendValue_3arg_maxWidthTooBig() throws Exception { 182 builder.appendValue(DAY_OF_MONTH, 2, 20, SignStyle.NORMAL); 183 } 184 185 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_maxWidthMinWidth()186 public void test_appendValue_3arg_maxWidthMinWidth() throws Exception { 187 builder.appendValue(DAY_OF_MONTH, 4, 2, SignStyle.NORMAL); 188 } 189 190 @Test(expectedExceptions=NullPointerException.class) test_appendValue_3arg_nullSignStyle()191 public void test_appendValue_3arg_nullSignStyle() throws Exception { 192 builder.appendValue(DAY_OF_MONTH, 2, 3, null); 193 } 194 195 //----------------------------------------------------------------------- 196 @Test(expectedExceptions=NullPointerException.class) test_appendValueReduced_int_nullField()197 public void test_appendValueReduced_int_nullField() throws Exception { 198 builder.appendValueReduced(null, 2, 2, 2000); 199 } 200 201 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_minWidthTooSmall()202 public void test_appendValueReduced_int_minWidthTooSmall() throws Exception { 203 builder.appendValueReduced(YEAR, 0, 2, 2000); 204 } 205 206 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_minWidthTooBig()207 public void test_appendValueReduced_int_minWidthTooBig() throws Exception { 208 builder.appendValueReduced(YEAR, 11, 2, 2000); 209 } 210 211 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_maxWidthTooSmall()212 public void test_appendValueReduced_int_maxWidthTooSmall() throws Exception { 213 builder.appendValueReduced(YEAR, 2, 0, 2000); 214 } 215 216 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_maxWidthTooBig()217 public void test_appendValueReduced_int_maxWidthTooBig() throws Exception { 218 builder.appendValueReduced(YEAR, 2, 11, 2000); 219 } 220 221 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_maxWidthLessThanMin()222 public void test_appendValueReduced_int_maxWidthLessThanMin() throws Exception { 223 builder.appendValueReduced(YEAR, 2, 1, 2000); 224 } 225 226 //----------------------------------------------------------------------- 227 @Test(expectedExceptions=NullPointerException.class) test_appendValueReduced_date_nullField()228 public void test_appendValueReduced_date_nullField() throws Exception { 229 builder.appendValueReduced(null, 2, 2, LocalDate.of(2000, 1, 1)); 230 } 231 232 @Test(expectedExceptions=NullPointerException.class) test_appendValueReduced_date_nullDate()233 public void test_appendValueReduced_date_nullDate() throws Exception { 234 builder.appendValueReduced(YEAR, 2, 2, null); 235 } 236 237 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_minWidthTooSmall()238 public void test_appendValueReduced_date_minWidthTooSmall() throws Exception { 239 builder.appendValueReduced(YEAR, 0, 2, LocalDate.of(2000, 1, 1)); 240 } 241 242 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_minWidthTooBig()243 public void test_appendValueReduced_date_minWidthTooBig() throws Exception { 244 builder.appendValueReduced(YEAR, 11, 2, LocalDate.of(2000, 1, 1)); 245 } 246 247 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_maxWidthTooSmall()248 public void test_appendValueReduced_date_maxWidthTooSmall() throws Exception { 249 builder.appendValueReduced(YEAR, 2, 0, LocalDate.of(2000, 1, 1)); 250 } 251 252 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_maxWidthTooBig()253 public void test_appendValueReduced_date_maxWidthTooBig() throws Exception { 254 builder.appendValueReduced(YEAR, 2, 11, LocalDate.of(2000, 1, 1)); 255 } 256 257 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_maxWidthLessThanMin()258 public void test_appendValueReduced_date_maxWidthLessThanMin() throws Exception { 259 builder.appendValueReduced(YEAR, 2, 1, LocalDate.of(2000, 1, 1)); 260 } 261 262 //----------------------------------------------------------------------- 263 //----------------------------------------------------------------------- 264 //----------------------------------------------------------------------- 265 @Test(expectedExceptions=NullPointerException.class) test_appendFraction_4arg_nullRule()266 public void test_appendFraction_4arg_nullRule() throws Exception { 267 builder.appendFraction(null, 1, 9, false); 268 } 269 270 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_invalidRuleNotFixedSet()271 public void test_appendFraction_4arg_invalidRuleNotFixedSet() throws Exception { 272 builder.appendFraction(DAY_OF_MONTH, 1, 9, false); 273 } 274 275 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_minTooSmall()276 public void test_appendFraction_4arg_minTooSmall() throws Exception { 277 builder.appendFraction(MINUTE_OF_HOUR, -1, 9, false); 278 } 279 280 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_minTooBig()281 public void test_appendFraction_4arg_minTooBig() throws Exception { 282 builder.appendFraction(MINUTE_OF_HOUR, 10, 9, false); 283 } 284 285 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_maxTooSmall()286 public void test_appendFraction_4arg_maxTooSmall() throws Exception { 287 builder.appendFraction(MINUTE_OF_HOUR, 0, -1, false); 288 } 289 290 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_maxTooBig()291 public void test_appendFraction_4arg_maxTooBig() throws Exception { 292 builder.appendFraction(MINUTE_OF_HOUR, 1, 10, false); 293 } 294 295 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_maxWidthMinWidth()296 public void test_appendFraction_4arg_maxWidthMinWidth() throws Exception { 297 builder.appendFraction(MINUTE_OF_HOUR, 9, 3, false); 298 } 299 300 //----------------------------------------------------------------------- 301 //----------------------------------------------------------------------- 302 //----------------------------------------------------------------------- 303 @Test(expectedExceptions=NullPointerException.class) test_appendText_1arg_null()304 public void test_appendText_1arg_null() throws Exception { 305 builder.appendText(null); 306 } 307 308 //----------------------------------------------------------------------- 309 @Test(expectedExceptions=NullPointerException.class) test_appendText_2arg_nullRule()310 public void test_appendText_2arg_nullRule() throws Exception { 311 builder.appendText(null, TextStyle.SHORT); 312 } 313 314 @Test(expectedExceptions=NullPointerException.class) test_appendText_2arg_nullStyle()315 public void test_appendText_2arg_nullStyle() throws Exception { 316 builder.appendText(MONTH_OF_YEAR, (TextStyle) null); 317 } 318 319 //----------------------------------------------------------------------- 320 @Test(expectedExceptions=NullPointerException.class) test_appendTextMap_nullRule()321 public void test_appendTextMap_nullRule() throws Exception { 322 builder.appendText(null, new HashMap<>()); 323 } 324 325 @Test(expectedExceptions=NullPointerException.class) test_appendTextMap_nullStyle()326 public void test_appendTextMap_nullStyle() throws Exception { 327 builder.appendText(MONTH_OF_YEAR, (Map<Long, String>) null); 328 } 329 330 //----------------------------------------------------------------------- 331 //----------------------------------------------------------------------- 332 //----------------------------------------------------------------------- 333 @DataProvider(name="offsetPatterns") data_offsetPatterns()334 Object[][] data_offsetPatterns() { 335 return new Object[][] { 336 {"+HH", 2, 0, 0, "+02"}, 337 {"+HH", -2, 0, 0, "-02"}, 338 {"+HH", 2, 30, 0, "+02"}, 339 {"+HH", 2, 0, 45, "+02"}, 340 {"+HH", 2, 30, 45, "+02"}, 341 342 {"+HHMM", 2, 0, 0, "+0200"}, 343 {"+HHMM", -2, 0, 0, "-0200"}, 344 {"+HHMM", 2, 30, 0, "+0230"}, 345 {"+HHMM", 2, 0, 45, "+0200"}, 346 {"+HHMM", 2, 30, 45, "+0230"}, 347 348 {"+HH:MM", 2, 0, 0, "+02:00"}, 349 {"+HH:MM", -2, 0, 0, "-02:00"}, 350 {"+HH:MM", 2, 30, 0, "+02:30"}, 351 {"+HH:MM", 2, 0, 45, "+02:00"}, 352 {"+HH:MM", 2, 30, 45, "+02:30"}, 353 354 {"+HHMMss", 2, 0, 0, "+0200"}, 355 {"+HHMMss", -2, 0, 0, "-0200"}, 356 {"+HHMMss", 2, 30, 0, "+0230"}, 357 {"+HHMMss", 2, 0, 45, "+020045"}, 358 {"+HHMMss", 2, 30, 45, "+023045"}, 359 360 {"+HH:MM:ss", 2, 0, 0, "+02:00"}, 361 {"+HH:MM:ss", -2, 0, 0, "-02:00"}, 362 {"+HH:MM:ss", 2, 30, 0, "+02:30"}, 363 {"+HH:MM:ss", 2, 0, 45, "+02:00:45"}, 364 {"+HH:MM:ss", 2, 30, 45, "+02:30:45"}, 365 366 {"+HHMMSS", 2, 0, 0, "+020000"}, 367 {"+HHMMSS", -2, 0, 0, "-020000"}, 368 {"+HHMMSS", 2, 30, 0, "+023000"}, 369 {"+HHMMSS", 2, 0, 45, "+020045"}, 370 {"+HHMMSS", 2, 30, 45, "+023045"}, 371 372 {"+HH:MM:SS", 2, 0, 0, "+02:00:00"}, 373 {"+HH:MM:SS", -2, 0, 0, "-02:00:00"}, 374 {"+HH:MM:SS", 2, 30, 0, "+02:30:00"}, 375 {"+HH:MM:SS", 2, 0, 45, "+02:00:45"}, 376 {"+HH:MM:SS", 2, 30, 45, "+02:30:45"}, 377 }; 378 } 379 380 @Test(dataProvider="offsetPatterns") test_appendOffset_format(String pattern, int h, int m, int s, String expected)381 public void test_appendOffset_format(String pattern, int h, int m, int s, String expected) throws Exception { 382 builder.appendOffset(pattern, "Z"); 383 DateTimeFormatter f = builder.toFormatter(); 384 ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); 385 assertEquals(f.format(offset), expected); 386 } 387 388 @Test(dataProvider="offsetPatterns") test_appendOffset_parse(String pattern, int h, int m, int s, String expected)389 public void test_appendOffset_parse(String pattern, int h, int m, int s, String expected) throws Exception { 390 builder.appendOffset(pattern, "Z"); 391 DateTimeFormatter f = builder.toFormatter(); 392 ZoneOffset parsed = f.parse(expected, ZoneOffset::from); 393 assertEquals(f.format(parsed), expected); 394 } 395 396 @DataProvider(name="badOffsetPatterns") data_badOffsetPatterns()397 Object[][] data_badOffsetPatterns() { 398 return new Object[][] { 399 {"HH"}, 400 {"HHMM"}, 401 {"HH:MM"}, 402 {"HHMMss"}, 403 {"HH:MM:ss"}, 404 {"HHMMSS"}, 405 {"HH:MM:SS"}, 406 {"+H"}, 407 {"+HMM"}, 408 {"+HHM"}, 409 {"+A"}, 410 }; 411 } 412 413 @Test(dataProvider="badOffsetPatterns", expectedExceptions=IllegalArgumentException.class) test_appendOffset_badPattern(String pattern)414 public void test_appendOffset_badPattern(String pattern) throws Exception { 415 builder.appendOffset(pattern, "Z"); 416 } 417 418 @Test(expectedExceptions=NullPointerException.class) test_appendOffset_3arg_nullText()419 public void test_appendOffset_3arg_nullText() throws Exception { 420 builder.appendOffset("+HH:MM", null); 421 } 422 423 @Test(expectedExceptions=NullPointerException.class) test_appendOffset_3arg_nullPattern()424 public void test_appendOffset_3arg_nullPattern() throws Exception { 425 builder.appendOffset(null, "Z"); 426 } 427 428 //----------------------------------------------------------------------- 429 //----------------------------------------------------------------------- 430 //----------------------------------------------------------------------- 431 @Test(expectedExceptions=NullPointerException.class) test_appendZoneText_1arg_nullText()432 public void test_appendZoneText_1arg_nullText() throws Exception { 433 builder.appendZoneText(null); 434 } 435 436 //----------------------------------------------------------------------- 437 //----------------------------------------------------------------------- 438 //----------------------------------------------------------------------- 439 @Test test_padNext_1arg()440 public void test_padNext_1arg() { 441 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2).appendValue(DAY_OF_MONTH); 442 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1"); 443 } 444 445 @Test(expectedExceptions=IllegalArgumentException.class) test_padNext_1arg_invalidWidth()446 public void test_padNext_1arg_invalidWidth() throws Exception { 447 builder.padNext(0); 448 } 449 450 //----------------------------------------------------------------------- 451 @Test test_padNext_2arg_dash()452 public void test_padNext_2arg_dash() throws Exception { 453 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2, '-').appendValue(DAY_OF_MONTH); 454 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2:-1"); 455 } 456 457 @Test(expectedExceptions=IllegalArgumentException.class) test_padNext_2arg_invalidWidth()458 public void test_padNext_2arg_invalidWidth() throws Exception { 459 builder.padNext(0, '-'); 460 } 461 462 //----------------------------------------------------------------------- 463 @Test test_padOptional()464 public void test_padOptional() throws Exception { 465 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':') 466 .padNext(5).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd() 467 .appendLiteral(':').appendValue(YEAR); 468 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1:2013"); 469 assertEquals(builder.toFormatter().format(YearMonth.of(2013, 2)), "2: :2013"); 470 } 471 472 //----------------------------------------------------------------------- 473 //----------------------------------------------------------------------- 474 //----------------------------------------------------------------------- 475 @Test(expectedExceptions=IllegalStateException.class) test_optionalEnd_noStart()476 public void test_optionalEnd_noStart() throws Exception { 477 builder.optionalEnd(); 478 } 479 480 //----------------------------------------------------------------------- 481 //----------------------------------------------------------------------- 482 //----------------------------------------------------------------------- 483 @DataProvider(name="validPatterns") dataValid()484 Object[][] dataValid() { 485 return new Object[][] { 486 {"'a'"}, 487 {"''"}, 488 {"'!'"}, 489 {"!"}, 490 {"'#'"}, 491 492 {"'hello_people,][)('"}, 493 {"'hi'"}, 494 {"'yyyy'"}, 495 {"''''"}, 496 {"'o''clock'"}, 497 498 {"G"}, 499 {"GG"}, 500 {"GGG"}, 501 {"GGGG"}, 502 {"GGGGG"}, 503 504 {"y"}, 505 {"yy"}, 506 {"yyy"}, 507 {"yyyy"}, 508 {"yyyyy"}, 509 510 {"M"}, 511 {"MM"}, 512 {"MMM"}, 513 {"MMMM"}, 514 {"MMMMM"}, 515 516 {"L"}, 517 {"LL"}, 518 {"LLL"}, 519 {"LLLL"}, 520 {"LLLLL"}, 521 522 {"D"}, 523 {"DD"}, 524 {"DDD"}, 525 526 {"d"}, 527 {"dd"}, 528 529 {"F"}, 530 531 {"Q"}, 532 {"QQ"}, 533 {"QQQ"}, 534 {"QQQQ"}, 535 {"QQQQQ"}, 536 537 {"q"}, 538 {"qq"}, 539 {"qqq"}, 540 {"qqqq"}, 541 {"qqqqq"}, 542 543 {"E"}, 544 {"EE"}, 545 {"EEE"}, 546 {"EEEE"}, 547 {"EEEEE"}, 548 549 {"e"}, 550 {"ee"}, 551 {"eee"}, 552 {"eeee"}, 553 {"eeeee"}, 554 555 {"c"}, 556 {"ccc"}, 557 {"cccc"}, 558 {"ccccc"}, 559 560 {"a"}, 561 562 {"H"}, 563 {"HH"}, 564 565 {"K"}, 566 {"KK"}, 567 568 {"k"}, 569 {"kk"}, 570 571 {"h"}, 572 {"hh"}, 573 574 {"m"}, 575 {"mm"}, 576 577 {"s"}, 578 {"ss"}, 579 580 {"S"}, 581 {"SS"}, 582 {"SSS"}, 583 {"SSSSSSSSS"}, 584 585 {"A"}, 586 {"AA"}, 587 {"AAA"}, 588 589 {"n"}, 590 {"nn"}, 591 {"nnn"}, 592 593 {"N"}, 594 {"NN"}, 595 {"NNN"}, 596 597 {"z"}, 598 {"zz"}, 599 {"zzz"}, 600 {"zzzz"}, 601 602 {"VV"}, 603 604 {"Z"}, 605 {"ZZ"}, 606 {"ZZZ"}, 607 608 {"X"}, 609 {"XX"}, 610 {"XXX"}, 611 {"XXXX"}, 612 {"XXXXX"}, 613 614 {"x"}, 615 {"xx"}, 616 {"xxx"}, 617 {"xxxx"}, 618 {"xxxxx"}, 619 620 {"ppH"}, 621 {"pppDD"}, 622 623 {"yyyy[-MM[-dd"}, 624 {"yyyy[-MM[-dd]]"}, 625 {"yyyy[-MM[]-dd]"}, 626 627 {"yyyy-MM-dd'T'HH:mm:ss.SSS"}, 628 629 {"e"}, 630 {"w"}, 631 {"ww"}, 632 {"W"}, 633 {"W"}, 634 635 }; 636 } 637 638 @Test(dataProvider="validPatterns") test_appendPattern_valid(String input)639 public void test_appendPattern_valid(String input) throws Exception { 640 builder.appendPattern(input); // test is for no error here 641 } 642 643 //----------------------------------------------------------------------- 644 @DataProvider(name="invalidPatterns") dataInvalid()645 Object[][] dataInvalid() { 646 return new Object[][] { 647 {"'"}, 648 {"'hello"}, 649 {"'hel''lo"}, 650 {"'hello''"}, 651 {"{"}, 652 {"}"}, 653 {"{}"}, 654 {"#"}, 655 {"]"}, 656 {"yyyy]"}, 657 {"yyyy]MM"}, 658 {"yyyy[MM]]"}, 659 660 {"aa"}, 661 {"aaa"}, 662 {"aaaa"}, 663 {"aaaaa"}, 664 {"aaaaaa"}, 665 {"MMMMMM"}, 666 {"QQQQQQ"}, 667 {"qqqqqq"}, 668 {"EEEEEE"}, 669 {"eeeeee"}, 670 {"cc"}, 671 {"cccccc"}, 672 {"ddd"}, 673 {"DDDD"}, 674 {"FF"}, 675 {"FFF"}, 676 {"hhh"}, 677 {"HHH"}, 678 {"kkk"}, 679 {"KKK"}, 680 {"mmm"}, 681 {"sss"}, 682 {"OO"}, 683 {"OOO"}, 684 {"OOOOO"}, 685 {"XXXXXX"}, 686 {"zzzzz"}, 687 {"ZZZZZZ"}, 688 689 {"RO"}, 690 691 {"p"}, 692 {"pp"}, 693 {"p:"}, 694 695 {"f"}, 696 {"ff"}, 697 {"f:"}, 698 {"fy"}, 699 {"fa"}, 700 {"fM"}, 701 702 {"www"}, 703 {"WW"}, 704 }; 705 } 706 707 @Test(dataProvider="invalidPatterns", expectedExceptions=IllegalArgumentException.class) test_appendPattern_invalid(String input)708 public void test_appendPattern_invalid(String input) throws Exception { 709 builder.appendPattern(input); // test is for error here 710 } 711 712 //----------------------------------------------------------------------- 713 @DataProvider(name="patternPrint") data_patternPrint()714 Object[][] data_patternPrint() { 715 return new Object[][] { 716 {"Q", date(2012, 2, 10), "1"}, 717 {"QQ", date(2012, 2, 10), "01"}, 718 {"QQQ", date(2012, 2, 10), "Q1"}, 719 {"QQQQ", date(2012, 2, 10), "1st quarter"}, 720 {"QQQQQ", date(2012, 2, 10), "1"}, 721 }; 722 } 723 724 @Test(dataProvider="patternPrint") test_appendPattern_patternPrint(String input, Temporal temporal, String expected)725 public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { 726 DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); 727 String test = f.format(temporal); 728 assertEquals(test, expected); 729 } 730 date(int y, int m, int d)731 private static Temporal date(int y, int m, int d) { 732 return LocalDate.of(y, m, d); 733 } 734 735 //----------------------------------------------------------------------- 736 @Test test_adjacent_strict_firstFixedWidth()737 public void test_adjacent_strict_firstFixedWidth() throws Exception { 738 // succeeds because both number elements are fixed width 739 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 740 ParsePosition pp = new ParsePosition(0); 741 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 742 assertEquals(pp.getErrorIndex(), -1); 743 assertEquals(pp.getIndex(), 5); 744 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 745 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 746 } 747 748 @Test test_adjacent_strict_firstVariableWidth_success()749 public void test_adjacent_strict_firstVariableWidth_success() throws Exception { 750 // succeeds greedily parsing variable width, then fixed width, to non-numeric Z 751 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('Z').toFormatter(Locale.UK); 752 ParsePosition pp = new ParsePosition(0); 753 TemporalAccessor parsed = f.parseUnresolved("12309Z", pp); 754 assertEquals(pp.getErrorIndex(), -1); 755 assertEquals(pp.getIndex(), 6); 756 assertEquals(parsed.getLong(HOUR_OF_DAY), 123L); 757 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 9L); 758 } 759 760 @Test test_adjacent_strict_firstVariableWidth_fails()761 public void test_adjacent_strict_firstVariableWidth_fails() throws Exception { 762 // fails because literal is a number and variable width parse greedily absorbs it 763 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 764 ParsePosition pp = new ParsePosition(0); 765 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 766 assertEquals(pp.getErrorIndex(), 5); 767 assertEquals(parsed, null); 768 } 769 770 @Test test_adjacent_lenient()771 public void test_adjacent_lenient() throws Exception { 772 // succeeds because both number elements are fixed width even in lenient mode 773 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 774 ParsePosition pp = new ParsePosition(0); 775 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 776 assertEquals(pp.getErrorIndex(), -1); 777 assertEquals(pp.getIndex(), 5); 778 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 779 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 780 } 781 782 @Test test_adjacent_lenient_firstVariableWidth_success()783 public void test_adjacent_lenient_firstVariableWidth_success() throws Exception { 784 // succeeds greedily parsing variable width, then fixed width, to non-numeric Z 785 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('Z').toFormatter(Locale.UK); 786 ParsePosition pp = new ParsePosition(0); 787 TemporalAccessor parsed = f.parseUnresolved("12309Z", pp); 788 assertEquals(pp.getErrorIndex(), -1); 789 assertEquals(pp.getIndex(), 6); 790 assertEquals(parsed.getLong(HOUR_OF_DAY), 123L); 791 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 9L); 792 } 793 794 @Test test_adjacent_lenient_firstVariableWidth_fails()795 public void test_adjacent_lenient_firstVariableWidth_fails() throws Exception { 796 // fails because literal is a number and variable width parse greedily absorbs it 797 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 798 ParsePosition pp = new ParsePosition(0); 799 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 800 assertEquals(pp.getErrorIndex(), 5); 801 assertEquals(parsed, null); 802 } 803 804 //----------------------------------------------------------------------- 805 @Test test_adjacent_strict_fractionFollows()806 public void test_adjacent_strict_fractionFollows() throws Exception { 807 // succeeds because hour/min are fixed width 808 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); 809 ParsePosition pp = new ParsePosition(0); 810 TemporalAccessor parsed = f.parseUnresolved("1230567", pp); 811 assertEquals(pp.getErrorIndex(), -1); 812 assertEquals(pp.getIndex(), 7); 813 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 814 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 815 assertEquals(parsed.getLong(NANO_OF_SECOND), 567_000_000L); 816 } 817 818 @Test test_adjacent_strict_fractionFollows_2digit()819 public void test_adjacent_strict_fractionFollows_2digit() throws Exception { 820 // succeeds because hour/min are fixed width 821 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); 822 ParsePosition pp = new ParsePosition(0); 823 TemporalAccessor parsed = f.parseUnresolved("123056", pp); 824 assertEquals(pp.getErrorIndex(), -1); 825 assertEquals(pp.getIndex(), 6); 826 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 827 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 828 assertEquals(parsed.getLong(NANO_OF_SECOND), 560_000_000L); 829 } 830 831 @Test test_adjacent_strict_fractionFollows_0digit()832 public void test_adjacent_strict_fractionFollows_0digit() throws Exception { 833 // succeeds because hour/min are fixed width 834 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); 835 ParsePosition pp = new ParsePosition(0); 836 TemporalAccessor parsed = f.parseUnresolved("1230", pp); 837 assertEquals(pp.getErrorIndex(), -1); 838 assertEquals(pp.getIndex(), 4); 839 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 840 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 841 } 842 843 @Test test_adjacent_lenient_fractionFollows()844 public void test_adjacent_lenient_fractionFollows() throws Exception { 845 // succeeds because hour/min are fixed width 846 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); 847 ParsePosition pp = new ParsePosition(0); 848 TemporalAccessor parsed = f.parseUnresolved("1230567", pp); 849 assertEquals(pp.getErrorIndex(), -1); 850 assertEquals(pp.getIndex(), 7); 851 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 852 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 853 assertEquals(parsed.getLong(NANO_OF_SECOND), 567_000_000L); 854 } 855 856 @Test test_adjacent_lenient_fractionFollows_2digit()857 public void test_adjacent_lenient_fractionFollows_2digit() throws Exception { 858 // succeeds because hour/min are fixed width 859 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); 860 ParsePosition pp = new ParsePosition(0); 861 TemporalAccessor parsed = f.parseUnresolved("123056", pp); 862 assertEquals(pp.getErrorIndex(), -1); 863 assertEquals(pp.getIndex(), 6); 864 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 865 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 866 assertEquals(parsed.getLong(NANO_OF_SECOND), 560_000_000L); 867 } 868 869 @Test test_adjacent_lenient_fractionFollows_0digit()870 public void test_adjacent_lenient_fractionFollows_0digit() throws Exception { 871 // succeeds because hour/min are fixed width 872 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); 873 ParsePosition pp = new ParsePosition(0); 874 TemporalAccessor parsed = f.parseUnresolved("1230", pp); 875 assertEquals(pp.getErrorIndex(), -1); 876 assertEquals(pp.getIndex(), 4); 877 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 878 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 879 } 880 881 } 882