| /* |
| * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * This file is available under and governed by the GNU General Public |
| * License version 2 only, as published by the Free Software Foundation. |
| * However, the following notice accompanied the original version of this |
| * file: |
| * |
| * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * * Neither the name of JSR-310 nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| package tck.java.time.format; |
| |
| import static java.time.temporal.ChronoField.DAY_OF_MONTH; |
| import static java.time.temporal.ChronoField.HOUR_OF_DAY; |
| import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; |
| import static java.time.temporal.ChronoField.MONTH_OF_YEAR; |
| import static java.time.temporal.ChronoField.NANO_OF_SECOND; |
| import static java.time.temporal.ChronoField.YEAR; |
| import static org.testng.Assert.assertEquals; |
| |
| import java.text.ParsePosition; |
| import java.time.LocalDate; |
| import java.time.YearMonth; |
| import java.time.ZoneOffset; |
| import java.time.format.DateTimeFormatter; |
| import java.time.format.DateTimeFormatterBuilder; |
| import java.time.format.SignStyle; |
| import java.time.format.TextStyle; |
| import java.time.temporal.Temporal; |
| import java.time.temporal.TemporalAccessor; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.testng.annotations.BeforeMethod; |
| import org.testng.annotations.DataProvider; |
| import org.testng.annotations.Test; |
| |
| /** |
| * Test DateTimeFormatterBuilder. |
| */ |
| @Test |
| public class TCKDateTimeFormatterBuilder { |
| |
| private DateTimeFormatterBuilder builder; |
| |
| @BeforeMethod |
| public void setUp() { |
| builder = new DateTimeFormatterBuilder(); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test |
| public void test_toFormatter_empty() throws Exception { |
| DateTimeFormatter f = builder.toFormatter(); |
| assertEquals(f.format(LocalDate.of(2012, 6, 30)), ""); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test |
| public void test_parseDefaulting_entireDate() { |
| DateTimeFormatter f = builder |
| .parseDefaulting(YEAR, 2012).parseDefaulting(MONTH_OF_YEAR, 6) |
| .parseDefaulting(DAY_OF_MONTH, 30).toFormatter(); |
| LocalDate parsed = f.parse("", LocalDate::from); // blank string can be parsed |
| assertEquals(parsed, LocalDate.of(2012, 6, 30)); |
| } |
| |
| @Test |
| public void test_parseDefaulting_yearOptionalMonthOptionalDay() { |
| DateTimeFormatter f = builder |
| .appendValue(YEAR) |
| .optionalStart().appendLiteral('-').appendValue(MONTH_OF_YEAR) |
| .optionalStart().appendLiteral('-').appendValue(DAY_OF_MONTH) |
| .optionalEnd().optionalEnd() |
| .parseDefaulting(MONTH_OF_YEAR, 1) |
| .parseDefaulting(DAY_OF_MONTH, 1).toFormatter(); |
| assertEquals(f.parse("2012", LocalDate::from), LocalDate.of(2012, 1, 1)); |
| assertEquals(f.parse("2012-6", LocalDate::from), LocalDate.of(2012, 6, 1)); |
| assertEquals(f.parse("2012-6-30", LocalDate::from), LocalDate.of(2012, 6, 30)); |
| } |
| |
| @Test(expectedExceptions = NullPointerException.class) |
| public void test_parseDefaulting_null() { |
| builder.parseDefaulting(null, 1); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendValue_1arg_null() throws Exception { |
| builder.appendValue(null); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendValue_2arg_null() throws Exception { |
| builder.appendValue(null, 3); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValue_2arg_widthTooSmall() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 0); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValue_2arg_widthTooBig() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 20); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendValue_3arg_nullField() throws Exception { |
| builder.appendValue(null, 2, 3, SignStyle.NORMAL); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValue_3arg_minWidthTooSmall() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 0, 2, SignStyle.NORMAL); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValue_3arg_minWidthTooBig() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 20, 2, SignStyle.NORMAL); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValue_3arg_maxWidthTooSmall() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 2, 0, SignStyle.NORMAL); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValue_3arg_maxWidthTooBig() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 2, 20, SignStyle.NORMAL); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValue_3arg_maxWidthMinWidth() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 4, 2, SignStyle.NORMAL); |
| } |
| |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendValue_3arg_nullSignStyle() throws Exception { |
| builder.appendValue(DAY_OF_MONTH, 2, 3, null); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendValueReduced_int_nullField() throws Exception { |
| builder.appendValueReduced(null, 2, 2, 2000); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_int_minWidthTooSmall() throws Exception { |
| builder.appendValueReduced(YEAR, 0, 2, 2000); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_int_minWidthTooBig() throws Exception { |
| builder.appendValueReduced(YEAR, 11, 2, 2000); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_int_maxWidthTooSmall() throws Exception { |
| builder.appendValueReduced(YEAR, 2, 0, 2000); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_int_maxWidthTooBig() throws Exception { |
| builder.appendValueReduced(YEAR, 2, 11, 2000); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_int_maxWidthLessThanMin() throws Exception { |
| builder.appendValueReduced(YEAR, 2, 1, 2000); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendValueReduced_date_nullField() throws Exception { |
| builder.appendValueReduced(null, 2, 2, LocalDate.of(2000, 1, 1)); |
| } |
| |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendValueReduced_date_nullDate() throws Exception { |
| builder.appendValueReduced(YEAR, 2, 2, null); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_date_minWidthTooSmall() throws Exception { |
| builder.appendValueReduced(YEAR, 0, 2, LocalDate.of(2000, 1, 1)); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_date_minWidthTooBig() throws Exception { |
| builder.appendValueReduced(YEAR, 11, 2, LocalDate.of(2000, 1, 1)); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_date_maxWidthTooSmall() throws Exception { |
| builder.appendValueReduced(YEAR, 2, 0, LocalDate.of(2000, 1, 1)); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_date_maxWidthTooBig() throws Exception { |
| builder.appendValueReduced(YEAR, 2, 11, LocalDate.of(2000, 1, 1)); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendValueReduced_date_maxWidthLessThanMin() throws Exception { |
| builder.appendValueReduced(YEAR, 2, 1, LocalDate.of(2000, 1, 1)); |
| } |
| |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendFraction_4arg_nullRule() throws Exception { |
| builder.appendFraction(null, 1, 9, false); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendFraction_4arg_invalidRuleNotFixedSet() throws Exception { |
| builder.appendFraction(DAY_OF_MONTH, 1, 9, false); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendFraction_4arg_minTooSmall() throws Exception { |
| builder.appendFraction(MINUTE_OF_HOUR, -1, 9, false); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendFraction_4arg_minTooBig() throws Exception { |
| builder.appendFraction(MINUTE_OF_HOUR, 10, 9, false); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendFraction_4arg_maxTooSmall() throws Exception { |
| builder.appendFraction(MINUTE_OF_HOUR, 0, -1, false); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendFraction_4arg_maxTooBig() throws Exception { |
| builder.appendFraction(MINUTE_OF_HOUR, 1, 10, false); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_appendFraction_4arg_maxWidthMinWidth() throws Exception { |
| builder.appendFraction(MINUTE_OF_HOUR, 9, 3, false); |
| } |
| |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendText_1arg_null() throws Exception { |
| builder.appendText(null); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendText_2arg_nullRule() throws Exception { |
| builder.appendText(null, TextStyle.SHORT); |
| } |
| |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendText_2arg_nullStyle() throws Exception { |
| builder.appendText(MONTH_OF_YEAR, (TextStyle) null); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendTextMap_nullRule() throws Exception { |
| builder.appendText(null, new HashMap<>()); |
| } |
| |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendTextMap_nullStyle() throws Exception { |
| builder.appendText(MONTH_OF_YEAR, (Map<Long, String>) null); |
| } |
| |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| @DataProvider(name="offsetPatterns") |
| Object[][] data_offsetPatterns() { |
| return new Object[][] { |
| {"+HH", 2, 0, 0, "+02"}, |
| {"+HH", -2, 0, 0, "-02"}, |
| {"+HH", 2, 30, 0, "+02"}, |
| {"+HH", 2, 0, 45, "+02"}, |
| {"+HH", 2, 30, 45, "+02"}, |
| |
| {"+HHMM", 2, 0, 0, "+0200"}, |
| {"+HHMM", -2, 0, 0, "-0200"}, |
| {"+HHMM", 2, 30, 0, "+0230"}, |
| {"+HHMM", 2, 0, 45, "+0200"}, |
| {"+HHMM", 2, 30, 45, "+0230"}, |
| |
| {"+HH:MM", 2, 0, 0, "+02:00"}, |
| {"+HH:MM", -2, 0, 0, "-02:00"}, |
| {"+HH:MM", 2, 30, 0, "+02:30"}, |
| {"+HH:MM", 2, 0, 45, "+02:00"}, |
| {"+HH:MM", 2, 30, 45, "+02:30"}, |
| |
| {"+HHMMss", 2, 0, 0, "+0200"}, |
| {"+HHMMss", -2, 0, 0, "-0200"}, |
| {"+HHMMss", 2, 30, 0, "+0230"}, |
| {"+HHMMss", 2, 0, 45, "+020045"}, |
| {"+HHMMss", 2, 30, 45, "+023045"}, |
| |
| {"+HH:MM:ss", 2, 0, 0, "+02:00"}, |
| {"+HH:MM:ss", -2, 0, 0, "-02:00"}, |
| {"+HH:MM:ss", 2, 30, 0, "+02:30"}, |
| {"+HH:MM:ss", 2, 0, 45, "+02:00:45"}, |
| {"+HH:MM:ss", 2, 30, 45, "+02:30:45"}, |
| |
| {"+HHMMSS", 2, 0, 0, "+020000"}, |
| {"+HHMMSS", -2, 0, 0, "-020000"}, |
| {"+HHMMSS", 2, 30, 0, "+023000"}, |
| {"+HHMMSS", 2, 0, 45, "+020045"}, |
| {"+HHMMSS", 2, 30, 45, "+023045"}, |
| |
| {"+HH:MM:SS", 2, 0, 0, "+02:00:00"}, |
| {"+HH:MM:SS", -2, 0, 0, "-02:00:00"}, |
| {"+HH:MM:SS", 2, 30, 0, "+02:30:00"}, |
| {"+HH:MM:SS", 2, 0, 45, "+02:00:45"}, |
| {"+HH:MM:SS", 2, 30, 45, "+02:30:45"}, |
| }; |
| } |
| |
| @Test(dataProvider="offsetPatterns") |
| public void test_appendOffset_format(String pattern, int h, int m, int s, String expected) throws Exception { |
| builder.appendOffset(pattern, "Z"); |
| DateTimeFormatter f = builder.toFormatter(); |
| ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); |
| assertEquals(f.format(offset), expected); |
| } |
| |
| @Test(dataProvider="offsetPatterns") |
| public void test_appendOffset_parse(String pattern, int h, int m, int s, String expected) throws Exception { |
| builder.appendOffset(pattern, "Z"); |
| DateTimeFormatter f = builder.toFormatter(); |
| ZoneOffset parsed = f.parse(expected, ZoneOffset::from); |
| assertEquals(f.format(parsed), expected); |
| } |
| |
| @DataProvider(name="badOffsetPatterns") |
| Object[][] data_badOffsetPatterns() { |
| return new Object[][] { |
| {"HH"}, |
| {"HHMM"}, |
| {"HH:MM"}, |
| {"HHMMss"}, |
| {"HH:MM:ss"}, |
| {"HHMMSS"}, |
| {"HH:MM:SS"}, |
| {"+H"}, |
| {"+HMM"}, |
| {"+HHM"}, |
| {"+A"}, |
| }; |
| } |
| |
| @Test(dataProvider="badOffsetPatterns", expectedExceptions=IllegalArgumentException.class) |
| public void test_appendOffset_badPattern(String pattern) throws Exception { |
| builder.appendOffset(pattern, "Z"); |
| } |
| |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendOffset_3arg_nullText() throws Exception { |
| builder.appendOffset("+HH:MM", null); |
| } |
| |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendOffset_3arg_nullPattern() throws Exception { |
| builder.appendOffset(null, "Z"); |
| } |
| |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=NullPointerException.class) |
| public void test_appendZoneText_1arg_nullText() throws Exception { |
| builder.appendZoneText(null); |
| } |
| |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| @Test |
| public void test_padNext_1arg() { |
| builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2).appendValue(DAY_OF_MONTH); |
| assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1"); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_padNext_1arg_invalidWidth() throws Exception { |
| builder.padNext(0); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test |
| public void test_padNext_2arg_dash() throws Exception { |
| builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2, '-').appendValue(DAY_OF_MONTH); |
| assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2:-1"); |
| } |
| |
| @Test(expectedExceptions=IllegalArgumentException.class) |
| public void test_padNext_2arg_invalidWidth() throws Exception { |
| builder.padNext(0, '-'); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test |
| public void test_padOptional() throws Exception { |
| builder.appendValue(MONTH_OF_YEAR).appendLiteral(':') |
| .padNext(5).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd() |
| .appendLiteral(':').appendValue(YEAR); |
| assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1:2013"); |
| assertEquals(builder.toFormatter().format(YearMonth.of(2013, 2)), "2: :2013"); |
| } |
| |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| @Test(expectedExceptions=IllegalStateException.class) |
| public void test_optionalEnd_noStart() throws Exception { |
| builder.optionalEnd(); |
| } |
| |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| //----------------------------------------------------------------------- |
| @DataProvider(name="validPatterns") |
| Object[][] dataValid() { |
| return new Object[][] { |
| {"'a'"}, |
| {"''"}, |
| {"'!'"}, |
| {"!"}, |
| {"'#'"}, |
| |
| {"'hello_people,][)('"}, |
| {"'hi'"}, |
| {"'yyyy'"}, |
| {"''''"}, |
| {"'o''clock'"}, |
| |
| {"G"}, |
| {"GG"}, |
| {"GGG"}, |
| {"GGGG"}, |
| {"GGGGG"}, |
| |
| {"y"}, |
| {"yy"}, |
| {"yyy"}, |
| {"yyyy"}, |
| {"yyyyy"}, |
| |
| {"M"}, |
| {"MM"}, |
| {"MMM"}, |
| {"MMMM"}, |
| {"MMMMM"}, |
| |
| {"L"}, |
| {"LL"}, |
| {"LLL"}, |
| {"LLLL"}, |
| {"LLLLL"}, |
| |
| {"D"}, |
| {"DD"}, |
| {"DDD"}, |
| |
| {"d"}, |
| {"dd"}, |
| |
| {"F"}, |
| |
| {"Q"}, |
| {"QQ"}, |
| {"QQQ"}, |
| {"QQQQ"}, |
| {"QQQQQ"}, |
| |
| {"q"}, |
| {"qq"}, |
| {"qqq"}, |
| {"qqqq"}, |
| {"qqqqq"}, |
| |
| {"E"}, |
| {"EE"}, |
| {"EEE"}, |
| {"EEEE"}, |
| {"EEEEE"}, |
| |
| {"e"}, |
| {"ee"}, |
| {"eee"}, |
| {"eeee"}, |
| {"eeeee"}, |
| |
| {"c"}, |
| {"ccc"}, |
| {"cccc"}, |
| {"ccccc"}, |
| |
| {"a"}, |
| |
| {"H"}, |
| {"HH"}, |
| |
| {"K"}, |
| {"KK"}, |
| |
| {"k"}, |
| {"kk"}, |
| |
| {"h"}, |
| {"hh"}, |
| |
| {"m"}, |
| {"mm"}, |
| |
| {"s"}, |
| {"ss"}, |
| |
| {"S"}, |
| {"SS"}, |
| {"SSS"}, |
| {"SSSSSSSSS"}, |
| |
| {"A"}, |
| {"AA"}, |
| {"AAA"}, |
| |
| {"n"}, |
| {"nn"}, |
| {"nnn"}, |
| |
| {"N"}, |
| {"NN"}, |
| {"NNN"}, |
| |
| {"z"}, |
| {"zz"}, |
| {"zzz"}, |
| {"zzzz"}, |
| |
| {"VV"}, |
| |
| {"Z"}, |
| {"ZZ"}, |
| {"ZZZ"}, |
| |
| {"X"}, |
| {"XX"}, |
| {"XXX"}, |
| {"XXXX"}, |
| {"XXXXX"}, |
| |
| {"x"}, |
| {"xx"}, |
| {"xxx"}, |
| {"xxxx"}, |
| {"xxxxx"}, |
| |
| {"ppH"}, |
| {"pppDD"}, |
| |
| {"yyyy[-MM[-dd"}, |
| {"yyyy[-MM[-dd]]"}, |
| {"yyyy[-MM[]-dd]"}, |
| |
| {"yyyy-MM-dd'T'HH:mm:ss.SSS"}, |
| |
| {"e"}, |
| {"w"}, |
| {"ww"}, |
| {"W"}, |
| {"W"}, |
| |
| }; |
| } |
| |
| @Test(dataProvider="validPatterns") |
| public void test_appendPattern_valid(String input) throws Exception { |
| builder.appendPattern(input); // test is for no error here |
| } |
| |
| //----------------------------------------------------------------------- |
| @DataProvider(name="invalidPatterns") |
| Object[][] dataInvalid() { |
| return new Object[][] { |
| {"'"}, |
| {"'hello"}, |
| {"'hel''lo"}, |
| {"'hello''"}, |
| {"{"}, |
| {"}"}, |
| {"{}"}, |
| {"#"}, |
| {"]"}, |
| {"yyyy]"}, |
| {"yyyy]MM"}, |
| {"yyyy[MM]]"}, |
| |
| {"aa"}, |
| {"aaa"}, |
| {"aaaa"}, |
| {"aaaaa"}, |
| {"aaaaaa"}, |
| {"MMMMMM"}, |
| {"QQQQQQ"}, |
| {"qqqqqq"}, |
| {"EEEEEE"}, |
| {"eeeeee"}, |
| {"cc"}, |
| {"cccccc"}, |
| {"ddd"}, |
| {"DDDD"}, |
| {"FF"}, |
| {"FFF"}, |
| {"hhh"}, |
| {"HHH"}, |
| {"kkk"}, |
| {"KKK"}, |
| {"mmm"}, |
| {"sss"}, |
| {"OO"}, |
| {"OOO"}, |
| {"OOOOO"}, |
| {"XXXXXX"}, |
| {"zzzzz"}, |
| {"ZZZZZZ"}, |
| |
| {"RO"}, |
| |
| {"p"}, |
| {"pp"}, |
| {"p:"}, |
| |
| {"f"}, |
| {"ff"}, |
| {"f:"}, |
| {"fy"}, |
| {"fa"}, |
| {"fM"}, |
| |
| {"www"}, |
| {"WW"}, |
| }; |
| } |
| |
| @Test(dataProvider="invalidPatterns", expectedExceptions=IllegalArgumentException.class) |
| public void test_appendPattern_invalid(String input) throws Exception { |
| builder.appendPattern(input); // test is for error here |
| } |
| |
| //----------------------------------------------------------------------- |
| @DataProvider(name="patternPrint") |
| Object[][] data_patternPrint() { |
| return new Object[][] { |
| {"Q", date(2012, 2, 10), "1"}, |
| {"QQ", date(2012, 2, 10), "01"}, |
| {"QQQ", date(2012, 2, 10), "Q1"}, |
| {"QQQQ", date(2012, 2, 10), "1st quarter"}, |
| {"QQQQQ", date(2012, 2, 10), "1"}, |
| }; |
| } |
| |
| @Test(dataProvider="patternPrint") |
| public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { |
| DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); |
| String test = f.format(temporal); |
| assertEquals(test, expected); |
| } |
| |
| private static Temporal date(int y, int m, int d) { |
| return LocalDate.of(y, m, d); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test |
| public void test_adjacent_strict_firstFixedWidth() throws Exception { |
| // succeeds because both number elements are fixed width |
| DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("12309", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 5); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| } |
| |
| @Test |
| public void test_adjacent_strict_firstVariableWidth_success() throws Exception { |
| // succeeds greedily parsing variable width, then fixed width, to non-numeric Z |
| DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('Z').toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("12309Z", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 6); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 123L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 9L); |
| } |
| |
| @Test |
| public void test_adjacent_strict_firstVariableWidth_fails() throws Exception { |
| // fails because literal is a number and variable width parse greedily absorbs it |
| DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("12309", pp); |
| assertEquals(pp.getErrorIndex(), 5); |
| assertEquals(parsed, null); |
| } |
| |
| @Test |
| public void test_adjacent_lenient() throws Exception { |
| // succeeds because both number elements are fixed width even in lenient mode |
| DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("12309", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 5); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| } |
| |
| @Test |
| public void test_adjacent_lenient_firstVariableWidth_success() throws Exception { |
| // succeeds greedily parsing variable width, then fixed width, to non-numeric Z |
| DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('Z').toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("12309Z", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 6); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 123L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 9L); |
| } |
| |
| @Test |
| public void test_adjacent_lenient_firstVariableWidth_fails() throws Exception { |
| // fails because literal is a number and variable width parse greedily absorbs it |
| DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY).appendValue(MINUTE_OF_HOUR, 2).appendLiteral('9').toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("12309", pp); |
| assertEquals(pp.getErrorIndex(), 5); |
| assertEquals(parsed, null); |
| } |
| |
| //----------------------------------------------------------------------- |
| @Test |
| public void test_adjacent_strict_fractionFollows() throws Exception { |
| // succeeds because hour/min are fixed width |
| DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("1230567", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 7); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| assertEquals(parsed.getLong(NANO_OF_SECOND), 567_000_000L); |
| } |
| |
| @Test |
| public void test_adjacent_strict_fractionFollows_2digit() throws Exception { |
| // succeeds because hour/min are fixed width |
| DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("123056", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 6); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| assertEquals(parsed.getLong(NANO_OF_SECOND), 560_000_000L); |
| } |
| |
| @Test |
| public void test_adjacent_strict_fractionFollows_0digit() throws Exception { |
| // succeeds because hour/min are fixed width |
| DateTimeFormatter f = builder.appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 0, 3, false).toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("1230", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 4); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| } |
| |
| @Test |
| public void test_adjacent_lenient_fractionFollows() throws Exception { |
| // succeeds because hour/min are fixed width |
| DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("1230567", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 7); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| assertEquals(parsed.getLong(NANO_OF_SECOND), 567_000_000L); |
| } |
| |
| @Test |
| public void test_adjacent_lenient_fractionFollows_2digit() throws Exception { |
| // succeeds because hour/min are fixed width |
| DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("123056", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 6); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| assertEquals(parsed.getLong(NANO_OF_SECOND), 560_000_000L); |
| } |
| |
| @Test |
| public void test_adjacent_lenient_fractionFollows_0digit() throws Exception { |
| // succeeds because hour/min are fixed width |
| DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); |
| ParsePosition pp = new ParsePosition(0); |
| TemporalAccessor parsed = f.parseUnresolved("1230", pp); |
| assertEquals(pp.getErrorIndex(), -1); |
| assertEquals(pp.getIndex(), 4); |
| assertEquals(parsed.getLong(HOUR_OF_DAY), 12L); |
| assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); |
| } |
| |
| } |