1 /* 2 * Copyright (c) 2012, 2016, 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 test.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.MINUTE_OF_HOUR; 65 import static java.time.temporal.ChronoField.MONTH_OF_YEAR; 66 import static java.time.temporal.ChronoField.YEAR; 67 import static org.testng.Assert.assertEquals; 68 import static org.testng.Assert.assertNotNull; 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.chrono.Chronology; 75 import java.time.chrono.IsoChronology; 76 import java.time.chrono.JapaneseChronology; 77 import java.time.chrono.MinguoChronology; 78 import java.time.format.DateTimeFormatter; 79 import java.time.format.DateTimeFormatterBuilder; 80 import java.time.format.FormatStyle; 81 import java.time.format.SignStyle; 82 import java.time.format.TextStyle; 83 import java.time.temporal.Temporal; 84 import java.time.temporal.TemporalAccessor; 85 import java.util.HashMap; 86 import java.util.Locale; 87 import java.util.Map; 88 89 import org.testng.annotations.BeforeMethod; 90 import org.testng.annotations.DataProvider; 91 import org.testng.annotations.Test; 92 93 /** 94 * Test DateTimeFormatterBuilder. 95 */ 96 @Test 97 public class TestDateTimeFormatterBuilder { 98 99 private DateTimeFormatterBuilder builder; 100 101 @BeforeMethod 102 public void setUp() { 103 builder = new DateTimeFormatterBuilder(); 104 } 105 106 //----------------------------------------------------------------------- 107 @Test 108 public void test_toFormatter_empty() throws Exception { 109 DateTimeFormatter f = builder.toFormatter(); 110 assertEquals(f.toString(), ""); 111 } 112 113 //----------------------------------------------------------------------- 114 @Test 115 public void test_parseCaseSensitive() throws Exception { 116 builder.parseCaseSensitive(); 117 DateTimeFormatter f = builder.toFormatter(); 118 assertEquals(f.toString(), "ParseCaseSensitive(true)"); 119 } 120 121 @Test 122 public void test_parseCaseInsensitive() throws Exception { 123 builder.parseCaseInsensitive(); 124 DateTimeFormatter f = builder.toFormatter(); 125 assertEquals(f.toString(), "ParseCaseSensitive(false)"); 126 } 127 128 //----------------------------------------------------------------------- 129 @Test 130 public void test_parseStrict() throws Exception { 131 builder.parseStrict(); 132 DateTimeFormatter f = builder.toFormatter(); 133 assertEquals(f.toString(), "ParseStrict(true)"); 134 } 135 136 @Test 137 public void test_parseLenient() throws Exception { 138 builder.parseLenient(); 139 DateTimeFormatter f = builder.toFormatter(); 140 assertEquals(f.toString(), "ParseStrict(false)"); 141 } 142 143 //----------------------------------------------------------------------- 144 @Test 145 public void test_appendValue_1arg() throws Exception { 146 builder.appendValue(DAY_OF_MONTH); 147 DateTimeFormatter f = builder.toFormatter(); 148 assertEquals(f.toString(), "Value(DayOfMonth)"); 149 } 150 151 @Test(expectedExceptions=NullPointerException.class) 152 public void test_appendValue_1arg_null() throws Exception { 153 builder.appendValue(null); 154 } 155 156 //----------------------------------------------------------------------- 157 @Test 158 public void test_appendValue_2arg() throws Exception { 159 builder.appendValue(DAY_OF_MONTH, 3); 160 DateTimeFormatter f = builder.toFormatter(); 161 assertEquals(f.toString(), "Value(DayOfMonth,3)"); 162 } 163 164 @Test(expectedExceptions=NullPointerException.class) 165 public void test_appendValue_2arg_null() throws Exception { 166 builder.appendValue(null, 3); 167 } 168 169 @Test(expectedExceptions=IllegalArgumentException.class) 170 public void test_appendValue_2arg_widthTooSmall() throws Exception { 171 builder.appendValue(DAY_OF_MONTH, 0); 172 } 173 174 @Test(expectedExceptions=IllegalArgumentException.class) 175 public void test_appendValue_2arg_widthTooBig() throws Exception { 176 builder.appendValue(DAY_OF_MONTH, 20); 177 } 178 179 //----------------------------------------------------------------------- 180 @Test 181 public void test_appendValue_3arg() throws Exception { 182 builder.appendValue(DAY_OF_MONTH, 2, 3, SignStyle.NORMAL); 183 DateTimeFormatter f = builder.toFormatter(); 184 assertEquals(f.toString(), "Value(DayOfMonth,2,3,NORMAL)"); 185 } 186 187 @Test(expectedExceptions=NullPointerException.class) 188 public void test_appendValue_3arg_nullField() throws Exception { 189 builder.appendValue(null, 2, 3, SignStyle.NORMAL); 190 } 191 192 @Test(expectedExceptions=IllegalArgumentException.class) 193 public void test_appendValue_3arg_minWidthTooSmall() throws Exception { 194 builder.appendValue(DAY_OF_MONTH, 0, 2, SignStyle.NORMAL); 195 } 196 197 @Test(expectedExceptions=IllegalArgumentException.class) 198 public void test_appendValue_3arg_minWidthTooBig() throws Exception { 199 builder.appendValue(DAY_OF_MONTH, 20, 2, SignStyle.NORMAL); 200 } 201 202 @Test(expectedExceptions=IllegalArgumentException.class) 203 public void test_appendValue_3arg_maxWidthTooSmall() throws Exception { 204 builder.appendValue(DAY_OF_MONTH, 2, 0, SignStyle.NORMAL); 205 } 206 207 @Test(expectedExceptions=IllegalArgumentException.class) 208 public void test_appendValue_3arg_maxWidthTooBig() throws Exception { 209 builder.appendValue(DAY_OF_MONTH, 2, 20, SignStyle.NORMAL); 210 } 211 212 @Test(expectedExceptions=IllegalArgumentException.class) 213 public void test_appendValue_3arg_maxWidthMinWidth() throws Exception { 214 builder.appendValue(DAY_OF_MONTH, 4, 2, SignStyle.NORMAL); 215 } 216 217 @Test(expectedExceptions=NullPointerException.class) 218 public void test_appendValue_3arg_nullSignStyle() throws Exception { 219 builder.appendValue(DAY_OF_MONTH, 2, 3, null); 220 } 221 222 //----------------------------------------------------------------------- 223 @Test 224 public void test_appendValue_subsequent2_parse3() throws Exception { 225 builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2); 226 DateTimeFormatter f = builder.toFormatter(); 227 assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)"); 228 TemporalAccessor parsed = f.parseUnresolved("123", new ParsePosition(0)); 229 assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); 230 assertEquals(parsed.getLong(DAY_OF_MONTH), 23L); 231 } 232 233 @Test 234 public void test_appendValue_subsequent2_parse4() throws Exception { 235 builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2); 236 DateTimeFormatter f = builder.toFormatter(); 237 assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)"); 238 TemporalAccessor parsed = f.parseUnresolved("0123", new ParsePosition(0)); 239 assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); 240 assertEquals(parsed.getLong(DAY_OF_MONTH), 23L); 241 } 242 243 @Test 244 public void test_appendValue_subsequent2_parse5() throws Exception { 245 builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2).appendLiteral('4'); 246 DateTimeFormatter f = builder.toFormatter(); 247 assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)'4'"); 248 TemporalAccessor parsed = f.parseUnresolved("01234", new ParsePosition(0)); 249 assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); 250 assertEquals(parsed.getLong(DAY_OF_MONTH), 23L); 251 } 252 253 @Test 254 public void test_appendValue_subsequent3_parse6() throws Exception { 255 builder 256 .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) 257 .appendValue(MONTH_OF_YEAR, 2) 258 .appendValue(DAY_OF_MONTH, 2); 259 DateTimeFormatter f = builder.toFormatter(); 260 assertEquals(f.toString(), "Value(Year,4,10,EXCEEDS_PAD)Value(MonthOfYear,2)Value(DayOfMonth,2)"); 261 TemporalAccessor parsed = f.parseUnresolved("20090630", new ParsePosition(0)); 262 assertEquals(parsed.getLong(YEAR), 2009L); 263 assertEquals(parsed.getLong(MONTH_OF_YEAR), 6L); 264 assertEquals(parsed.getLong(DAY_OF_MONTH), 30L); 265 } 266 267 //----------------------------------------------------------------------- 268 @Test(expectedExceptions=NullPointerException.class) 269 public void test_appendValueReduced_null() throws Exception { 270 builder.appendValueReduced(null, 2, 2, 2000); 271 } 272 273 @Test 274 public void test_appendValueReduced() throws Exception { 275 builder.appendValueReduced(YEAR, 2, 2, 2000); 276 DateTimeFormatter f = builder.toFormatter(); 277 assertEquals(f.toString(), "ReducedValue(Year,2,2,2000)"); 278 TemporalAccessor parsed = f.parseUnresolved("12", new ParsePosition(0)); 279 assertEquals(parsed.getLong(YEAR), 2012L); 280 } 281 282 @Test 283 public void test_appendValueReduced_subsequent_parse() throws Exception { 284 builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValueReduced(YEAR, 2, 2, 2000); 285 DateTimeFormatter f = builder.toFormatter(); 286 assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)ReducedValue(Year,2,2,2000)"); 287 ParsePosition ppos = new ParsePosition(0); 288 TemporalAccessor parsed = f.parseUnresolved("123", ppos); 289 assertNotNull(parsed, "Parse failed: " + ppos.toString()); 290 assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); 291 assertEquals(parsed.getLong(YEAR), 2023L); 292 } 293 294 //----------------------------------------------------------------------- 295 //----------------------------------------------------------------------- 296 //----------------------------------------------------------------------- 297 @Test 298 public void test_appendFraction_4arg() throws Exception { 299 builder.appendFraction(MINUTE_OF_HOUR, 1, 9, false); 300 DateTimeFormatter f = builder.toFormatter(); 301 assertEquals(f.toString(), "Fraction(MinuteOfHour,1,9)"); 302 } 303 304 @Test(expectedExceptions=NullPointerException.class) 305 public void test_appendFraction_4arg_nullRule() throws Exception { 306 builder.appendFraction(null, 1, 9, false); 307 } 308 309 @Test(expectedExceptions=IllegalArgumentException.class) 310 public void test_appendFraction_4arg_invalidRuleNotFixedSet() throws Exception { 311 builder.appendFraction(DAY_OF_MONTH, 1, 9, false); 312 } 313 314 @Test(expectedExceptions=IllegalArgumentException.class) 315 public void test_appendFraction_4arg_minTooSmall() throws Exception { 316 builder.appendFraction(MINUTE_OF_HOUR, -1, 9, false); 317 } 318 319 @Test(expectedExceptions=IllegalArgumentException.class) 320 public void test_appendFraction_4arg_minTooBig() throws Exception { 321 builder.appendFraction(MINUTE_OF_HOUR, 10, 9, false); 322 } 323 324 @Test(expectedExceptions=IllegalArgumentException.class) 325 public void test_appendFraction_4arg_maxTooSmall() throws Exception { 326 builder.appendFraction(MINUTE_OF_HOUR, 0, -1, false); 327 } 328 329 @Test(expectedExceptions=IllegalArgumentException.class) 330 public void test_appendFraction_4arg_maxTooBig() throws Exception { 331 builder.appendFraction(MINUTE_OF_HOUR, 1, 10, false); 332 } 333 334 @Test(expectedExceptions=IllegalArgumentException.class) 335 public void test_appendFraction_4arg_maxWidthMinWidth() throws Exception { 336 builder.appendFraction(MINUTE_OF_HOUR, 9, 3, false); 337 } 338 339 //----------------------------------------------------------------------- 340 //----------------------------------------------------------------------- 341 //----------------------------------------------------------------------- 342 @Test 343 public void test_appendText_1arg() throws Exception { 344 builder.appendText(MONTH_OF_YEAR); 345 DateTimeFormatter f = builder.toFormatter(); 346 assertEquals(f.toString(), "Text(MonthOfYear)"); 347 } 348 349 @Test(expectedExceptions=NullPointerException.class) 350 public void test_appendText_1arg_null() throws Exception { 351 builder.appendText(null); 352 } 353 354 //----------------------------------------------------------------------- 355 @Test 356 public void test_appendText_2arg() throws Exception { 357 builder.appendText(MONTH_OF_YEAR, TextStyle.SHORT); 358 DateTimeFormatter f = builder.toFormatter(); 359 assertEquals(f.toString(), "Text(MonthOfYear,SHORT)"); 360 } 361 362 @Test(expectedExceptions=NullPointerException.class) 363 public void test_appendText_2arg_nullRule() throws Exception { 364 builder.appendText(null, TextStyle.SHORT); 365 } 366 367 @Test(expectedExceptions=NullPointerException.class) 368 public void test_appendText_2arg_nullStyle() throws Exception { 369 builder.appendText(MONTH_OF_YEAR, (TextStyle) null); 370 } 371 372 //----------------------------------------------------------------------- 373 @Test 374 public void test_appendTextMap() throws Exception { 375 Map<Long, String> map = new HashMap<>(); 376 map.put(1L, "JNY"); 377 map.put(2L, "FBY"); 378 map.put(3L, "MCH"); 379 map.put(4L, "APL"); 380 map.put(5L, "MAY"); 381 map.put(6L, "JUN"); 382 map.put(7L, "JLY"); 383 map.put(8L, "AGT"); 384 map.put(9L, "SPT"); 385 map.put(10L, "OBR"); 386 map.put(11L, "NVR"); 387 map.put(12L, "DBR"); 388 builder.appendText(MONTH_OF_YEAR, map); 389 DateTimeFormatter f = builder.toFormatter(); 390 assertEquals(f.toString(), "Text(MonthOfYear)"); // TODO: toString should be different? 391 } 392 393 @Test(expectedExceptions=NullPointerException.class) 394 public void test_appendTextMap_nullRule() throws Exception { 395 builder.appendText(null, new HashMap<Long, String>()); 396 } 397 398 @Test(expectedExceptions=NullPointerException.class) 399 public void test_appendTextMap_nullStyle() throws Exception { 400 builder.appendText(MONTH_OF_YEAR, (Map<Long, String>) null); 401 } 402 403 //----------------------------------------------------------------------- 404 //----------------------------------------------------------------------- 405 //----------------------------------------------------------------------- 406 @Test 407 public void test_appendOffsetId() throws Exception { 408 builder.appendOffsetId(); 409 DateTimeFormatter f = builder.toFormatter(); 410 assertEquals(f.toString(), "Offset(+HH:MM:ss,'Z')"); 411 } 412 413 @DataProvider(name="offsetPatterns") 414 Object[][] data_offsetPatterns() { 415 return new Object[][] { 416 {"+HH", 2, 0, 0, "+02"}, 417 {"+HH", -2, 0, 0, "-02"}, 418 {"+HH", 2, 30, 0, "+02"}, 419 {"+HH", 2, 0, 45, "+02"}, 420 {"+HH", 2, 30, 45, "+02"}, 421 422 {"+HHMM", 2, 0, 0, "+0200"}, 423 {"+HHMM", -2, 0, 0, "-0200"}, 424 {"+HHMM", 2, 30, 0, "+0230"}, 425 {"+HHMM", 2, 0, 45, "+0200"}, 426 {"+HHMM", 2, 30, 45, "+0230"}, 427 428 {"+HH:MM", 2, 0, 0, "+02:00"}, 429 {"+HH:MM", -2, 0, 0, "-02:00"}, 430 {"+HH:MM", 2, 30, 0, "+02:30"}, 431 {"+HH:MM", 2, 0, 45, "+02:00"}, 432 {"+HH:MM", 2, 30, 45, "+02:30"}, 433 434 {"+HHMMss", 2, 0, 0, "+0200"}, 435 {"+HHMMss", -2, 0, 0, "-0200"}, 436 {"+HHMMss", 2, 30, 0, "+0230"}, 437 {"+HHMMss", 2, 0, 45, "+020045"}, 438 {"+HHMMss", 2, 30, 45, "+023045"}, 439 440 {"+HH:MM:ss", 2, 0, 0, "+02:00"}, 441 {"+HH:MM:ss", -2, 0, 0, "-02:00"}, 442 {"+HH:MM:ss", 2, 30, 0, "+02:30"}, 443 {"+HH:MM:ss", 2, 0, 45, "+02:00:45"}, 444 {"+HH:MM:ss", 2, 30, 45, "+02:30:45"}, 445 446 {"+HHMMSS", 2, 0, 0, "+020000"}, 447 {"+HHMMSS", -2, 0, 0, "-020000"}, 448 {"+HHMMSS", 2, 30, 0, "+023000"}, 449 {"+HHMMSS", 2, 0, 45, "+020045"}, 450 {"+HHMMSS", 2, 30, 45, "+023045"}, 451 452 {"+HH:MM:SS", 2, 0, 0, "+02:00:00"}, 453 {"+HH:MM:SS", -2, 0, 0, "-02:00:00"}, 454 {"+HH:MM:SS", 2, 30, 0, "+02:30:00"}, 455 {"+HH:MM:SS", 2, 0, 45, "+02:00:45"}, 456 {"+HH:MM:SS", 2, 30, 45, "+02:30:45"}, 457 }; 458 } 459 460 @Test(dataProvider="offsetPatterns") 461 public void test_appendOffset_format(String pattern, int h, int m, int s, String expected) throws Exception { 462 builder.appendOffset(pattern, "Z"); 463 DateTimeFormatter f = builder.toFormatter(); 464 ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); 465 assertEquals(f.format(offset), expected); 466 } 467 468 @Test(dataProvider="offsetPatterns") 469 public void test_appendOffset_parse(String pattern, int h, int m, int s, String expected) throws Exception { 470 builder.appendOffset(pattern, "Z"); 471 DateTimeFormatter f = builder.toFormatter(); 472 ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); 473 ZoneOffset parsed = f.parse(expected, ZoneOffset::from); 474 assertEquals(f.format(parsed), expected); 475 } 476 477 @DataProvider(name="badOffsetPatterns") 478 Object[][] data_badOffsetPatterns() { 479 return new Object[][] { 480 {"HH"}, 481 {"HHMM"}, 482 {"HH:MM"}, 483 {"HHMMss"}, 484 {"HH:MM:ss"}, 485 {"HHMMSS"}, 486 {"HH:MM:SS"}, 487 {"+HHM"}, 488 {"+A"}, 489 }; 490 } 491 492 @Test(dataProvider="badOffsetPatterns", expectedExceptions=IllegalArgumentException.class) 493 public void test_appendOffset_badPattern(String pattern) throws Exception { 494 builder.appendOffset(pattern, "Z"); 495 } 496 497 @Test(expectedExceptions=NullPointerException.class) 498 public void test_appendOffset_3arg_nullText() throws Exception { 499 builder.appendOffset("+HH:MM", null); 500 } 501 502 @Test(expectedExceptions=NullPointerException.class) 503 public void test_appendOffset_3arg_nullPattern() throws Exception { 504 builder.appendOffset(null, "Z"); 505 } 506 507 //----------------------------------------------------------------------- 508 //----------------------------------------------------------------------- 509 //----------------------------------------------------------------------- 510 @Test 511 public void test_appendZoneId() throws Exception { 512 builder.appendZoneId(); 513 DateTimeFormatter f = builder.toFormatter(); 514 assertEquals(f.toString(), "ZoneId()"); 515 } 516 517 @Test 518 public void test_appendZoneText_1arg() throws Exception { 519 builder.appendZoneText(TextStyle.FULL); 520 DateTimeFormatter f = builder.toFormatter(); 521 assertEquals(f.toString(), "ZoneText(FULL)"); 522 } 523 524 @Test(expectedExceptions=NullPointerException.class) 525 public void test_appendZoneText_1arg_nullText() throws Exception { 526 builder.appendZoneText(null); 527 } 528 529 //----------------------------------------------------------------------- 530 //----------------------------------------------------------------------- 531 //----------------------------------------------------------------------- 532 @Test 533 public void test_padNext_1arg() { 534 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2).appendValue(DAY_OF_MONTH); 535 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1"); 536 } 537 538 @Test(expectedExceptions=IllegalArgumentException.class) 539 public void test_padNext_1arg_invalidWidth() throws Exception { 540 builder.padNext(0); 541 } 542 543 //----------------------------------------------------------------------- 544 @Test 545 public void test_padNext_2arg_dash() throws Exception { 546 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2, '-').appendValue(DAY_OF_MONTH); 547 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2:-1"); 548 } 549 550 @Test(expectedExceptions=IllegalArgumentException.class) 551 public void test_padNext_2arg_invalidWidth() throws Exception { 552 builder.padNext(0, '-'); 553 } 554 555 //----------------------------------------------------------------------- 556 @Test 557 public void test_padOptional() throws Exception { 558 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':') 559 .padNext(5).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd() 560 .appendLiteral(':').appendValue(YEAR); 561 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1:2013"); 562 assertEquals(builder.toFormatter().format(YearMonth.of(2013, 2)), "2: :2013"); 563 } 564 565 //----------------------------------------------------------------------- 566 //----------------------------------------------------------------------- 567 //----------------------------------------------------------------------- 568 @Test 569 public void test_optionalStart_noEnd() throws Exception { 570 builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).appendValue(DAY_OF_WEEK); 571 DateTimeFormatter f = builder.toFormatter(); 572 assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)Value(DayOfWeek)]"); 573 } 574 575 @Test 576 public void test_optionalStart2_noEnd() throws Exception { 577 builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).optionalStart().appendValue(DAY_OF_WEEK); 578 DateTimeFormatter f = builder.toFormatter(); 579 assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)[Value(DayOfWeek)]]"); 580 } 581 582 @Test 583 public void test_optionalStart_doubleStart() throws Exception { 584 builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH); 585 DateTimeFormatter f = builder.toFormatter(); 586 assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); 587 } 588 589 //----------------------------------------------------------------------- 590 @Test 591 public void test_optionalEnd() throws Exception { 592 builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd().appendValue(DAY_OF_WEEK); 593 DateTimeFormatter f = builder.toFormatter(); 594 assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)]Value(DayOfWeek)"); 595 } 596 597 @Test 598 public void test_optionalEnd2() throws Exception { 599 builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH) 600 .optionalStart().appendValue(DAY_OF_WEEK).optionalEnd().appendValue(DAY_OF_MONTH).optionalEnd(); 601 DateTimeFormatter f = builder.toFormatter(); 602 assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)[Value(DayOfWeek)]Value(DayOfMonth)]"); 603 } 604 605 @Test 606 public void test_optionalEnd_doubleStartSingleEnd() throws Exception { 607 builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH).optionalEnd(); 608 DateTimeFormatter f = builder.toFormatter(); 609 assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); 610 } 611 612 @Test 613 public void test_optionalEnd_doubleStartDoubleEnd() throws Exception { 614 builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH).optionalEnd().optionalEnd(); 615 DateTimeFormatter f = builder.toFormatter(); 616 assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); 617 } 618 619 @Test 620 public void test_optionalStartEnd_immediateStartEnd() throws Exception { 621 builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalEnd().appendValue(DAY_OF_MONTH); 622 DateTimeFormatter f = builder.toFormatter(); 623 assertEquals(f.toString(), "Value(MonthOfYear)Value(DayOfMonth)"); 624 } 625 626 @Test(expectedExceptions=IllegalStateException.class) 627 public void test_optionalEnd_noStart() throws Exception { 628 builder.optionalEnd(); 629 } 630 631 //----------------------------------------------------------------------- 632 //----------------------------------------------------------------------- 633 //----------------------------------------------------------------------- 634 @DataProvider(name="validPatterns") 635 Object[][] dataValid() { 636 return new Object[][] { 637 {"'a'", "'a'"}, 638 {"''", "''"}, 639 {"'!'", "'!'"}, 640 {"!", "'!'"}, 641 642 {"'hello_people,][)('", "'hello_people,][)('"}, 643 {"'hi'", "'hi'"}, 644 {"'yyyy'", "'yyyy'"}, 645 {"''''", "''"}, 646 {"'o''clock'", "'o''clock'"}, 647 648 {"G", "Text(Era,SHORT)"}, 649 {"GG", "Text(Era,SHORT)"}, 650 {"GGG", "Text(Era,SHORT)"}, 651 {"GGGG", "Text(Era)"}, 652 {"GGGGG", "Text(Era,NARROW)"}, 653 654 {"u", "Value(Year)"}, 655 {"uu", "ReducedValue(Year,2,2,2000-01-01)"}, 656 {"uuu", "Value(Year,3,19,NORMAL)"}, 657 {"uuuu", "Value(Year,4,19,EXCEEDS_PAD)"}, 658 {"uuuuu", "Value(Year,5,19,EXCEEDS_PAD)"}, 659 660 {"y", "Value(YearOfEra)"}, 661 {"yy", "ReducedValue(YearOfEra,2,2,2000-01-01)"}, 662 {"yyy", "Value(YearOfEra,3,19,NORMAL)"}, 663 {"yyyy", "Value(YearOfEra,4,19,EXCEEDS_PAD)"}, 664 {"yyyyy", "Value(YearOfEra,5,19,EXCEEDS_PAD)"}, 665 666 {"Y", "Localized(WeekBasedYear)"}, 667 {"YY", "Localized(ReducedValue(WeekBasedYear,2,2,2000-01-01))"}, 668 {"YYY", "Localized(WeekBasedYear,3,19,NORMAL)"}, 669 {"YYYY", "Localized(WeekBasedYear,4,19,EXCEEDS_PAD)"}, 670 {"YYYYY", "Localized(WeekBasedYear,5,19,EXCEEDS_PAD)"}, 671 672 {"M", "Value(MonthOfYear)"}, 673 {"MM", "Value(MonthOfYear,2)"}, 674 {"MMM", "Text(MonthOfYear,SHORT)"}, 675 {"MMMM", "Text(MonthOfYear)"}, 676 {"MMMMM", "Text(MonthOfYear,NARROW)"}, 677 678 {"L", "Value(MonthOfYear)"}, 679 {"LL", "Value(MonthOfYear,2)"}, 680 {"LLL", "Text(MonthOfYear,SHORT_STANDALONE)"}, 681 {"LLLL", "Text(MonthOfYear,FULL_STANDALONE)"}, 682 {"LLLLL", "Text(MonthOfYear,NARROW_STANDALONE)"}, 683 684 {"D", "Value(DayOfYear)"}, 685 {"DD", "Value(DayOfYear,2,3,NOT_NEGATIVE)"}, 686 {"DDD", "Value(DayOfYear,3)"}, 687 688 {"d", "Value(DayOfMonth)"}, 689 {"dd", "Value(DayOfMonth,2)"}, 690 691 {"F", "Value(AlignedDayOfWeekInMonth)"}, 692 693 {"Q", "Value(QuarterOfYear)"}, 694 {"QQ", "Value(QuarterOfYear,2)"}, 695 {"QQQ", "Text(QuarterOfYear,SHORT)"}, 696 {"QQQQ", "Text(QuarterOfYear)"}, 697 {"QQQQQ", "Text(QuarterOfYear,NARROW)"}, 698 699 {"q", "Value(QuarterOfYear)"}, 700 {"qq", "Value(QuarterOfYear,2)"}, 701 {"qqq", "Text(QuarterOfYear,SHORT_STANDALONE)"}, 702 {"qqqq", "Text(QuarterOfYear,FULL_STANDALONE)"}, 703 {"qqqqq", "Text(QuarterOfYear,NARROW_STANDALONE)"}, 704 705 {"E", "Text(DayOfWeek,SHORT)"}, 706 {"EE", "Text(DayOfWeek,SHORT)"}, 707 {"EEE", "Text(DayOfWeek,SHORT)"}, 708 {"EEEE", "Text(DayOfWeek)"}, 709 {"EEEEE", "Text(DayOfWeek,NARROW)"}, 710 711 {"e", "Localized(DayOfWeek,1)"}, 712 {"ee", "Localized(DayOfWeek,2)"}, 713 {"eee", "Text(DayOfWeek,SHORT)"}, 714 {"eeee", "Text(DayOfWeek)"}, 715 {"eeeee", "Text(DayOfWeek,NARROW)"}, 716 717 {"c", "Localized(DayOfWeek,1)"}, 718 {"ccc", "Text(DayOfWeek,SHORT_STANDALONE)"}, 719 {"cccc", "Text(DayOfWeek,FULL_STANDALONE)"}, 720 {"ccccc", "Text(DayOfWeek,NARROW_STANDALONE)"}, 721 722 {"a", "Text(AmPmOfDay,SHORT)"}, 723 724 {"H", "Value(HourOfDay)"}, 725 {"HH", "Value(HourOfDay,2)"}, 726 727 {"K", "Value(HourOfAmPm)"}, 728 {"KK", "Value(HourOfAmPm,2)"}, 729 730 {"k", "Value(ClockHourOfDay)"}, 731 {"kk", "Value(ClockHourOfDay,2)"}, 732 733 {"h", "Value(ClockHourOfAmPm)"}, 734 {"hh", "Value(ClockHourOfAmPm,2)"}, 735 736 {"m", "Value(MinuteOfHour)"}, 737 {"mm", "Value(MinuteOfHour,2)"}, 738 739 {"s", "Value(SecondOfMinute)"}, 740 {"ss", "Value(SecondOfMinute,2)"}, 741 742 {"S", "Fraction(NanoOfSecond,1,1)"}, 743 {"SS", "Fraction(NanoOfSecond,2,2)"}, 744 {"SSS", "Fraction(NanoOfSecond,3,3)"}, 745 {"SSSSSSSSS", "Fraction(NanoOfSecond,9,9)"}, 746 747 {"A", "Value(MilliOfDay,1,19,NOT_NEGATIVE)"}, 748 {"AA", "Value(MilliOfDay,2,19,NOT_NEGATIVE)"}, 749 {"AAA", "Value(MilliOfDay,3,19,NOT_NEGATIVE)"}, 750 751 {"n", "Value(NanoOfSecond,1,19,NOT_NEGATIVE)"}, 752 {"nn", "Value(NanoOfSecond,2,19,NOT_NEGATIVE)"}, 753 {"nnn", "Value(NanoOfSecond,3,19,NOT_NEGATIVE)"}, 754 755 {"N", "Value(NanoOfDay,1,19,NOT_NEGATIVE)"}, 756 {"NN", "Value(NanoOfDay,2,19,NOT_NEGATIVE)"}, 757 {"NNN", "Value(NanoOfDay,3,19,NOT_NEGATIVE)"}, 758 759 {"z", "ZoneText(SHORT)"}, 760 {"zz", "ZoneText(SHORT)"}, 761 {"zzz", "ZoneText(SHORT)"}, 762 {"zzzz", "ZoneText(FULL)"}, 763 764 {"VV", "ZoneId()"}, 765 766 {"Z", "Offset(+HHMM,'+0000')"}, // SimpleDateFormat 767 {"ZZ", "Offset(+HHMM,'+0000')"}, // SimpleDateFormat 768 {"ZZZ", "Offset(+HHMM,'+0000')"}, // SimpleDateFormat 769 770 {"X", "Offset(+HHmm,'Z')"}, // LDML/almost SimpleDateFormat 771 {"XX", "Offset(+HHMM,'Z')"}, // LDML/SimpleDateFormat 772 {"XXX", "Offset(+HH:MM,'Z')"}, // LDML/SimpleDateFormat 773 {"XXXX", "Offset(+HHMMss,'Z')"}, // LDML 774 {"XXXXX", "Offset(+HH:MM:ss,'Z')"}, // LDML 775 776 {"x", "Offset(+HHmm,'+00')"}, // LDML 777 {"xx", "Offset(+HHMM,'+0000')"}, // LDML 778 {"xxx", "Offset(+HH:MM,'+00:00')"}, // LDML 779 {"xxxx", "Offset(+HHMMss,'+0000')"}, // LDML 780 {"xxxxx", "Offset(+HH:MM:ss,'+00:00')"}, // LDML 781 782 {"ppH", "Pad(Value(HourOfDay),2)"}, 783 {"pppDD", "Pad(Value(DayOfYear,2,3,NOT_NEGATIVE),3)"}, 784 785 {"yyyy[-MM[-dd", "Value(YearOfEra,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"}, 786 {"yyyy[-MM[-dd]]", "Value(YearOfEra,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"}, 787 {"yyyy[-MM[]-dd]", "Value(YearOfEra,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)]"}, 788 789 {"yyyy-MM-dd'T'HH:mm:ss.SSS", "Value(YearOfEra,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)" + 790 "'T'Value(HourOfDay,2)':'Value(MinuteOfHour,2)':'Value(SecondOfMinute,2)'.'Fraction(NanoOfSecond,3,3)"}, 791 792 {"w", "Localized(WeekOfWeekBasedYear,1)"}, 793 {"ww", "Localized(WeekOfWeekBasedYear,2)"}, 794 {"W", "Localized(WeekOfMonth,1)"}, 795 }; 796 } 797 798 @Test(dataProvider="validPatterns") 799 public void test_appendPattern_valid(String input, String expected) throws Exception { 800 builder.appendPattern(input); 801 DateTimeFormatter f = builder.toFormatter(); 802 assertEquals(f.toString(), expected); 803 } 804 805 //----------------------------------------------------------------------- 806 @DataProvider(name="invalidPatterns") 807 Object[][] dataInvalid() { 808 return new Object[][] { 809 {"'"}, 810 {"'hello"}, 811 {"'hel''lo"}, 812 {"'hello''"}, 813 {"{"}, 814 {"}"}, 815 {"{}"}, 816 {"]"}, 817 {"yyyy]"}, 818 {"yyyy]MM"}, 819 {"yyyy[MM]]"}, 820 821 {"aa"}, 822 {"aaa"}, 823 {"aaaa"}, 824 {"aaaaa"}, 825 {"aaaaaa"}, 826 {"MMMMMM"}, 827 {"LLLLLL"}, 828 {"QQQQQQ"}, 829 {"qqqqqq"}, 830 {"EEEEEE"}, 831 {"eeeeee"}, 832 {"cc"}, 833 {"cccccc"}, 834 {"ddd"}, 835 {"DDDD"}, 836 {"FF"}, 837 {"FFF"}, 838 {"hhh"}, 839 {"HHH"}, 840 {"kkk"}, 841 {"KKK"}, 842 {"mmm"}, 843 {"sss"}, 844 {"OO"}, 845 {"OOO"}, 846 {"OOOOO"}, 847 {"XXXXXX"}, 848 {"ZZZZZZ"}, 849 {"zzzzz"}, 850 {"V"}, 851 {"VVV"}, 852 {"VVVV"}, 853 {"VVVVV"}, 854 855 {"RO"}, 856 857 {"p"}, 858 {"pp"}, 859 {"p:"}, 860 861 {"f"}, 862 {"ff"}, 863 {"f:"}, 864 {"fy"}, 865 {"fa"}, 866 {"fM"}, 867 868 {"www"}, 869 {"WW"}, 870 }; 871 } 872 873 @Test(dataProvider="invalidPatterns", expectedExceptions=IllegalArgumentException.class) 874 public void test_appendPattern_invalid(String input) throws Exception { 875 try { 876 builder.appendPattern(input); 877 } catch (IllegalArgumentException ex) { 878 throw ex; 879 } 880 } 881 882 //----------------------------------------------------------------------- 883 @DataProvider(name="patternPrint") 884 Object[][] data_patternPrint() { 885 return new Object[][] { 886 {"Q", date(2012, 2, 10), "1"}, 887 {"QQ", date(2012, 2, 10), "01"}, 888 {"QQQ", date(2012, 2, 10), "Q1"}, 889 {"QQQQ", date(2012, 2, 10), "1st quarter"}, 890 {"QQQQQ", date(2012, 2, 10), "1"}, 891 }; 892 } 893 894 @Test(dataProvider="patternPrint") 895 public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { 896 DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); 897 String test = f.format(temporal); 898 assertEquals(test, expected); 899 } 900 901 //----------------------------------------------------------------------- 902 @DataProvider(name="localePatterns") 903 Object[][] localizedDateTimePatterns() { 904 return new Object[][] { 905 {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, y 'at' h:mm:ss a zzzz"}, 906 {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "MMMM d, y 'at' h:mm:ss a z"}, 907 {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "MMM d, y, h:mm:ss a"}, 908 {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "M/d/yy, h:mm a"}, 909 {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.US, "EEEE, MMMM d, y"}, 910 {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.US, "MMMM d, y"}, 911 {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.US, "MMM d, y"}, 912 {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.US, "M/d/yy"}, 913 {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a zzzz"}, 914 {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"}, 915 {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a"}, 916 {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "h:mm a"}, 917 918 // French Locale and ISO Chronology 919 {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y '\u00e0' HH:mm:ss zzzz"}, 920 {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y '\u00e0' HH:mm:ss z"}, 921 {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y '\u00e0' HH:mm:ss"}, 922 {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"}, 923 {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"}, 924 {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"}, 925 {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"}, 926 {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"}, 927 {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"}, 928 {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"}, 929 {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"}, 930 {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"}, 931 932 // Japanese Locale and JapaneseChronology 933 {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"}, 934 {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"}, 935 {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"}, 936 {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"}, 937 {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, 938 {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, 939 {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"}, 940 {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"}, 941 {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"}, 942 {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"}, 943 {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"}, 944 {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"}, 945 946 // Chinese Local and Chronology 947 {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"}, 948 {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"}, 949 {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"}, 950 {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"}, 951 {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"}, 952 {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, 953 {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"}, 954 {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"}, 955 {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"}, 956 {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"}, 957 {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"}, 958 {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"}, 959 }; 960 } 961 962 @Test(dataProvider="localePatterns") 963 public void test_getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle, 964 Chronology chrono, Locale locale, String expected) { 965 String actual = DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale); 966 assertEquals(actual, expected, "Pattern " + convertNonAscii(actual)); 967 } 968 969 @Test(expectedExceptions=java.lang.IllegalArgumentException.class) 970 public void test_getLocalizedDateTimePatternIAE() { 971 DateTimeFormatterBuilder.getLocalizedDateTimePattern(null, null, IsoChronology.INSTANCE, Locale.US); 972 } 973 974 @Test(expectedExceptions=java.lang.NullPointerException.class) 975 public void test_getLocalizedChronoNPE() { 976 DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT, FormatStyle.SHORT, null, Locale.US); 977 } 978 979 @Test(expectedExceptions=java.lang.NullPointerException.class) 980 public void test_getLocalizedLocaleNPE() { 981 DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, null); 982 } 983 984 /** 985 * Returns a string that includes non-ascii characters after expanding 986 * the non-ascii characters to their Java language \\uxxxx form. 987 * @param input an input string 988 * @return the encoded string. 989 */ 990 private String convertNonAscii(String input) { 991 StringBuilder sb = new StringBuilder(input.length() * 6); 992 for (int i = 0; i < input.length(); i++) { 993 char ch = input.charAt(i); 994 if (ch < 255) { 995 sb.append(ch); 996 } else { 997 sb.append("\\u"); 998 sb.append(Integer.toHexString(ch)); 999 } 1000 } 1001 return sb.toString(); 1002 } 1003 1004 private static Temporal date(int y, int m, int d) { 1005 return LocalDate.of(y, m, d); 1006 } 1007 1008 }