blob: c5a017c911ebadc39bd5370c5215b25c85760879 [file] [log] [blame]
/*
* 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);
}
}