1 /* 2 * Copyright (c) 2012, 2019, 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.format.DateTimeFormatter.BASIC_ISO_DATE; 63 import static java.time.temporal.ChronoField.DAY_OF_MONTH; 64 import static java.time.temporal.ChronoField.HOUR_OF_DAY; 65 import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; 66 import static java.time.temporal.ChronoField.MONTH_OF_YEAR; 67 import static java.time.temporal.ChronoField.NANO_OF_SECOND; 68 import static java.time.temporal.ChronoField.OFFSET_SECONDS; 69 import static java.time.temporal.ChronoField.YEAR; 70 import static org.testng.Assert.assertEquals; 71 72 import java.text.ParsePosition; 73 import java.time.LocalDate; 74 import java.time.LocalDateTime; 75 import java.time.LocalTime; 76 import java.time.Month; 77 import java.time.YearMonth; 78 import java.time.ZonedDateTime; 79 import java.time.ZoneId; 80 import java.time.ZoneOffset; 81 import java.time.format.DateTimeFormatter; 82 import java.time.format.DateTimeFormatterBuilder; 83 import java.time.format.DateTimeParseException; 84 import java.time.format.SignStyle; 85 import java.time.format.TextStyle; 86 import java.time.temporal.Temporal; 87 import java.time.temporal.TemporalAccessor; 88 import java.util.HashMap; 89 import java.util.Locale; 90 import java.util.Map; 91 92 import org.testng.annotations.BeforeMethod; 93 import org.testng.annotations.DataProvider; 94 import org.testng.annotations.Test; 95 96 /** 97 * Test DateTimeFormatterBuilder. 98 */ 99 @Test 100 public class TCKDateTimeFormatterBuilder { 101 102 private DateTimeFormatterBuilder builder; 103 104 @BeforeMethod setUp()105 public void setUp() { 106 builder = new DateTimeFormatterBuilder(); 107 } 108 109 //----------------------------------------------------------------------- 110 @Test test_toFormatter_empty()111 public void test_toFormatter_empty() throws Exception { 112 DateTimeFormatter f = builder.toFormatter(); 113 assertEquals(f.format(LocalDate.of(2012, 6, 30)), ""); 114 } 115 116 //----------------------------------------------------------------------- 117 @Test test_parseDefaulting_entireDate()118 public void test_parseDefaulting_entireDate() { 119 DateTimeFormatter f = builder 120 .parseDefaulting(YEAR, 2012).parseDefaulting(MONTH_OF_YEAR, 6) 121 .parseDefaulting(DAY_OF_MONTH, 30).toFormatter(); 122 LocalDate parsed = f.parse("", LocalDate::from); // blank string can be parsed 123 assertEquals(parsed, LocalDate.of(2012, 6, 30)); 124 } 125 126 @Test test_parseDefaulting_yearOptionalMonthOptionalDay()127 public void test_parseDefaulting_yearOptionalMonthOptionalDay() { 128 DateTimeFormatter f = builder 129 .appendValue(YEAR) 130 .optionalStart().appendLiteral('-').appendValue(MONTH_OF_YEAR) 131 .optionalStart().appendLiteral('-').appendValue(DAY_OF_MONTH) 132 .optionalEnd().optionalEnd() 133 .parseDefaulting(MONTH_OF_YEAR, 1) 134 .parseDefaulting(DAY_OF_MONTH, 1).toFormatter(); 135 assertEquals(f.parse("2012", LocalDate::from), LocalDate.of(2012, 1, 1)); 136 assertEquals(f.parse("2012-6", LocalDate::from), LocalDate.of(2012, 6, 1)); 137 assertEquals(f.parse("2012-6-30", LocalDate::from), LocalDate.of(2012, 6, 30)); 138 } 139 140 @Test(expectedExceptions = NullPointerException.class) test_parseDefaulting_null()141 public void test_parseDefaulting_null() { 142 builder.parseDefaulting(null, 1); 143 } 144 145 //----------------------------------------------------------------------- 146 @Test(expectedExceptions=NullPointerException.class) test_appendValue_1arg_null()147 public void test_appendValue_1arg_null() throws Exception { 148 builder.appendValue(null); 149 } 150 151 //----------------------------------------------------------------------- 152 @Test(expectedExceptions=NullPointerException.class) test_appendValue_2arg_null()153 public void test_appendValue_2arg_null() throws Exception { 154 builder.appendValue(null, 3); 155 } 156 157 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_2arg_widthTooSmall()158 public void test_appendValue_2arg_widthTooSmall() throws Exception { 159 builder.appendValue(DAY_OF_MONTH, 0); 160 } 161 162 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_2arg_widthTooBig()163 public void test_appendValue_2arg_widthTooBig() throws Exception { 164 builder.appendValue(DAY_OF_MONTH, 20); 165 } 166 167 //----------------------------------------------------------------------- 168 @Test(expectedExceptions=NullPointerException.class) test_appendValue_3arg_nullField()169 public void test_appendValue_3arg_nullField() throws Exception { 170 builder.appendValue(null, 2, 3, SignStyle.NORMAL); 171 } 172 173 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_minWidthTooSmall()174 public void test_appendValue_3arg_minWidthTooSmall() throws Exception { 175 builder.appendValue(DAY_OF_MONTH, 0, 2, SignStyle.NORMAL); 176 } 177 178 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_minWidthTooBig()179 public void test_appendValue_3arg_minWidthTooBig() throws Exception { 180 builder.appendValue(DAY_OF_MONTH, 20, 2, SignStyle.NORMAL); 181 } 182 183 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_maxWidthTooSmall()184 public void test_appendValue_3arg_maxWidthTooSmall() throws Exception { 185 builder.appendValue(DAY_OF_MONTH, 2, 0, SignStyle.NORMAL); 186 } 187 188 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_maxWidthTooBig()189 public void test_appendValue_3arg_maxWidthTooBig() throws Exception { 190 builder.appendValue(DAY_OF_MONTH, 2, 20, SignStyle.NORMAL); 191 } 192 193 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValue_3arg_maxWidthMinWidth()194 public void test_appendValue_3arg_maxWidthMinWidth() throws Exception { 195 builder.appendValue(DAY_OF_MONTH, 4, 2, SignStyle.NORMAL); 196 } 197 198 @Test(expectedExceptions=NullPointerException.class) test_appendValue_3arg_nullSignStyle()199 public void test_appendValue_3arg_nullSignStyle() throws Exception { 200 builder.appendValue(DAY_OF_MONTH, 2, 3, null); 201 } 202 203 //----------------------------------------------------------------------- 204 @Test(expectedExceptions=NullPointerException.class) test_appendValueReduced_int_nullField()205 public void test_appendValueReduced_int_nullField() throws Exception { 206 builder.appendValueReduced(null, 2, 2, 2000); 207 } 208 209 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_minWidthTooSmall()210 public void test_appendValueReduced_int_minWidthTooSmall() throws Exception { 211 builder.appendValueReduced(YEAR, 0, 2, 2000); 212 } 213 214 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_minWidthTooBig()215 public void test_appendValueReduced_int_minWidthTooBig() throws Exception { 216 builder.appendValueReduced(YEAR, 11, 2, 2000); 217 } 218 219 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_maxWidthTooSmall()220 public void test_appendValueReduced_int_maxWidthTooSmall() throws Exception { 221 builder.appendValueReduced(YEAR, 2, 0, 2000); 222 } 223 224 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_maxWidthTooBig()225 public void test_appendValueReduced_int_maxWidthTooBig() throws Exception { 226 builder.appendValueReduced(YEAR, 2, 11, 2000); 227 } 228 229 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_int_maxWidthLessThanMin()230 public void test_appendValueReduced_int_maxWidthLessThanMin() throws Exception { 231 builder.appendValueReduced(YEAR, 2, 1, 2000); 232 } 233 234 //----------------------------------------------------------------------- 235 @Test(expectedExceptions=NullPointerException.class) test_appendValueReduced_date_nullField()236 public void test_appendValueReduced_date_nullField() throws Exception { 237 builder.appendValueReduced(null, 2, 2, LocalDate.of(2000, 1, 1)); 238 } 239 240 @Test(expectedExceptions=NullPointerException.class) test_appendValueReduced_date_nullDate()241 public void test_appendValueReduced_date_nullDate() throws Exception { 242 builder.appendValueReduced(YEAR, 2, 2, null); 243 } 244 245 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_minWidthTooSmall()246 public void test_appendValueReduced_date_minWidthTooSmall() throws Exception { 247 builder.appendValueReduced(YEAR, 0, 2, LocalDate.of(2000, 1, 1)); 248 } 249 250 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_minWidthTooBig()251 public void test_appendValueReduced_date_minWidthTooBig() throws Exception { 252 builder.appendValueReduced(YEAR, 11, 2, LocalDate.of(2000, 1, 1)); 253 } 254 255 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_maxWidthTooSmall()256 public void test_appendValueReduced_date_maxWidthTooSmall() throws Exception { 257 builder.appendValueReduced(YEAR, 2, 0, LocalDate.of(2000, 1, 1)); 258 } 259 260 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_maxWidthTooBig()261 public void test_appendValueReduced_date_maxWidthTooBig() throws Exception { 262 builder.appendValueReduced(YEAR, 2, 11, LocalDate.of(2000, 1, 1)); 263 } 264 265 @Test(expectedExceptions=IllegalArgumentException.class) test_appendValueReduced_date_maxWidthLessThanMin()266 public void test_appendValueReduced_date_maxWidthLessThanMin() throws Exception { 267 builder.appendValueReduced(YEAR, 2, 1, LocalDate.of(2000, 1, 1)); 268 } 269 270 //----------------------------------------------------------------------- 271 //----------------------------------------------------------------------- 272 //----------------------------------------------------------------------- 273 @Test(expectedExceptions=NullPointerException.class) test_appendFraction_4arg_nullRule()274 public void test_appendFraction_4arg_nullRule() throws Exception { 275 builder.appendFraction(null, 1, 9, false); 276 } 277 278 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_invalidRuleNotFixedSet()279 public void test_appendFraction_4arg_invalidRuleNotFixedSet() throws Exception { 280 builder.appendFraction(DAY_OF_MONTH, 1, 9, false); 281 } 282 283 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_minTooSmall()284 public void test_appendFraction_4arg_minTooSmall() throws Exception { 285 builder.appendFraction(MINUTE_OF_HOUR, -1, 9, false); 286 } 287 288 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_minTooBig()289 public void test_appendFraction_4arg_minTooBig() throws Exception { 290 builder.appendFraction(MINUTE_OF_HOUR, 10, 9, false); 291 } 292 293 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_maxTooSmall()294 public void test_appendFraction_4arg_maxTooSmall() throws Exception { 295 builder.appendFraction(MINUTE_OF_HOUR, 0, -1, false); 296 } 297 298 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_maxTooBig()299 public void test_appendFraction_4arg_maxTooBig() throws Exception { 300 builder.appendFraction(MINUTE_OF_HOUR, 1, 10, false); 301 } 302 303 @Test(expectedExceptions=IllegalArgumentException.class) test_appendFraction_4arg_maxWidthMinWidth()304 public void test_appendFraction_4arg_maxWidthMinWidth() throws Exception { 305 builder.appendFraction(MINUTE_OF_HOUR, 9, 3, false); 306 } 307 308 //----------------------------------------------------------------------- 309 //----------------------------------------------------------------------- 310 //----------------------------------------------------------------------- 311 @Test(expectedExceptions=NullPointerException.class) test_appendText_1arg_null()312 public void test_appendText_1arg_null() throws Exception { 313 builder.appendText(null); 314 } 315 316 //----------------------------------------------------------------------- 317 @Test(expectedExceptions=NullPointerException.class) test_appendText_2arg_nullRule()318 public void test_appendText_2arg_nullRule() throws Exception { 319 builder.appendText(null, TextStyle.SHORT); 320 } 321 322 @Test(expectedExceptions=NullPointerException.class) test_appendText_2arg_nullStyle()323 public void test_appendText_2arg_nullStyle() throws Exception { 324 builder.appendText(MONTH_OF_YEAR, (TextStyle) null); 325 } 326 327 //----------------------------------------------------------------------- 328 @Test(expectedExceptions=NullPointerException.class) test_appendTextMap_nullRule()329 public void test_appendTextMap_nullRule() throws Exception { 330 builder.appendText(null, new HashMap<>()); 331 } 332 333 @Test(expectedExceptions=NullPointerException.class) test_appendTextMap_nullStyle()334 public void test_appendTextMap_nullStyle() throws Exception { 335 builder.appendText(MONTH_OF_YEAR, (Map<Long, String>) null); 336 } 337 338 //----------------------------------------------------------------------- 339 //----------------------------------------------------------------------- 340 //----------------------------------------------------------------------- 341 @DataProvider(name="offsetPatterns") data_offsetPatterns()342 Object[][] data_offsetPatterns() { 343 return new Object[][] { 344 {"+HH", 2, 0, 0, "+02"}, 345 {"+HH", -2, 0, 0, "-02"}, 346 {"+HH", 2, 30, 0, "+02"}, 347 {"+HH", 2, 0, 45, "+02"}, 348 {"+HH", 2, 30, 45, "+02"}, 349 350 {"+HHmm", 2, 0, 0, "+02"}, 351 {"+HHmm", -2, 0, 0, "-02"}, 352 {"+HHmm", 2, 30, 0, "+0230"}, 353 {"+HHmm", 2, 0, 45, "+02"}, 354 {"+HHmm", 2, 30, 45, "+0230"}, 355 356 {"+HH:mm", 2, 0, 0, "+02"}, 357 {"+HH:mm", -2, 0, 0, "-02"}, 358 {"+HH:mm", 2, 30, 0, "+02:30"}, 359 {"+HH:mm", 2, 0, 45, "+02"}, 360 {"+HH:mm", 2, 30, 45, "+02:30"}, 361 362 {"+HHMM", 2, 0, 0, "+0200"}, 363 {"+HHMM", -2, 0, 0, "-0200"}, 364 {"+HHMM", 2, 30, 0, "+0230"}, 365 {"+HHMM", 2, 0, 45, "+0200"}, 366 {"+HHMM", 2, 30, 45, "+0230"}, 367 368 {"+HH:MM", 2, 0, 0, "+02:00"}, 369 {"+HH:MM", -2, 0, 0, "-02:00"}, 370 {"+HH:MM", 2, 30, 0, "+02:30"}, 371 {"+HH:MM", 2, 0, 45, "+02:00"}, 372 {"+HH:MM", 2, 30, 45, "+02:30"}, 373 374 {"+HHMMss", 2, 0, 0, "+0200"}, 375 {"+HHMMss", -2, 0, 0, "-0200"}, 376 {"+HHMMss", 2, 30, 0, "+0230"}, 377 {"+HHMMss", 2, 0, 45, "+020045"}, 378 {"+HHMMss", 2, 30, 45, "+023045"}, 379 380 {"+HH:MM:ss", 2, 0, 0, "+02:00"}, 381 {"+HH:MM:ss", -2, 0, 0, "-02:00"}, 382 {"+HH:MM:ss", 2, 30, 0, "+02:30"}, 383 {"+HH:MM:ss", 2, 0, 45, "+02:00:45"}, 384 {"+HH:MM:ss", 2, 30, 45, "+02:30:45"}, 385 386 {"+HHMMSS", 2, 0, 0, "+020000"}, 387 {"+HHMMSS", -2, 0, 0, "-020000"}, 388 {"+HHMMSS", 2, 30, 0, "+023000"}, 389 {"+HHMMSS", 2, 0, 45, "+020045"}, 390 {"+HHMMSS", 2, 30, 45, "+023045"}, 391 392 {"+HH:MM:SS", 2, 0, 0, "+02:00:00"}, 393 {"+HH:MM:SS", -2, 0, 0, "-02:00:00"}, 394 {"+HH:MM:SS", 2, 30, 0, "+02:30:00"}, 395 {"+HH:MM:SS", 2, 0, 45, "+02:00:45"}, 396 {"+HH:MM:SS", 2, 30, 45, "+02:30:45"}, 397 398 {"+HHmmss", 2, 0, 0, "+02"}, 399 {"+HHmmss", -2, 0, 0, "-02"}, 400 {"+HHmmss", 2, 30, 0, "+0230"}, 401 {"+HHmmss", 2, 0, 45, "+020045"}, 402 {"+HHmmss", 2, 30, 45, "+023045"}, 403 404 {"+HH:mm:ss", 2, 0, 0, "+02"}, 405 {"+HH:mm:ss", -2, 0, 0, "-02"}, 406 {"+HH:mm:ss", 2, 30, 0, "+02:30"}, 407 {"+HH:mm:ss", 2, 0, 45, "+02:00:45"}, 408 {"+HH:mm:ss", 2, 30, 45, "+02:30:45"}, 409 410 {"+H", 2, 0, 0, "+2"}, 411 {"+H", -2, 0, 0, "-2"}, 412 {"+H", 2, 30, 0, "+2"}, 413 {"+H", 2, 0, 45, "+2"}, 414 {"+H", 2, 30, 45, "+2"}, 415 {"+H", 12, 0, 0, "+12"}, 416 {"+H", -12, 0, 0, "-12"}, 417 {"+H", 12, 30, 0, "+12"}, 418 {"+H", 12, 0, 45, "+12"}, 419 {"+H", 12, 30, 45, "+12"}, 420 421 {"+Hmm", 2, 0, 0, "+2"}, 422 {"+Hmm", -2, 0, 0, "-2"}, 423 {"+Hmm", 2, 30, 0, "+230"}, 424 {"+Hmm", 2, 0, 45, "+2"}, 425 {"+Hmm", 2, 30, 45, "+230"}, 426 {"+Hmm", 12, 0, 0, "+12"}, 427 {"+Hmm", -12, 0, 0, "-12"}, 428 {"+Hmm", 12, 30, 0, "+1230"}, 429 {"+Hmm", 12, 0, 45, "+12"}, 430 {"+Hmm", 12, 30, 45, "+1230"}, 431 432 {"+H:mm", 2, 0, 0, "+2"}, 433 {"+H:mm", -2, 0, 0, "-2"}, 434 {"+H:mm", 2, 30, 0, "+2:30"}, 435 {"+H:mm", 2, 0, 45, "+2"}, 436 {"+H:mm", 2, 30, 45, "+2:30"}, 437 {"+H:mm", 12, 0, 0, "+12"}, 438 {"+H:mm", -12, 0, 0, "-12"}, 439 {"+H:mm", 12, 30, 0, "+12:30"}, 440 {"+H:mm", 12, 0, 45, "+12"}, 441 {"+H:mm", 12, 30, 45, "+12:30"}, 442 443 {"+HMM", 2, 0, 0, "+200"}, 444 {"+HMM", -2, 0, 0, "-200"}, 445 {"+HMM", 2, 30, 0, "+230"}, 446 {"+HMM", 2, 0, 45, "+200"}, 447 {"+HMM", 2, 30, 45, "+230"}, 448 {"+HMM", 12, 0, 0, "+1200"}, 449 {"+HMM", -12, 0, 0, "-1200"}, 450 {"+HMM", 12, 30, 0, "+1230"}, 451 {"+HMM", 12, 0, 45, "+1200"}, 452 {"+HMM", 12, 30, 45, "+1230"}, 453 454 {"+H:MM", 2, 0, 0, "+2:00"}, 455 {"+H:MM", -2, 0, 0, "-2:00"}, 456 {"+H:MM", 2, 30, 0, "+2:30"}, 457 {"+H:MM", 2, 0, 45, "+2:00"}, 458 {"+H:MM", 2, 30, 45, "+2:30"}, 459 {"+H:MM", 12, 0, 0, "+12:00"}, 460 {"+H:MM", -12, 0, 0, "-12:00"}, 461 {"+H:MM", 12, 30, 0, "+12:30"}, 462 {"+H:MM", 12, 0, 45, "+12:00"}, 463 {"+H:MM", 12, 30, 45, "+12:30"}, 464 465 {"+HMMss", 2, 0, 0, "+200"}, 466 {"+HMMss", -2, 0, 0, "-200"}, 467 {"+HMMss", 2, 30, 0, "+230"}, 468 {"+HMMss", 2, 0, 45, "+20045"}, 469 {"+HMMss", 2, 30, 45, "+23045"}, 470 {"+HMMss", 12, 0, 0, "+1200"}, 471 {"+HMMss", -12, 0, 0, "-1200"}, 472 {"+HMMss", 12, 30, 0, "+1230"}, 473 {"+HMMss", 12, 0, 45, "+120045"}, 474 {"+HMMss", 12, 30, 45, "+123045"}, 475 476 {"+H:MM:ss", 2, 0, 0, "+2:00"}, 477 {"+H:MM:ss", -2, 0, 0, "-2:00"}, 478 {"+H:MM:ss", 2, 30, 0, "+2:30"}, 479 {"+H:MM:ss", 2, 0, 45, "+2:00:45"}, 480 {"+H:MM:ss", 2, 30, 45, "+2:30:45"}, 481 {"+H:MM:ss", 12, 0, 0, "+12:00"}, 482 {"+H:MM:ss", -12, 0, 0, "-12:00"}, 483 {"+H:MM:ss", 12, 30, 0, "+12:30"}, 484 {"+H:MM:ss", 12, 0, 45, "+12:00:45"}, 485 {"+H:MM:ss", 12, 30, 45, "+12:30:45"}, 486 487 {"+HMMSS", 2, 0, 0, "+20000"}, 488 {"+HMMSS", -2, 0, 0, "-20000"}, 489 {"+HMMSS", 2, 30, 0, "+23000"}, 490 {"+HMMSS", 2, 0, 45, "+20045"}, 491 {"+HMMSS", 2, 30, 45, "+23045"}, 492 {"+HMMSS", 12, 0, 0, "+120000"}, 493 {"+HMMSS", -12, 0, 0, "-120000"}, 494 {"+HMMSS", 12, 30, 0, "+123000"}, 495 {"+HMMSS", 12, 0, 45, "+120045"}, 496 {"+HMMSS", 12, 30, 45, "+123045"}, 497 498 {"+H:MM:SS", 2, 0, 0, "+2:00:00"}, 499 {"+H:MM:SS", -2, 0, 0, "-2:00:00"}, 500 {"+H:MM:SS", 2, 30, 0, "+2:30:00"}, 501 {"+H:MM:SS", 2, 0, 45, "+2:00:45"}, 502 {"+H:MM:SS", 2, 30, 45, "+2:30:45"}, 503 {"+H:MM:SS", 12, 0, 0, "+12:00:00"}, 504 {"+H:MM:SS", -12, 0, 0, "-12:00:00"}, 505 {"+H:MM:SS", 12, 30, 0, "+12:30:00"}, 506 {"+H:MM:SS", 12, 0, 45, "+12:00:45"}, 507 {"+H:MM:SS", 12, 30, 45, "+12:30:45"}, 508 509 {"+Hmmss", 2, 0, 0, "+2"}, 510 {"+Hmmss", -2, 0, 0, "-2"}, 511 {"+Hmmss", 2, 30, 0, "+230"}, 512 {"+Hmmss", 2, 0, 45, "+20045"}, 513 {"+Hmmss", 2, 30, 45, "+23045"}, 514 {"+Hmmss", 12, 0, 0, "+12"}, 515 {"+Hmmss", -12, 0, 0, "-12"}, 516 {"+Hmmss", 12, 30, 0, "+1230"}, 517 {"+Hmmss", 12, 0, 45, "+120045"}, 518 {"+Hmmss", 12, 30, 45, "+123045"}, 519 520 {"+H:mm:ss", 2, 0, 0, "+2"}, 521 {"+H:mm:ss", -2, 0, 0, "-2"}, 522 {"+H:mm:ss", 2, 30, 0, "+2:30"}, 523 {"+H:mm:ss", 2, 0, 45, "+2:00:45"}, 524 {"+H:mm:ss", 2, 30, 45, "+2:30:45"}, 525 {"+H:mm:ss", 12, 0, 0, "+12"}, 526 {"+H:mm:ss", -12, 0, 0, "-12"}, 527 {"+H:mm:ss", 12, 30, 0, "+12:30"}, 528 {"+H:mm:ss", 12, 0, 45, "+12:00:45"}, 529 {"+H:mm:ss", 12, 30, 45, "+12:30:45"}, 530 531 532 }; 533 } 534 535 @Test(dataProvider="offsetPatterns") test_appendOffset_format(String pattern, int h, int m, int s, String expected)536 public void test_appendOffset_format(String pattern, int h, int m, int s, String expected) throws Exception { 537 builder.appendOffset(pattern, "Z"); 538 DateTimeFormatter f = builder.toFormatter(); 539 ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); 540 assertEquals(f.format(offset), expected); 541 } 542 543 @Test(dataProvider="offsetPatterns") test_appendOffset_parse(String pattern, int h, int m, int s, String expected)544 public void test_appendOffset_parse(String pattern, int h, int m, int s, String expected) throws Exception { 545 builder.appendOffset(pattern, "Z"); 546 DateTimeFormatter f = builder.toFormatter(); 547 ZoneOffset parsed = f.parse(expected, ZoneOffset::from); 548 assertEquals(f.format(parsed), expected); 549 } 550 551 @DataProvider(name="badOffsetPatterns") data_badOffsetPatterns()552 Object[][] data_badOffsetPatterns() { 553 return new Object[][] { 554 {"HH"}, 555 {"HHMM"}, 556 {"HH:MM"}, 557 {"HHMMss"}, 558 {"HH:MM:ss"}, 559 {"HHMMSS"}, 560 {"HH:MM:SS"}, 561 {"+HHM"}, 562 {"+A"}, 563 }; 564 } 565 566 @Test(dataProvider="badOffsetPatterns", expectedExceptions=IllegalArgumentException.class) test_appendOffset_badPattern(String pattern)567 public void test_appendOffset_badPattern(String pattern) throws Exception { 568 builder.appendOffset(pattern, "Z"); 569 } 570 571 @Test(expectedExceptions=NullPointerException.class) test_appendOffset_3arg_nullText()572 public void test_appendOffset_3arg_nullText() throws Exception { 573 builder.appendOffset("+HH:MM", null); 574 } 575 576 @Test(expectedExceptions=NullPointerException.class) test_appendOffset_3arg_nullPattern()577 public void test_appendOffset_3arg_nullPattern() throws Exception { 578 builder.appendOffset(null, "Z"); 579 } 580 581 //----------------------------------------------------------------------- 582 //----------------------------------------------------------------------- 583 //----------------------------------------------------------------------- 584 @DataProvider(name = "formatGenericTimeZonePatterns") data_formatGenericNonLocationPatterns()585 Object[][] data_formatGenericNonLocationPatterns() { 586 return new Object[][] { 587 {"v", "America/Los_Angeles", "PT"}, 588 {"vvvv", "America/Los_Angeles", "Pacific Time"}, 589 {"v", "America/New_York", "ET"}, 590 {"vvvv", "America/New_York", "Eastern Time"}, 591 }; 592 } 593 594 @Test(dataProvider = "formatGenericTimeZonePatterns") test_appendZoneText_formatGenericTimeZonePatterns(String pattern, String input, String expected)595 public void test_appendZoneText_formatGenericTimeZonePatterns(String pattern, String input, String expected) { 596 ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of(input)); 597 DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern, Locale.US); 598 assertEquals(zdt.format(df), expected); 599 } 600 601 @DataProvider(name = "parseGenericTimeZonePatterns") data_parseGenericTimeZonePatterns()602 Object[][] data_parseGenericTimeZonePatterns() { 603 return new Object[][] { 604 {"yyyy DDD HH mm v", LocalDateTime.of(2015, Month.MARCH, 10, 12, 13), ZoneId.of("America/Los_Angeles"), 605 "2015 069 12 13 PT"}, 606 {"yyyy DDD HH mm vvvv", LocalDateTime.of(2015, Month.MARCH, 10, 12, 13), ZoneId.of("America/Los_Angeles"), 607 "2015 069 12 13 Pacific Time"}, 608 {"yyyy DDD HH mm v", LocalDateTime.of(2015, Month.NOVEMBER, 10, 12, 13), ZoneId.of("America/Los_Angeles"), 609 "2015 314 12 13 PT"}, 610 {"yyyy DDD HH mm vvvv", LocalDateTime.of(2015, Month.NOVEMBER, 10, 12, 13), ZoneId.of("America/Los_Angeles"), 611 "2015 314 12 13 Pacific Time"}, 612 }; 613 } 614 615 @Test(dataProvider = "parseGenericTimeZonePatterns") test_appendZoneText_parseGenericTimeZonePatterns(String pattern, LocalDateTime ldt, ZoneId zId, String input)616 public void test_appendZoneText_parseGenericTimeZonePatterns(String pattern, LocalDateTime ldt, ZoneId zId, String input) { 617 DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(Locale.US); 618 ZonedDateTime expected = ZonedDateTime.parse(input, df); 619 ZonedDateTime actual = ZonedDateTime.of(ldt, zId); 620 assertEquals(actual, expected); 621 } 622 623 @DataProvider(name = "formatNonGenericTimeZonePatterns_1") data_formatNonGenericTimeZonePatterns_1()624 Object[][] data_formatNonGenericTimeZonePatterns_1() { 625 return new Object[][] { 626 {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30), 627 "2015-11-01 00:30:00 PDT"}, 628 {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30), 629 "2015-11-01 01:30:00 PDT"}, 630 {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30), 631 "2015-11-01 02:30:00 PST"}, 632 {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30), 633 "2015-11-01 00:30:00 Pacific Daylight Time"}, 634 {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30), 635 "2015-11-01 01:30:00 Pacific Daylight Time"}, 636 {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30), 637 "2015-11-01 02:30:00 Pacific Standard Time"}, 638 }; 639 } 640 641 @Test(dataProvider = "formatNonGenericTimeZonePatterns_1") test_appendZoneText_parseNonGenricTimeZonePatterns_1(String pattern, LocalDateTime ldt, String expected)642 public void test_appendZoneText_parseNonGenricTimeZonePatterns_1(String pattern, LocalDateTime ldt, String expected) { 643 ZoneId zId = ZoneId.of("America/Los_Angeles"); 644 DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(Locale.US); 645 ZonedDateTime zdt = ZonedDateTime.of(ldt, zId); 646 String actual = df.format(zdt); 647 assertEquals(actual, expected); 648 } 649 650 @DataProvider(name = "formatNonGenericTimeZonePatterns_2") data_formatNonGenericTimeZonePatterns_2()651 Object[][] data_formatNonGenericTimeZonePatterns_2() { 652 return new Object[][] { 653 {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30), 654 "2015-11-01 00:30:00 PDT"}, 655 {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30), 656 "2015-11-01 01:30:00 PT"}, 657 {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30), 658 "2015-11-01 02:30:00 PST"}, 659 {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30), 660 "2015-11-01 00:30:00 Pacific Daylight Time"}, 661 {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30), 662 "2015-11-01 01:30:00 Pacific Time"}, 663 {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30), 664 "2015-11-01 02:30:00 Pacific Standard Time"}, 665 }; 666 } 667 668 @Test(dataProvider = "formatNonGenericTimeZonePatterns_2") test_appendZoneText_parseNonGenricTimeZonePatterns_2(String pattern, LocalDateTime ldt, String expected)669 public void test_appendZoneText_parseNonGenricTimeZonePatterns_2(String pattern, LocalDateTime ldt, String expected) { 670 ZoneId zId = ZoneId.of("America/Los_Angeles"); 671 DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern, Locale.US).withZone(zId); 672 String actual = df.format(ldt); 673 assertEquals(actual, expected); 674 } 675 676 @Test(expectedExceptions=NullPointerException.class) test_appendZoneText_1arg_nullText()677 public void test_appendZoneText_1arg_nullText() throws Exception { 678 builder.appendZoneText(null); 679 } 680 681 //----------------------------------------------------------------------- 682 //----------------------------------------------------------------------- 683 //----------------------------------------------------------------------- 684 @Test test_padNext_1arg()685 public void test_padNext_1arg() { 686 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2).appendValue(DAY_OF_MONTH); 687 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1"); 688 } 689 690 @Test(expectedExceptions=IllegalArgumentException.class) test_padNext_1arg_invalidWidth()691 public void test_padNext_1arg_invalidWidth() throws Exception { 692 builder.padNext(0); 693 } 694 695 //----------------------------------------------------------------------- 696 @Test test_padNext_2arg_dash()697 public void test_padNext_2arg_dash() throws Exception { 698 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2, '-').appendValue(DAY_OF_MONTH); 699 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2:-1"); 700 } 701 702 @Test(expectedExceptions=IllegalArgumentException.class) test_padNext_2arg_invalidWidth()703 public void test_padNext_2arg_invalidWidth() throws Exception { 704 builder.padNext(0, '-'); 705 } 706 707 //----------------------------------------------------------------------- 708 @Test test_padOptional()709 public void test_padOptional() throws Exception { 710 builder.appendValue(MONTH_OF_YEAR).appendLiteral(':') 711 .padNext(5).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd() 712 .appendLiteral(':').appendValue(YEAR); 713 assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1:2013"); 714 assertEquals(builder.toFormatter().format(YearMonth.of(2013, 2)), "2: :2013"); 715 } 716 717 //----------------------------------------------------------------------- 718 //----------------------------------------------------------------------- 719 //----------------------------------------------------------------------- 720 @Test(expectedExceptions=IllegalStateException.class) test_optionalEnd_noStart()721 public void test_optionalEnd_noStart() throws Exception { 722 builder.optionalEnd(); 723 } 724 725 //----------------------------------------------------------------------- 726 //----------------------------------------------------------------------- 727 //----------------------------------------------------------------------- 728 @DataProvider(name="validPatterns") dataValid()729 Object[][] dataValid() { 730 return new Object[][] { 731 {"'a'"}, 732 {"''"}, 733 {"'!'"}, 734 {"!"}, 735 {"'#'"}, 736 737 {"'hello_people,][)('"}, 738 {"'hi'"}, 739 {"'yyyy'"}, 740 {"''''"}, 741 {"'o''clock'"}, 742 743 {"G"}, 744 {"GG"}, 745 {"GGG"}, 746 {"GGGG"}, 747 {"GGGGG"}, 748 749 {"y"}, 750 {"yy"}, 751 {"yyy"}, 752 {"yyyy"}, 753 {"yyyyy"}, 754 755 {"M"}, 756 {"MM"}, 757 {"MMM"}, 758 {"MMMM"}, 759 {"MMMMM"}, 760 761 {"L"}, 762 {"LL"}, 763 {"LLL"}, 764 {"LLLL"}, 765 {"LLLLL"}, 766 767 {"D"}, 768 {"DD"}, 769 {"DDD"}, 770 771 {"d"}, 772 {"dd"}, 773 774 {"F"}, 775 776 {"Q"}, 777 {"QQ"}, 778 {"QQQ"}, 779 {"QQQQ"}, 780 {"QQQQQ"}, 781 782 {"q"}, 783 {"qq"}, 784 {"qqq"}, 785 {"qqqq"}, 786 {"qqqqq"}, 787 788 {"E"}, 789 {"EE"}, 790 {"EEE"}, 791 {"EEEE"}, 792 {"EEEEE"}, 793 794 {"e"}, 795 {"ee"}, 796 {"eee"}, 797 {"eeee"}, 798 {"eeeee"}, 799 800 {"c"}, 801 {"ccc"}, 802 {"cccc"}, 803 {"ccccc"}, 804 805 {"a"}, 806 807 {"H"}, 808 {"HH"}, 809 810 {"K"}, 811 {"KK"}, 812 813 {"k"}, 814 {"kk"}, 815 816 {"h"}, 817 {"hh"}, 818 819 {"m"}, 820 {"mm"}, 821 822 {"s"}, 823 {"ss"}, 824 825 {"S"}, 826 {"SS"}, 827 {"SSS"}, 828 {"SSSSSSSSS"}, 829 830 {"A"}, 831 {"AA"}, 832 {"AAA"}, 833 834 {"n"}, 835 {"nn"}, 836 {"nnn"}, 837 838 {"N"}, 839 {"NN"}, 840 {"NNN"}, 841 842 {"z"}, 843 {"zz"}, 844 {"zzz"}, 845 {"zzzz"}, 846 847 {"VV"}, 848 849 {"Z"}, 850 {"ZZ"}, 851 {"ZZZ"}, 852 853 {"X"}, 854 {"XX"}, 855 {"XXX"}, 856 {"XXXX"}, 857 {"XXXXX"}, 858 859 {"x"}, 860 {"xx"}, 861 {"xxx"}, 862 {"xxxx"}, 863 {"xxxxx"}, 864 865 {"ppH"}, 866 {"pppDD"}, 867 868 {"yyyy[-MM[-dd"}, 869 {"yyyy[-MM[-dd]]"}, 870 {"yyyy[-MM[]-dd]"}, 871 872 {"yyyy-MM-dd'T'HH:mm:ss.SSS"}, 873 874 {"e"}, 875 {"w"}, 876 {"ww"}, 877 {"W"}, 878 {"W"}, 879 880 {"g"}, 881 {"ggggg"}, 882 }; 883 } 884 885 @Test(dataProvider="validPatterns") test_appendPattern_valid(String input)886 public void test_appendPattern_valid(String input) throws Exception { 887 builder.appendPattern(input); // test is for no error here 888 } 889 890 //----------------------------------------------------------------------- 891 @DataProvider(name="invalidPatterns") dataInvalid()892 Object[][] dataInvalid() { 893 return new Object[][] { 894 {"'"}, 895 {"'hello"}, 896 {"'hel''lo"}, 897 {"'hello''"}, 898 {"{"}, 899 {"}"}, 900 {"{}"}, 901 {"#"}, 902 {"]"}, 903 {"yyyy]"}, 904 {"yyyy]MM"}, 905 {"yyyy[MM]]"}, 906 907 {"aa"}, 908 {"aaa"}, 909 {"aaaa"}, 910 {"aaaaa"}, 911 {"aaaaaa"}, 912 {"MMMMMM"}, 913 {"QQQQQQ"}, 914 {"qqqqqq"}, 915 {"EEEEEE"}, 916 {"eeeeee"}, 917 {"cc"}, 918 {"cccccc"}, 919 {"ddd"}, 920 {"DDDD"}, 921 {"FF"}, 922 {"FFF"}, 923 {"hhh"}, 924 {"HHH"}, 925 {"kkk"}, 926 {"KKK"}, 927 {"mmm"}, 928 {"sss"}, 929 {"OO"}, 930 {"OOO"}, 931 {"OOOOO"}, 932 {"XXXXXX"}, 933 {"zzzzz"}, 934 {"ZZZZZZ"}, 935 936 {"RO"}, 937 938 {"p"}, 939 {"pp"}, 940 {"p:"}, 941 942 {"f"}, 943 {"ff"}, 944 {"f:"}, 945 {"fy"}, 946 {"fa"}, 947 {"fM"}, 948 949 {"www"}, 950 {"WW"}, 951 952 {"vv"}, 953 {"vvv"}, 954 }; 955 } 956 957 @Test(dataProvider="invalidPatterns", expectedExceptions=IllegalArgumentException.class) test_appendPattern_invalid(String input)958 public void test_appendPattern_invalid(String input) throws Exception { 959 builder.appendPattern(input); // test is for error here 960 } 961 962 //----------------------------------------------------------------------- 963 @DataProvider(name="patternPrint") data_patternPrint()964 Object[][] data_patternPrint() { 965 return new Object[][] { 966 {"Q", date(2012, 2, 10), "1"}, 967 {"QQ", date(2012, 2, 10), "01"}, 968 {"QQQ", date(2012, 2, 10), "Q1"}, 969 {"QQQQ", date(2012, 2, 10), "1st quarter"}, 970 {"QQQQQ", date(2012, 2, 10), "1"}, 971 }; 972 } 973 974 @Test(dataProvider="patternPrint") test_appendPattern_patternPrint(String input, Temporal temporal, String expected)975 public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { 976 DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); 977 String test = f.format(temporal); 978 assertEquals(test, expected); 979 } 980 date(int y, int m, int d)981 private static Temporal date(int y, int m, int d) { 982 return LocalDate.of(y, m, d); 983 } 984 985 //----------------------------------------------------------------------- 986 @DataProvider(name="modJulianFieldPattern") data_modJuilanFieldPattern()987 Object[][] data_modJuilanFieldPattern() { 988 return new Object[][] { 989 {"g", "1"}, 990 {"g", "123456"}, 991 {"gggggg", "123456"}, 992 }; 993 } 994 995 @Test(dataProvider="modJulianFieldPattern") test_modJulianFieldPattern(String pattern, String input)996 public void test_modJulianFieldPattern(String pattern, String input) throws Exception { 997 DateTimeFormatter.ofPattern(pattern).parse(input); 998 } 999 1000 @DataProvider(name="modJulianFieldValues") data_modJuilanFieldValues()1001 Object[][] data_modJuilanFieldValues() { 1002 return new Object[][] { 1003 {1970, 1, 1, "40587"}, 1004 {1858, 11, 17, "0"}, 1005 {1858, 11, 16, "-1"}, 1006 }; 1007 } 1008 1009 @Test(dataProvider="modJulianFieldValues") test_modJulianFieldValues(int y, int m, int d, String expected)1010 public void test_modJulianFieldValues(int y, int m, int d, String expected) throws Exception { 1011 DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("g").toFormatter(); 1012 assertEquals(LocalDate.of(y, m, d).format(df), expected); 1013 } 1014 //---------------------------------------------------------------------- 1015 @DataProvider(name="dayOfYearFieldValues") data_dayOfYearFieldValues()1016 Object[][] data_dayOfYearFieldValues() { 1017 return new Object[][] { 1018 {2016, 1, 1, "D", "1"}, 1019 {2016, 1, 31, "D", "31"}, 1020 {2016, 1, 1, "DD", "01"}, 1021 {2016, 1, 31, "DD", "31"}, 1022 {2016, 4, 9, "DD", "100"}, 1023 {2016, 1, 1, "DDD", "001"}, 1024 {2016, 1, 31, "DDD", "031"}, 1025 {2016, 4, 9, "DDD", "100"}, 1026 }; 1027 } 1028 1029 @Test(dataProvider="dayOfYearFieldValues") test_dayOfYearFieldValues(int y, int m, int d, String pattern, String expected)1030 public void test_dayOfYearFieldValues(int y, int m, int d, String pattern, String expected) throws Exception { 1031 DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(); 1032 assertEquals(LocalDate.of(y, m, d).format(df), expected); 1033 } 1034 1035 @DataProvider(name="dayOfYearFieldAdjacentParsingValues") data_dayOfYearFieldAdjacentParsingValues()1036 Object[][] data_dayOfYearFieldAdjacentParsingValues() { 1037 return new Object[][] { 1038 {"20160281015", LocalDateTime.of(2016, 1, 28, 10, 15)}, 1039 {"20161001015", LocalDateTime.of(2016, 4, 9, 10, 15)}, 1040 }; 1041 } 1042 1043 @Test(dataProvider="dayOfYearFieldAdjacentParsingValues") test_dayOfYearFieldAdjacentValueParsing(String input, LocalDateTime expected)1044 public void test_dayOfYearFieldAdjacentValueParsing(String input, LocalDateTime expected) { 1045 DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("yyyyDDDHHmm").toFormatter(); 1046 LocalDateTime actual = LocalDateTime.parse(input, df); 1047 assertEquals(actual, expected); 1048 } 1049 1050 @Test(expectedExceptions = DateTimeParseException.class) test_dayOfYearFieldInvalidValue()1051 public void test_dayOfYearFieldInvalidValue() { 1052 DateTimeFormatter.ofPattern("DDD").parse("1234"); 1053 } 1054 1055 @Test(expectedExceptions = DateTimeParseException.class) test_dayOfYearFieldInvalidAdacentValueParsingPattern()1056 public void test_dayOfYearFieldInvalidAdacentValueParsingPattern() { 1057 // patterns D and DD will not take part in adjacent value parsing 1058 DateTimeFormatter.ofPattern("yyyyDDHHmmss").parse("201610123456"); 1059 } 1060 1061 //----------------------------------------------------------------------- 1062 @DataProvider(name="secondsPattern") data_secondsPattern()1063 Object[][] data_secondsPattern() { 1064 return new Object[][] { 1065 {"A", "1", LocalTime.ofNanoOfDay(1_000_000)}, 1066 {"A", "100000", LocalTime.ofSecondOfDay(100)}, 1067 {"AA", "01", LocalTime.ofNanoOfDay(1_000_000)}, 1068 {"AA", "100000", LocalTime.ofSecondOfDay(100)}, 1069 {"AAAAAA", "100000", LocalTime.ofSecondOfDay(100)}, 1070 {"HHmmssn", "0000001", LocalTime.ofNanoOfDay(1)}, 1071 {"HHmmssn", "000000111", LocalTime.ofNanoOfDay(111)}, 1072 {"HHmmssnn", "00000001", LocalTime.ofNanoOfDay(1)}, 1073 {"HHmmssnn", "0000001111", LocalTime.ofNanoOfDay(1111)}, 1074 {"HHmmssnnnnnn", "000000111111", LocalTime.ofNanoOfDay(111_111)}, 1075 {"N", "1", LocalTime.ofNanoOfDay(1)}, 1076 {"N", "100000", LocalTime.ofNanoOfDay(100_000)}, 1077 {"NN", "01", LocalTime.ofNanoOfDay(1)}, 1078 {"NN", "100000", LocalTime.ofNanoOfDay(100_000)}, 1079 {"NNNNNN", "100000", LocalTime.ofNanoOfDay(100_000)}, 1080 }; 1081 } 1082 1083 @Test(dataProvider="secondsPattern") test_secondsPattern(String pattern, String input, LocalTime expected)1084 public void test_secondsPattern(String pattern, String input, LocalTime expected) throws Exception { 1085 DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(); 1086 assertEquals(LocalTime.parse(input, df), expected); 1087 } 1088 1089 @DataProvider(name="secondsValues") data_secondsValues()1090 Object[][] data_secondsValues() { 1091 return new Object[][] { 1092 {"A", 1, "1000"}, 1093 {"n", 1, "0"}, 1094 {"N", 1, "1000000000"}, 1095 }; 1096 } 1097 1098 @Test(dataProvider="secondsValues") test_secondsValues(String pattern, int seconds , String expected)1099 public void test_secondsValues(String pattern, int seconds , String expected) throws Exception { 1100 DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(); 1101 assertEquals(LocalTime.ofSecondOfDay(seconds).format(df), expected); 1102 } 1103 1104 @Test(expectedExceptions = DateTimeParseException.class) test_secondsPatternInvalidAdacentValueParsingPattern()1105 public void test_secondsPatternInvalidAdacentValueParsingPattern() { 1106 // patterns A*, N*, n* will not take part in adjacent value parsing 1107 DateTimeFormatter.ofPattern("yyyyAA").parse("201610"); 1108 } 1109 1110 //----------------------------------------------------------------------- 1111 @Test test_adjacent_strict_firstFixedWidth()1112 public void test_adjacent_strict_firstFixedWidth() throws Exception { 1113 // succeeds because both number elements are fixed width 1114 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 1115 ParsePosition pp = new ParsePosition(0); 1116 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 1117 assertEquals(pp.getErrorIndex(), -1); 1118 assertEquals(pp.getIndex(), 5); 1119 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1120 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1121 } 1122 1123 @Test test_adjacent_strict_firstVariableWidth_success()1124 public void test_adjacent_strict_firstVariableWidth_success() throws Exception { 1125 // succeeds greedily parsing variable width, then fixed width, to non-numeric Z 1126 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('Z').toFormatter(Locale.UK); 1127 ParsePosition pp = new ParsePosition(0); 1128 TemporalAccessor parsed = f.parseUnresolved("12309Z", pp); 1129 assertEquals(pp.getErrorIndex(), -1); 1130 assertEquals(pp.getIndex(), 6); 1131 assertEquals(parsed.getLong(HOUR_OF_DAY), 123L); 1132 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 9L); 1133 } 1134 1135 @Test test_adjacent_strict_firstVariableWidth_fails()1136 public void test_adjacent_strict_firstVariableWidth_fails() throws Exception { 1137 // fails because literal is a number and variable width parse greedily absorbs it 1138 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 1139 ParsePosition pp = new ParsePosition(0); 1140 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 1141 assertEquals(pp.getErrorIndex(), 5); 1142 assertEquals(parsed, null); 1143 } 1144 1145 @Test test_adjacent_lenient()1146 public void test_adjacent_lenient() throws Exception { 1147 // succeeds because both number elements are fixed width even in lenient mode 1148 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 1149 ParsePosition pp = new ParsePosition(0); 1150 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 1151 assertEquals(pp.getErrorIndex(), -1); 1152 assertEquals(pp.getIndex(), 5); 1153 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1154 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1155 } 1156 1157 @Test test_adjacent_lenient_firstVariableWidth_success()1158 public void test_adjacent_lenient_firstVariableWidth_success() throws Exception { 1159 // succeeds greedily parsing variable width, then fixed width, to non-numeric Z 1160 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('Z').toFormatter(Locale.UK); 1161 ParsePosition pp = new ParsePosition(0); 1162 TemporalAccessor parsed = f.parseUnresolved("12309Z", pp); 1163 assertEquals(pp.getErrorIndex(), -1); 1164 assertEquals(pp.getIndex(), 6); 1165 assertEquals(parsed.getLong(HOUR_OF_DAY), 123L); 1166 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 9L); 1167 } 1168 1169 @Test test_adjacent_lenient_firstVariableWidth_fails()1170 public void test_adjacent_lenient_firstVariableWidth_fails() throws Exception { 1171 // fails because literal is a number and variable width parse greedily absorbs it 1172 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); 1173 ParsePosition pp = new ParsePosition(0); 1174 TemporalAccessor parsed = f.parseUnresolved("12309", pp); 1175 assertEquals(pp.getErrorIndex(), 5); 1176 assertEquals(parsed, null); 1177 } 1178 1179 //----------------------------------------------------------------------- 1180 @Test test_adjacent_strict_fractionFollows()1181 public void test_adjacent_strict_fractionFollows() throws Exception { 1182 // succeeds because hour/min are fixed width 1183 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); 1184 ParsePosition pp = new ParsePosition(0); 1185 TemporalAccessor parsed = f.parseUnresolved("1230567", pp); 1186 assertEquals(pp.getErrorIndex(), -1); 1187 assertEquals(pp.getIndex(), 7); 1188 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1189 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1190 assertEquals(parsed.getLong(NANO_OF_SECOND), 567_000_000L); 1191 } 1192 1193 @Test test_adjacent_strict_fractionFollows_2digit()1194 public void test_adjacent_strict_fractionFollows_2digit() throws Exception { 1195 // succeeds because hour/min are fixed width 1196 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); 1197 ParsePosition pp = new ParsePosition(0); 1198 TemporalAccessor parsed = f.parseUnresolved("123056", pp); 1199 assertEquals(pp.getErrorIndex(), -1); 1200 assertEquals(pp.getIndex(), 6); 1201 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1202 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1203 assertEquals(parsed.getLong(NANO_OF_SECOND), 560_000_000L); 1204 } 1205 1206 @Test test_adjacent_strict_fractionFollows_0digit()1207 public void test_adjacent_strict_fractionFollows_0digit() throws Exception { 1208 // succeeds because hour/min are fixed width 1209 DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); 1210 ParsePosition pp = new ParsePosition(0); 1211 TemporalAccessor parsed = f.parseUnresolved("1230", pp); 1212 assertEquals(pp.getErrorIndex(), -1); 1213 assertEquals(pp.getIndex(), 4); 1214 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1215 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1216 } 1217 1218 @Test test_adjacent_lenient_fractionFollows()1219 public void test_adjacent_lenient_fractionFollows() throws Exception { 1220 // succeeds because hour/min are fixed width 1221 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); 1222 ParsePosition pp = new ParsePosition(0); 1223 TemporalAccessor parsed = f.parseUnresolved("1230567", pp); 1224 assertEquals(pp.getErrorIndex(), -1); 1225 assertEquals(pp.getIndex(), 7); 1226 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1227 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1228 assertEquals(parsed.getLong(NANO_OF_SECOND), 567_000_000L); 1229 } 1230 1231 @Test test_adjacent_lenient_fractionFollows_2digit()1232 public void test_adjacent_lenient_fractionFollows_2digit() throws Exception { 1233 // succeeds because hour/min are fixed width 1234 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); 1235 ParsePosition pp = new ParsePosition(0); 1236 TemporalAccessor parsed = f.parseUnresolved("123056", pp); 1237 assertEquals(pp.getErrorIndex(), -1); 1238 assertEquals(pp.getIndex(), 6); 1239 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1240 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1241 assertEquals(parsed.getLong(NANO_OF_SECOND), 560_000_000L); 1242 } 1243 1244 @Test test_adjacent_lenient_fractionFollows_0digit()1245 public void test_adjacent_lenient_fractionFollows_0digit() throws Exception { 1246 // succeeds because hour, min and fraction of seconds are fixed width 1247 DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); 1248 ParsePosition pp = new ParsePosition(0); 1249 TemporalAccessor parsed = f.parseUnresolved("1230", pp); 1250 assertEquals(pp.getErrorIndex(), -1); 1251 assertEquals(pp.getIndex(), 4); 1252 assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); 1253 assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); 1254 } 1255 1256 @DataProvider(name="adjacentFractionParseData") data_adjacent_fraction_parse()1257 Object[][] data_adjacent_fraction_parse() { 1258 return new Object[][] { 1259 {"20130812214600025", "yyyyMMddHHmmssSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25000000)}, 1260 {"201308122146000256", "yyyyMMddHHmmssSSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25600000)}, 1261 }; 1262 } 1263 1264 @Test(dataProvider = "adjacentFractionParseData") test_adjacent_fraction(String input, String pattern, LocalDateTime expected)1265 public void test_adjacent_fraction(String input, String pattern, LocalDateTime expected) { 1266 DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern); 1267 LocalDateTime actual = LocalDateTime.parse(input, dtf); 1268 assertEquals(actual, expected); 1269 } 1270 1271 @DataProvider(name="lenientOffsetParseData") data_lenient_offset_parse()1272 Object[][] data_lenient_offset_parse() { 1273 return new Object[][] { 1274 {"+HH", "+01", 3600}, 1275 {"+HH", "+0101", 3660}, 1276 {"+HH", "+010101", 3661}, 1277 {"+HH", "+01", 3600}, 1278 {"+HH", "+01:01", 3660}, 1279 {"+HH", "+01:01:01", 3661}, 1280 {"+HHmm", "+01", 3600}, 1281 {"+HHmm", "+0101", 3660}, 1282 {"+HHmm", "+010101", 3661}, 1283 {"+HH:mm", "+01", 3600}, 1284 {"+HH:mm", "+01:01", 3660}, 1285 {"+HH:mm", "+01:01:01", 3661}, 1286 {"+HHMM", "+01", 3600}, 1287 {"+HHMM", "+0101", 3660}, 1288 {"+HHMM", "+010101", 3661}, 1289 {"+HH:MM", "+01", 3600}, 1290 {"+HH:MM", "+01:01", 3660}, 1291 {"+HH:MM", "+01:01:01", 3661}, 1292 {"+HHMMss", "+01", 3600}, 1293 {"+HHMMss", "+0101", 3660}, 1294 {"+HHMMss", "+010101", 3661}, 1295 {"+HH:MM:ss", "+01", 3600}, 1296 {"+HH:MM:ss", "+01:01", 3660}, 1297 {"+HH:MM:ss", "+01:01:01", 3661}, 1298 {"+HHMMSS", "+01", 3600}, 1299 {"+HHMMSS", "+0101", 3660}, 1300 {"+HHMMSS", "+010101", 3661}, 1301 {"+HH:MM:SS", "+01", 3600}, 1302 {"+HH:MM:SS", "+01:01", 3660}, 1303 {"+HH:MM:SS", "+01:01:01", 3661}, 1304 {"+HHmmss", "+01", 3600}, 1305 {"+HHmmss", "+0101", 3660}, 1306 {"+HHmmss", "+010101", 3661}, 1307 {"+HH:mm:ss", "+01", 3600}, 1308 {"+HH:mm:ss", "+01:01", 3660}, 1309 {"+HH:mm:ss", "+01:01:01", 3661}, 1310 1311 {"+H", "+1", 3600}, 1312 {"+H", "+101", 3660}, 1313 {"+H", "+10101", 3661}, 1314 {"+H", "+1:01", 3660}, 1315 {"+H", "+1:01:01", 3661}, 1316 {"+H", "+01", 3600}, 1317 {"+H", "+0101", 3660}, 1318 {"+H", "+010101", 3661}, 1319 {"+H", "+01:01", 3660}, 1320 {"+H", "+01:01:01", 3661}, 1321 {"+Hmm", "+1", 3600}, 1322 {"+Hmm", "+101", 3660}, 1323 {"+Hmm", "+10101", 3661}, 1324 {"+Hmm", "+01", 3600}, 1325 {"+Hmm", "+0101", 3660}, 1326 {"+Hmm", "+010101", 3661}, 1327 {"+H:mm", "+1", 3600}, 1328 {"+H:mm", "+1:01", 3660}, 1329 {"+H:mm", "+1:01:01", 3661}, 1330 {"+H:mm", "+01", 3600}, 1331 {"+H:mm", "+01:01", 3660}, 1332 {"+H:mm", "+01:01:01", 3661}, 1333 {"+HMM", "+1", 3600}, 1334 {"+HMM", "+101", 3660}, 1335 {"+HMM", "+10101", 3661}, 1336 {"+HMM", "+01", 3600}, 1337 {"+HMM", "+0101", 3660}, 1338 {"+HMM", "+010101", 3661}, 1339 {"+H:MM", "+1", 3600}, 1340 {"+H:MM", "+1:01", 3660}, 1341 {"+H:MM", "+1:01:01", 3661}, 1342 {"+H:MM", "+01", 3600}, 1343 {"+H:MM", "+01:01", 3660}, 1344 {"+H:MM", "+01:01:01", 3661}, 1345 {"+HMMss", "+1", 3600}, 1346 {"+HMMss", "+101", 3660}, 1347 {"+HMMss", "+10101", 3661}, 1348 {"+HMMss", "+01", 3600}, 1349 {"+HMMss", "+0101", 3660}, 1350 {"+HMMss", "+010101", 3661}, 1351 {"+H:MM:ss", "+1", 3600}, 1352 {"+H:MM:ss", "+1:01", 3660}, 1353 {"+H:MM:ss", "+1:01:01", 3661}, 1354 {"+H:MM:ss", "+01", 3600}, 1355 {"+H:MM:ss", "+01:01", 3660}, 1356 {"+H:MM:ss", "+01:01:01", 3661}, 1357 {"+HMMSS", "+1", 3600}, 1358 {"+HMMSS", "+101", 3660}, 1359 {"+HMMSS", "+10101", 3661}, 1360 {"+HMMSS", "+01", 3600}, 1361 {"+HMMSS", "+0101", 3660}, 1362 {"+HMMSS", "+010101", 3661}, 1363 {"+H:MM:SS", "+1", 3600}, 1364 {"+H:MM:SS", "+1:01", 3660}, 1365 {"+H:MM:SS", "+1:01:01", 3661}, 1366 {"+H:MM:SS", "+01", 3600}, 1367 {"+H:MM:SS", "+01:01", 3660}, 1368 {"+H:MM:SS", "+01:01:01", 3661}, 1369 {"+Hmmss", "+1", 3600}, 1370 {"+Hmmss", "+101", 3660}, 1371 {"+Hmmss", "+10101", 3661}, 1372 {"+Hmmss", "+01", 3600}, 1373 {"+Hmmss", "+0101", 3660}, 1374 {"+Hmmss", "+010101", 3661}, 1375 {"+H:mm:ss", "+1", 3600}, 1376 {"+H:mm:ss", "+1:01", 3660}, 1377 {"+H:mm:ss", "+1:01:01", 3661}, 1378 {"+H:mm:ss", "+01", 3600}, 1379 {"+H:mm:ss", "+01:01", 3660}, 1380 {"+H:mm:ss", "+01:01:01", 3661}, 1381 }; 1382 } 1383 1384 @DataProvider(name="strictDoubleDigitHourOffsetParseData") data_strictDoubleDigitHour_offset_parse()1385 Object[][] data_strictDoubleDigitHour_offset_parse() { 1386 return new Object[][] { 1387 {"+HH", "+01", 3600}, 1388 {"+HHmm", "+01", 3600}, 1389 {"+HHmm", "+0101", 3660}, 1390 {"+HH:mm", "+01", 3600}, 1391 {"+HH:mm", "+01:01", 3660}, 1392 {"+HHMM", "+0101", 3660}, 1393 {"+HH:MM", "+01:01", 3660}, 1394 {"+HHMMss", "+0101", 3660}, 1395 {"+HHMMss", "+010101", 3661}, 1396 {"+HH:MM:ss", "+01:01", 3660}, 1397 {"+HH:MM:ss", "+01:01:01", 3661}, 1398 {"+HHMMSS", "+010101", 3661}, 1399 {"+HH:MM:SS", "+01:01:01", 3661}, 1400 {"+HHmmss", "+01", 3600}, 1401 {"+HHmmss", "+0101", 3660}, 1402 {"+HHmmss", "+010101", 3661}, 1403 {"+HH:mm:ss", "+01", 3600}, 1404 {"+HH:mm:ss", "+01:01", 3660}, 1405 {"+HH:mm:ss", "+01:01:01", 3661}, 1406 }; 1407 } 1408 1409 @DataProvider(name="strictSingleDigitHourOffsetParseData") data_strictSingleDigitHour_offset_parse()1410 Object[][] data_strictSingleDigitHour_offset_parse() { 1411 return new Object[][] { 1412 {"+H", "+01", 3600}, 1413 {"+H", "+1", 3600}, 1414 {"+Hmm", "+01", 3600}, 1415 {"+Hmm", "+0101", 3660}, 1416 {"+Hmm", "+1", 3600}, 1417 {"+Hmm", "+101", 3660}, 1418 {"+H:mm", "+01", 3600}, 1419 {"+H:mm", "+01:01", 3660}, 1420 {"+H:mm", "+1", 3600}, 1421 {"+H:mm", "+1:01", 3660}, 1422 {"+HMM", "+0101", 3660}, 1423 {"+HMM", "+101", 3660}, 1424 {"+H:MM", "+01:01", 3660}, 1425 {"+H:MM", "+1:01", 3660}, 1426 {"+HMMss", "+0101", 3660}, 1427 {"+HMMss", "+010101", 3661}, 1428 {"+HMMss", "+101", 3660}, 1429 {"+HMMss", "+10101", 3661}, 1430 {"+H:MM:ss", "+01:01", 3660}, 1431 {"+H:MM:ss", "+01:01:01", 3661}, 1432 {"+H:MM:ss", "+1:01", 3660}, 1433 {"+H:MM:ss", "+1:01:01", 3661}, 1434 {"+HMMSS", "+010101", 3661}, 1435 {"+HMMSS", "+10101", 3661}, 1436 {"+H:MM:SS", "+01:01:01", 3661}, 1437 {"+H:MM:SS", "+1:01:01", 3661}, 1438 {"+Hmmss", "+01", 3600}, 1439 {"+Hmmss", "+0101", 3660}, 1440 {"+Hmmss", "+010101", 3661}, 1441 {"+Hmmss", "+1", 3600}, 1442 {"+Hmmss", "+101", 3660}, 1443 {"+Hmmss", "+10101", 3661}, 1444 {"+H:mm:ss", "+01", 3600}, 1445 {"+H:mm:ss", "+01:01", 3660}, 1446 {"+H:mm:ss", "+01:01:01", 3661}, 1447 {"+H:mm:ss", "+1", 3600}, 1448 {"+H:mm:ss", "+1:01", 3660}, 1449 {"+H:mm:ss", "+1:01:01", 3661}, 1450 }; 1451 } 1452 1453 @Test(dataProvider="lenientOffsetParseData") test_lenient_offset_parse_1(String pattern, String offset, int offsetSeconds)1454 public void test_lenient_offset_parse_1(String pattern, String offset, int offsetSeconds) { 1455 assertEquals(new DateTimeFormatterBuilder().parseLenient().appendOffset(pattern, "Z").toFormatter().parse(offset).get(OFFSET_SECONDS), 1456 offsetSeconds); 1457 } 1458 1459 @Test test_lenient_offset_parse_2()1460 public void test_lenient_offset_parse_2() { 1461 assertEquals(new DateTimeFormatterBuilder().parseLenient().appendOffsetId().toFormatter().parse("+01").get(OFFSET_SECONDS), 1462 3600); 1463 } 1464 1465 @Test(dataProvider="strictDoubleDigitHourOffsetParseData") test_strictDoubleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds)1466 public void test_strictDoubleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) { 1467 assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter() 1468 .parse(offset).get(OFFSET_SECONDS), offsetSeconds); 1469 } 1470 1471 @Test(dataProvider="strictDoubleDigitHourOffsetParseData") test_strictDoubleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds)1472 public void test_strictDoubleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) { 1473 assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z") 1474 .appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds); 1475 } 1476 1477 @Test(dataProvider="strictSingleDigitHourOffsetParseData") test_strictSingleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds)1478 public void test_strictSingleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) { 1479 assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter() 1480 .parse(offset).get(OFFSET_SECONDS), offsetSeconds); 1481 } 1482 1483 @Test(dataProvider="strictSingleDigitHourOffsetParseData") test_strictSingleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds)1484 public void test_strictSingleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) { 1485 assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z") 1486 .appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds); 1487 } 1488 1489 @DataProvider(name="strictOffsetAdjacentParseValidPatternData") data_strict_offset_adjacentParse_validPattern()1490 Object[][] data_strict_offset_adjacentParse_validPattern() { 1491 return new Object[][] { 1492 {"+HH", "+01", 3600}, 1493 {"+HHmm", "+0101", 3660}, 1494 {"+HH:mm", "+01", 3600}, 1495 {"+HH:mm", "+01:01", 3660}, 1496 {"+HHMM", "+0101", 3660}, 1497 {"+HH:MM", "+01:01", 3660}, 1498 {"+HHMMss", "+010101", 3661}, 1499 {"+HH:MM:ss", "+01:01", 3660}, 1500 {"+HH:MM:ss", "+01:01:01", 3661}, 1501 {"+HHMMSS", "+010101", 3661}, 1502 {"+HH:MM:SS", "+01:01:01", 3661}, 1503 {"+HHmmss", "+010101", 3661}, 1504 {"+HH:mm:ss", "+01", 3600}, 1505 {"+HH:mm:ss", "+01:01", 3660}, 1506 {"+HH:mm:ss", "+01:01:01", 3661}, 1507 1508 {"+H", "+01", 3600}, 1509 {"+Hmm", "+0101", 3660}, 1510 {"+H:mm", "+01", 3600}, 1511 {"+H:mm", "+01:01", 3660}, 1512 {"+H:mm", "+1:01", 3660}, 1513 {"+HMM", "+0101", 3660}, 1514 {"+H:MM", "+01:01", 3660}, 1515 {"+H:MM", "+1:01", 3660}, 1516 {"+HMMss", "+010101", 3661}, 1517 {"+H:MM:ss", "+01:01", 3660}, 1518 {"+H:MM:ss", "+01:01:01", 3661}, 1519 {"+H:MM:ss", "+1:01", 3660}, 1520 {"+H:MM:ss", "+1:01:01", 3661}, 1521 {"+HMMSS", "+010101", 3661}, 1522 {"+H:MM:SS", "+01:01:01", 3661}, 1523 {"+H:MM:SS", "+1:01:01", 3661}, 1524 {"+Hmmss", "+010101", 3661}, 1525 {"+H:mm:ss", "+01", 3600}, 1526 {"+H:mm:ss", "+01:01", 3660}, 1527 {"+H:mm:ss", "+01:01:01", 3661}, 1528 {"+H:mm:ss", "+1:01", 3660}, 1529 {"+H:mm:ss", "+1:01:01", 3661}, 1530 }; 1531 } 1532 1533 @Test(dataProvider="strictOffsetAdjacentParseValidPatternData") test_strict_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds)1534 public void test_strict_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) { 1535 TemporalAccessor tmp = new DateTimeFormatterBuilder().appendOffset(pattern, "Z") 1536 .appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12"); 1537 assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds); 1538 assertEquals(tmp.get(HOUR_OF_DAY), 12); 1539 } 1540 1541 @DataProvider(name="strictOffsetAdjacentParseInvalidPatternData") data_strict_offset_adjacentParse_invalidPattern()1542 Object[][] data_strict_offset_adjacentParse_invalidPattern() { 1543 return new Object[][] { 1544 {"+HHmm", "+01", 3600}, 1545 {"+HHMMss", "+0101", 3660}, 1546 {"+HHmmss", "+01", 3600}, 1547 {"+HHmmss", "+0101", 3660}, 1548 {"+H", "+1", 3600}, 1549 {"+Hmm", "+01", 3600}, 1550 {"+H:mm", "+1", 3600}, 1551 {"+Hmm", "+1", 3600}, 1552 {"+Hmm", "+101", 3660}, 1553 {"+HMM", "+101", 3660}, 1554 {"+HMMss", "+0101", 3660}, 1555 {"+HMMss", "+101", 3660}, 1556 {"+HMMss", "+10101", 3661}, 1557 {"+HMMSS", "+10101", 3661}, 1558 {"+Hmmss", "+01", 3600}, 1559 {"+Hmmss", "+0101", 3660}, 1560 {"+Hmmss", "+1", 3600}, 1561 {"+Hmmss", "+101", 3660}, 1562 {"+Hmmss", "+10101", 3661}, 1563 {"+H:mm:ss", "+1", 3600}, 1564 }; 1565 } 1566 1567 @Test(dataProvider="strictOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class) test_strict_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds)1568 public void test_strict_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) { 1569 new DateTimeFormatterBuilder().appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2) 1570 .toFormatter().parse(offset + "12"); 1571 } 1572 1573 @DataProvider(name="lenientOffsetAdjacentParseValidPatternData") data_lenient_offset_adjacentParse_validPattern()1574 Object[][] data_lenient_offset_adjacentParse_validPattern() { 1575 return new Object[][] { 1576 {"+HH:mm", "+01", 3600}, 1577 {"+HH:mm", "+01:01", 3660}, 1578 {"+HH:MM", "+01:01", 3660}, 1579 {"+HH:MM:ss", "+01:01", 3660}, 1580 {"+HH:MM:ss", "+01:01:01", 3661}, 1581 {"+HHMMSS", "+010101", 3661}, 1582 {"+HH:MM:SS", "+01:01:01", 3661}, 1583 {"+HHmmss", "+010101", 3661}, 1584 {"+HH:mm:ss", "+01", 3600}, 1585 {"+HH:mm:ss", "+01:01", 3660}, 1586 {"+HH:mm:ss", "+01:01:01", 3661}, 1587 {"+H:mm", "+01", 3600}, 1588 {"+H:mm", "+01:01", 3660}, 1589 {"+H:mm", "+1:01", 3660}, 1590 {"+H:MM", "+01:01", 3660}, 1591 {"+H:MM", "+1:01", 3660}, 1592 {"+HMMss", "+010101", 3661}, 1593 {"+H:MM:ss", "+01:01", 3660}, 1594 {"+H:MM:ss", "+01:01:01", 3661}, 1595 {"+H:MM:ss", "+1:01", 3660}, 1596 {"+H:MM:ss", "+1:01:01", 3661}, 1597 {"+HMMSS", "+010101", 3661}, 1598 {"+H:MM:SS", "+01:01:01", 3661}, 1599 {"+H:MM:SS", "+1:01:01", 3661}, 1600 {"+Hmmss", "+010101", 3661}, 1601 {"+H:mm:ss", "+01", 3600}, 1602 {"+H:mm:ss", "+01:01", 3660}, 1603 {"+H:mm:ss", "+01:01:01", 3661}, 1604 {"+H:mm:ss", "+1:01", 3660}, 1605 {"+H:mm:ss", "+1:01:01", 3661}, 1606 }; 1607 } 1608 1609 @Test(dataProvider="lenientOffsetAdjacentParseValidPatternData") test_lenient_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds)1610 public void test_lenient_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) { 1611 TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient() 1612 .appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12"); 1613 assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds); 1614 assertEquals(tmp.get(HOUR_OF_DAY), 12); 1615 } 1616 1617 @Test test_lenient_offset_adjacentValidPattern_parse1()1618 public void test_lenient_offset_adjacentValidPattern_parse1() { 1619 TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient() 1620 .appendOffset("+HMMSS", "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse("+10101" + "12"); 1621 //Equivalent to +101011. In lenient mode, offset will parse upto 6 digit if possible. 1622 //It will take 1 digit from HOUR_OF_DAY. 1623 assertEquals(tmp.get(OFFSET_SECONDS), 36611); 1624 assertEquals(tmp.get(HOUR_OF_DAY), 2); 1625 } 1626 1627 @DataProvider(name="lenientOffsetAdjacentParseInvalidPatternData") data_lenient_offset_adjacentParse_invalidPattern()1628 Object[][] data_lenient_offset_adjacentParse_invalidPattern() { 1629 return new Object[][] { 1630 {"+HH", "+01", 3600}, 1631 {"+HHmm", "+0101", 3660}, 1632 {"+HHMM", "+0101", 3660}, 1633 {"+H", "+01", 3600}, 1634 {"+Hmm", "+0101", 3660}, 1635 {"+HMM", "+0101", 3660}, 1636 }; 1637 } 1638 1639 @Test(dataProvider="lenientOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class) test_lenient_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds)1640 public void test_lenient_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) { 1641 new DateTimeFormatterBuilder().parseLenient().appendOffset(pattern, "Z") 1642 .appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12"); 1643 } 1644 1645 @DataProvider(name="badValues") data_badOffsetValues()1646 Object[][] data_badOffsetValues() { 1647 return new Object[][] { 1648 {"+HH", "+24"}, 1649 {"+HHMM", "-1361"}, 1650 {"+HH:MM:ss", "+13:12:66"}, 1651 {"+HH:MM:SS", "+24:60:60"}, 1652 {"+HHMMSS", "369999"}, 1653 {"+H:MM", "+28:12"}, 1654 }; 1655 } 1656 1657 @Test(dataProvider="badValues", expectedExceptions=DateTimeParseException.class) test_badOffset_parse(String pattern, String offset)1658 public void test_badOffset_parse(String pattern, String offset) { 1659 new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter().parse(offset); 1660 } 1661 1662 @Test(expectedExceptions=DateTimeParseException.class) test_strict_appendOffsetId()1663 public void test_strict_appendOffsetId() { 1664 new DateTimeFormatterBuilder().appendOffsetId().toFormatter().parse("+01"); 1665 } 1666 1667 @Test(expectedExceptions=DateTimeParseException.class) test_strict_appendOffset_1()1668 public void test_strict_appendOffset_1() { 1669 new DateTimeFormatterBuilder().appendOffset("+HH:MM:ss", "Z").toFormatter().parse("+01"); 1670 } 1671 1672 @Test(expectedExceptions=DateTimeParseException.class) test_strict_appendOffset_2()1673 public void test_strict_appendOffset_2() { 1674 new DateTimeFormatterBuilder().appendOffset("+HHMMss", "Z").toFormatter().parse("+01"); 1675 } 1676 1677 @Test(expectedExceptions=DateTimeParseException.class) test_strict_appendOffset_3()1678 public void test_strict_appendOffset_3() { 1679 new DateTimeFormatterBuilder().appendOffset("+H:MM:ss", "Z").toFormatter().parse("+1"); 1680 } 1681 1682 @Test(expectedExceptions=DateTimeParseException.class) test_strict_appendOffset_4()1683 public void test_strict_appendOffset_4() { 1684 new DateTimeFormatterBuilder().appendOffset("+HMMss", "Z").toFormatter().parse("+1"); 1685 } 1686 1687 @Test test_basic_iso_date()1688 public void test_basic_iso_date() { 1689 assertEquals(BASIC_ISO_DATE.parse("20021231+01").get(OFFSET_SECONDS), 3600); 1690 assertEquals(BASIC_ISO_DATE.parse("20021231+0101").get(OFFSET_SECONDS), 3660); 1691 } 1692 1693 } 1694