Split out tests for a Java 15 bug.
These tests fail on Java 15 due to a bug which was only fixed for Java 16. See https://bugs.openjdk.java.net/browse/JDK-8248434 See https://bugs.openjdk.java.net/browse/JDK-8248655
This commit is contained in:
parent
bcdff98f02
commit
7995aad79f
20
pom.xml
20
pom.xml
|
@ -941,6 +941,26 @@
|
||||||
<jacoco.skip>true</jacoco.skip>
|
<jacoco.skip>true</jacoco.skip>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>java15</id>
|
||||||
|
<activation>
|
||||||
|
<!-- This is ONLY activated for Java 15 -->
|
||||||
|
<jdk>15</jdk>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>org/apache/commons/lang3/time/Java15BugFastDateParserTest.java</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>benchmark</id>
|
<id>benchmark</id>
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.lang3.function;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a function that accepts three arguments and produces a result. This is the three-arity specialization of
|
||||||
|
* {@link Function}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This is a <a href="package-summary.html">functional interface</a> whose functional method is
|
||||||
|
* {@link #apply(Object, Object, Object)}.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the first argument to the function
|
||||||
|
* @param <U> the type of the second argument to the function
|
||||||
|
* @param <V> the type of the third argument to the function
|
||||||
|
* @param <R> the type of the result of the function
|
||||||
|
*
|
||||||
|
* @see Function
|
||||||
|
* @since 3.12.0
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface TriFunction<T, U, V, R> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies this function to the given arguments.
|
||||||
|
*
|
||||||
|
* @param t the first function argument
|
||||||
|
* @param u the second function argument
|
||||||
|
* @param v the third function argument
|
||||||
|
* @return the function result
|
||||||
|
*/
|
||||||
|
R apply(T t, U u, V v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a composed function that first applies this function to its input, and then applies the {@code after}
|
||||||
|
* function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
|
||||||
|
* composed function.
|
||||||
|
*
|
||||||
|
* @param <W> the type of output of the {@code after} function, and of the composed function
|
||||||
|
* @param after the function to apply after this function is applied
|
||||||
|
* @return a composed function that first applies this function and then applies the {@code after} function
|
||||||
|
* @throws NullPointerException if after is null
|
||||||
|
*/
|
||||||
|
default <W> TriFunction<T, U, V, W> andThen(Function<? super R, ? extends W> after) {
|
||||||
|
Objects.requireNonNull(after);
|
||||||
|
return (T t, U u, V v) -> after.apply(apply(t, u, v));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.apache.commons.lang3.time;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for the parse methods of FastDateFormat
|
|
||||||
*
|
|
||||||
* @since 3.2
|
|
||||||
*/
|
|
||||||
public class FastDateFormat_ParserTest extends FastDateParserTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DateParser getInstance(final String format, final TimeZone timeZone, final Locale locale) {
|
|
||||||
return FastDateFormat.getInstance(format, timeZone, locale);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,10 +34,15 @@
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.commons.lang3.LocaleUtils;
|
import org.apache.commons.lang3.LocaleUtils;
|
||||||
import org.apache.commons.lang3.SerializationUtils;
|
import org.apache.commons.lang3.SerializationUtils;
|
||||||
|
import org.apache.commons.lang3.function.TriFunction;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests {@link org.apache.commons.lang3.time.FastDateParser}.
|
* Unit tests {@link org.apache.commons.lang3.time.FastDateParser}.
|
||||||
|
@ -45,9 +50,9 @@
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public class FastDateParserTest {
|
public class FastDateParserTest {
|
||||||
|
|
||||||
private enum Expected1806 {
|
private enum Expected1806 {
|
||||||
India(INDIA, "+05", "+0530", "+05:30", true),
|
India(INDIA, "+05", "+0530", "+05:30", true), Greenwich(GMT, "Z", "Z", "Z", false),
|
||||||
Greenwich(GMT, "Z", "Z", "Z", false),
|
|
||||||
NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
|
NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
|
||||||
|
|
||||||
final TimeZone zone;
|
final TimeZone zone;
|
||||||
|
@ -56,33 +61,48 @@ private enum Expected1806 {
|
||||||
final String two;
|
final String two;
|
||||||
final String three;
|
final String three;
|
||||||
final long offset;
|
final long offset;
|
||||||
Expected1806(final TimeZone zone, final String one, final String two, final String three, final boolean hasHalfHourOffset) {
|
|
||||||
|
Expected1806(final TimeZone zone, final String one, final String two, final String three,
|
||||||
|
final boolean hasHalfHourOffset) {
|
||||||
this.zone = zone;
|
this.zone = zone;
|
||||||
this.one = one;
|
this.one = one;
|
||||||
this.two = two;
|
this.two = two;
|
||||||
this.three = three;
|
this.three = three;
|
||||||
this.offset = hasHalfHourOffset ?30*60*1000 :0;
|
this.offset = hasHalfHourOffset ? 30 * 60 * 1000 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static final String SHORT_FORMAT_NOERA = "y/M/d/h/a/m/s/E";
|
|
||||||
private static final String LONG_FORMAT_NOERA = "yyyy/MMMM/dddd/hhhh/mmmm/ss/aaaa/EEEE";
|
|
||||||
private static final String SHORT_FORMAT = "G/" + SHORT_FORMAT_NOERA;
|
|
||||||
|
|
||||||
private static final String LONG_FORMAT = "GGGG/" + LONG_FORMAT_NOERA;
|
static final String DATE_PARSER_PARAMETERS = "dateParserParameters";
|
||||||
|
|
||||||
|
static final String SHORT_FORMAT_NOERA = "y/M/d/h/a/m/s/E";
|
||||||
|
|
||||||
|
static final String LONG_FORMAT_NOERA = "yyyy/MMMM/dddd/hhhh/mmmm/ss/aaaa/EEEE";
|
||||||
|
static final String SHORT_FORMAT = "G/" + SHORT_FORMAT_NOERA;
|
||||||
|
static final String LONG_FORMAT = "GGGG/" + LONG_FORMAT_NOERA;
|
||||||
|
|
||||||
private static final String yMdHmsSZ = "yyyy-MM-dd'T'HH:mm:ss.SSS Z";
|
private static final String yMdHmsSZ = "yyyy-MM-dd'T'HH:mm:ss.SSS Z";
|
||||||
private static final String DMY_DOT = "dd.MM.yyyy";
|
private static final String DMY_DOT = "dd.MM.yyyy";
|
||||||
private static final String YMD_SLASH = "yyyy/MM/dd";
|
private static final String YMD_SLASH = "yyyy/MM/dd";
|
||||||
private static final String MDY_DASH = "MM-DD-yyyy";
|
private static final String MDY_DASH = "MM-DD-yyyy";
|
||||||
|
|
||||||
private static final String MDY_SLASH = "MM/DD/yyyy";
|
private static final String MDY_SLASH = "MM/DD/yyyy";
|
||||||
|
|
||||||
private static final TimeZone REYKJAVIK = TimeZone.getTimeZone("Atlantic/Reykjavik");
|
private static final TimeZone REYKJAVIK = TimeZone.getTimeZone("Atlantic/Reykjavik");
|
||||||
private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York");
|
private static final TimeZone NEW_YORK = TimeZone.getTimeZone("America/New_York");
|
||||||
private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
|
static final TimeZone GMT = TimeZone.getTimeZone("GMT");
|
||||||
|
|
||||||
private static final TimeZone INDIA = TimeZone.getTimeZone("Asia/Calcutta");
|
private static final TimeZone INDIA = TimeZone.getTimeZone("Asia/Calcutta");
|
||||||
|
|
||||||
private static final Locale SWEDEN = new Locale("sv", "SE");
|
private static final Locale SWEDEN = new Locale("sv", "SE");
|
||||||
|
|
||||||
|
static Stream<Arguments> dateParserParameters() {
|
||||||
|
return Stream.of(
|
||||||
|
// @formatter:off
|
||||||
|
Arguments.of((TriFunction<String, TimeZone, Locale, DateParser>) (format, timeZone, locale)
|
||||||
|
-> new FastDateParser(format, timeZone, locale, null)),
|
||||||
|
Arguments.of((TriFunction<String, TimeZone, Locale, DateParser>) FastDateFormat::getInstance)
|
||||||
|
// @formatter:on
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private static Calendar initializeCalendar(final TimeZone tz) {
|
private static Calendar initializeCalendar(final TimeZone tz) {
|
||||||
final Calendar cal = Calendar.getInstance(tz);
|
final Calendar cal = Calendar.getInstance(tz);
|
||||||
cal.set(Calendar.YEAR, 2001);
|
cal.set(Calendar.YEAR, 2001);
|
||||||
|
@ -95,25 +115,30 @@ private static Calendar initializeCalendar(final TimeZone tz) {
|
||||||
return cal;
|
return cal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkParse(final Locale locale, final Calendar cal, final SimpleDateFormat sdf, final DateParser fdf) throws ParseException {
|
private final TriFunction<String, TimeZone, Locale, DateParser> dateParserProvider = (format, timeZone,
|
||||||
final String formattedDate= sdf.format(cal.getTime());
|
locale) -> new FastDateParser(format, timeZone, locale, null);
|
||||||
|
|
||||||
|
static void checkParse(final Locale locale, final Calendar cal, final SimpleDateFormat sdf, final DateParser fdf) {
|
||||||
|
final String formattedDate = sdf.format(cal.getTime());
|
||||||
checkParse(locale, sdf, fdf, formattedDate);
|
checkParse(locale, sdf, fdf, formattedDate);
|
||||||
checkParse(locale, sdf, fdf, formattedDate.toLowerCase(locale));
|
checkParse(locale, sdf, fdf, formattedDate.toLowerCase(locale));
|
||||||
checkParse(locale, sdf, fdf, formattedDate.toUpperCase(locale));
|
checkParse(locale, sdf, fdf, formattedDate.toUpperCase(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkParse(final Locale locale, final SimpleDateFormat sdf, final DateParser fdf, final String formattedDate) throws ParseException {
|
static void checkParse(final Locale locale, final SimpleDateFormat sdf, final DateParser fdf,
|
||||||
|
final String formattedDate) {
|
||||||
try {
|
try {
|
||||||
final Date expectedTime = sdf.parse(formattedDate);
|
final Date expectedTime = sdf.parse(formattedDate);
|
||||||
final Date actualTime = fdf.parse(formattedDate);
|
final Date actualTime = fdf.parse(formattedDate);
|
||||||
assertEquals(expectedTime, actualTime, "locale : " + locale + " formattedDate : " + formattedDate + "\n");
|
assertEquals(expectedTime, actualTime, "locale : " + locale + " formattedDate : " + formattedDate + "\n");
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
fail("locale : " + locale + " formattedDate : " + formattedDate + " error : " + e + "\n", e);
|
fail("locale : " + locale + " formattedDate : " + formattedDate + " error : " + e + "\n", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateParser getDateInstance(final int dateStyle, final Locale locale) {
|
private DateParser getDateInstance(final int dateStyle, final Locale locale) {
|
||||||
return getInstance(FormatCache.getPatternForStyle(Integer.valueOf(dateStyle), null, locale), TimeZone.getDefault(), Locale.getDefault());
|
return getInstance(null, FormatCache.getPatternForStyle(Integer.valueOf(dateStyle), null, locale),
|
||||||
|
TimeZone.getDefault(), Locale.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Calendar getEraStart(int year, final TimeZone zone, final Locale locale) {
|
private Calendar getEraStart(int year, final TimeZone zone, final Locale locale) {
|
||||||
|
@ -124,91 +149,68 @@ private Calendar getEraStart(int year, final TimeZone zone, final Locale locale)
|
||||||
if (locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
|
if (locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
|
||||||
if (year < 1868) {
|
if (year < 1868) {
|
||||||
cal.set(Calendar.ERA, 0);
|
cal.set(Calendar.ERA, 0);
|
||||||
cal.set(Calendar.YEAR, 1868-year);
|
cal.set(Calendar.YEAR, 1868 - year);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (year < 0) {
|
if (year < 0) {
|
||||||
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
||||||
year= -year;
|
year = -year;
|
||||||
}
|
}
|
||||||
cal.set(Calendar.YEAR, year/100 * 100);
|
cal.set(Calendar.YEAR, year / 100 * 100);
|
||||||
}
|
}
|
||||||
return cal;
|
return cal;
|
||||||
}
|
}
|
||||||
|
|
||||||
DateParser getInstance(final String format) {
|
DateParser getInstance(final String format) {
|
||||||
return getInstance(format, TimeZone.getDefault(), Locale.getDefault());
|
return getInstance(null, format, TimeZone.getDefault(), Locale.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateParser getInstance(final String format, final Locale locale) {
|
DateParser getInstance(final String format, final Locale locale) {
|
||||||
return getInstance(format, TimeZone.getDefault(), locale);
|
return getInstance(null, format, TimeZone.getDefault(), locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateParser getInstance(final String format, final TimeZone timeZone) {
|
private DateParser getInstance(final String format, final TimeZone timeZone) {
|
||||||
return getInstance(format, timeZone, Locale.getDefault());
|
return getInstance(null, format, timeZone, Locale.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this method in derived tests to change the construction of instances
|
* Override this method in derived tests to change the construction of instances
|
||||||
*
|
*
|
||||||
|
* @param dpProvider TODO
|
||||||
* @param format the format string to use
|
* @param format the format string to use
|
||||||
* @param timeZone the time zone to use
|
* @param timeZone the time zone to use
|
||||||
* @param locale the locale to use
|
* @param locale the locale to use
|
||||||
*
|
*
|
||||||
* @return the DateParser instance to use for testing
|
* @return the DateParser instance to use for testing
|
||||||
*/
|
*/
|
||||||
protected DateParser getInstance(final String format, final TimeZone timeZone, final Locale locale) {
|
protected DateParser getInstance(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider,
|
||||||
return new FastDateParser(format, timeZone, locale, null);
|
final String format, final TimeZone timeZone, final Locale locale) {
|
||||||
|
return (dpProvider == null ? this.dateParserProvider : dpProvider).apply(format, timeZone, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void java15BuggyLocaleTest() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
final String buggyLocaleName = "ff_LR_#Adlm";
|
public void test_Equality_Hash(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) {
|
||||||
Locale buggyLocale = null;
|
final DateParser[] parsers = {getInstance(dpProvider, yMdHmsSZ, NEW_YORK, Locale.US),
|
||||||
for (final Locale locale : Locale.getAvailableLocales()) {
|
getInstance(dpProvider, DMY_DOT, NEW_YORK, Locale.US),
|
||||||
if (buggyLocaleName.equals(locale.toString())) {
|
getInstance(dpProvider, YMD_SLASH, NEW_YORK, Locale.US),
|
||||||
buggyLocale = locale;
|
getInstance(dpProvider, MDY_DASH, NEW_YORK, Locale.US),
|
||||||
break;
|
getInstance(dpProvider, MDY_SLASH, NEW_YORK, Locale.US),
|
||||||
}
|
getInstance(dpProvider, MDY_SLASH, REYKJAVIK, Locale.US),
|
||||||
}
|
getInstance(dpProvider, MDY_SLASH, REYKJAVIK, SWEDEN)};
|
||||||
if (buggyLocale == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
testSingleLocale(buggyLocale);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
final Map<DateParser, Integer> map = new HashMap<>();
|
||||||
public void java15BuggyLocaleTestAll() throws ParseException {
|
int i = 0;
|
||||||
for (final Locale locale : Locale.getAvailableLocales()) {
|
for (final DateParser parser : parsers) {
|
||||||
testSingleLocale(locale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test_Equality_Hash() {
|
|
||||||
final DateParser[] parsers= {
|
|
||||||
getInstance(yMdHmsSZ, NEW_YORK, Locale.US),
|
|
||||||
getInstance(DMY_DOT, NEW_YORK, Locale.US),
|
|
||||||
getInstance(YMD_SLASH, NEW_YORK, Locale.US),
|
|
||||||
getInstance(MDY_DASH, NEW_YORK, Locale.US),
|
|
||||||
getInstance(MDY_SLASH, NEW_YORK, Locale.US),
|
|
||||||
getInstance(MDY_SLASH, REYKJAVIK, Locale.US),
|
|
||||||
getInstance(MDY_SLASH, REYKJAVIK, SWEDEN)
|
|
||||||
};
|
|
||||||
|
|
||||||
final Map<DateParser, Integer> map= new HashMap<>();
|
|
||||||
int i= 0;
|
|
||||||
for (final DateParser parser:parsers) {
|
|
||||||
map.put(parser, Integer.valueOf(i++));
|
map.put(parser, Integer.valueOf(i++));
|
||||||
}
|
}
|
||||||
|
|
||||||
i= 0;
|
i = 0;
|
||||||
for (final DateParser parser:parsers) {
|
for (final DateParser parser : parsers) {
|
||||||
assertEquals(i++, map.get(parser).intValue());
|
assertEquals(i++, map.get(parser).intValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test1806() throws ParseException {
|
public void test1806() throws ParseException {
|
||||||
final String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
|
final String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
|
||||||
|
@ -217,16 +219,17 @@ public void test1806() throws ParseException {
|
||||||
for (final Expected1806 trial : Expected1806.values()) {
|
for (final Expected1806 trial : Expected1806.values()) {
|
||||||
final Calendar cal = initializeCalendar(trial.zone);
|
final Calendar cal = initializeCalendar(trial.zone);
|
||||||
|
|
||||||
final String message = trial.zone.getDisplayName()+";";
|
final String message = trial.zone.getDisplayName() + ";";
|
||||||
|
|
||||||
DateParser parser = getInstance(formatStub+"X", trial.zone);
|
DateParser parser = getInstance(formatStub + "X", trial.zone);
|
||||||
assertEquals(cal.getTime().getTime(), parser.parse(dateStub+trial.one).getTime()-trial.offset, message+trial.one);
|
assertEquals(cal.getTime().getTime(), parser.parse(dateStub + trial.one).getTime() - trial.offset,
|
||||||
|
message + trial.one);
|
||||||
|
|
||||||
parser = getInstance(formatStub+"XX", trial.zone);
|
parser = getInstance(formatStub + "XX", trial.zone);
|
||||||
assertEquals(cal.getTime(), parser.parse(dateStub+trial.two), message+trial.two);
|
assertEquals(cal.getTime(), parser.parse(dateStub + trial.two), message + trial.two);
|
||||||
|
|
||||||
parser = getInstance(formatStub+"XXX", trial.zone);
|
parser = getInstance(formatStub + "XXX", trial.zone);
|
||||||
assertEquals(cal.getTime(), parser.parse(dateStub+trial.three), message+trial.three);
|
assertEquals(cal.getTime(), parser.parse(dateStub + trial.three), message + trial.three);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,15 +238,16 @@ public void test1806Argument() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> getInstance("XXXX"));
|
assertThrows(IllegalArgumentException.class, () -> getInstance("XXXX"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testAmPm() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
|
public void testAmPm(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws ParseException {
|
||||||
|
final Calendar cal = Calendar.getInstance(NEW_YORK, Locale.US);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
|
|
||||||
final DateParser h = getInstance("yyyy-MM-dd hh a mm:ss", NEW_YORK, Locale.US);
|
final DateParser h = getInstance(dpProvider, "yyyy-MM-dd hh a mm:ss", NEW_YORK, Locale.US);
|
||||||
final DateParser K = getInstance("yyyy-MM-dd KK a mm:ss", NEW_YORK, Locale.US);
|
final DateParser K = getInstance(dpProvider, "yyyy-MM-dd KK a mm:ss", NEW_YORK, Locale.US);
|
||||||
final DateParser k = getInstance("yyyy-MM-dd kk:mm:ss", NEW_YORK, Locale.US);
|
final DateParser k = getInstance(dpProvider, "yyyy-MM-dd kk:mm:ss", NEW_YORK, Locale.US);
|
||||||
final DateParser H = getInstance("yyyy-MM-dd HH:mm:ss", NEW_YORK, Locale.US);
|
final DateParser H = getInstance(dpProvider, "yyyy-MM-dd HH:mm:ss", NEW_YORK, Locale.US);
|
||||||
|
|
||||||
cal.set(2010, Calendar.AUGUST, 1, 0, 33, 20);
|
cal.set(2010, Calendar.AUGUST, 1, 0, 33, 20);
|
||||||
assertEquals(cal.getTime(), h.parse("2010-08-01 12 AM 33:20"));
|
assertEquals(cal.getTime(), h.parse("2010-08-01 12 AM 33:20"));
|
||||||
|
@ -285,20 +289,21 @@ public void testDayNumberOfWeek() throws ParseException {
|
||||||
assertEquals(Calendar.SUNDAY, calendar.get(Calendar.DAY_OF_WEEK));
|
assertEquals(Calendar.SUNDAY, calendar.get(Calendar.DAY_OF_WEEK));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testDayOf() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
|
public void testDayOf(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws ParseException {
|
||||||
|
final Calendar cal = Calendar.getInstance(NEW_YORK, Locale.US);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(2003, Calendar.FEBRUARY, 10);
|
cal.set(2003, Calendar.FEBRUARY, 10);
|
||||||
|
|
||||||
final DateParser fdf = getInstance("W w F D y", NEW_YORK, Locale.US);
|
final DateParser fdf = getInstance(dpProvider, "W w F D y", NEW_YORK, Locale.US);
|
||||||
assertEquals(cal.getTime(), fdf.parse("3 7 2 41 03"));
|
assertEquals(cal.getTime(), fdf.parse("3 7 2 41 03"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquals() {
|
public void testEquals() {
|
||||||
final DateParser parser1= getInstance(YMD_SLASH);
|
final DateParser parser1 = getInstance(YMD_SLASH);
|
||||||
final DateParser parser2= getInstance(YMD_SLASH);
|
final DateParser parser2 = getInstance(YMD_SLASH);
|
||||||
|
|
||||||
assertEquals(parser1, parser2);
|
assertEquals(parser1, parser2);
|
||||||
assertEquals(parser1.hashCode(), parser2.hashCode());
|
assertEquals(parser1.hashCode(), parser2.hashCode());
|
||||||
|
@ -306,10 +311,13 @@ public void testEquals() {
|
||||||
assertNotEquals(parser1, new Object());
|
assertNotEquals(parser1, new Object());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testJpLocales() throws ParseException {
|
public void testJpLocales() throws ParseException {
|
||||||
|
|
||||||
final Calendar cal= Calendar.getInstance(GMT);
|
final Calendar cal = Calendar.getInstance(GMT);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(2003, Calendar.FEBRUARY, 10);
|
cal.set(2003, Calendar.FEBRUARY, 10);
|
||||||
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
||||||
|
@ -324,21 +332,24 @@ public void testJpLocales() throws ParseException {
|
||||||
checkParse(locale, cal, sdf, fdf);
|
checkParse(locale, cal, sdf, fdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testLANG_831() throws Exception {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
testSdfAndFdp("M E", "3 Tue", true);
|
public void testLANG_831(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws Exception {
|
||||||
|
testSdfAndFdp(dpProvider, "M E", "3 Tue", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testLANG_832() throws Exception {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
testSdfAndFdp("'d'd", "d3", false); // OK
|
public void testLANG_832(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws Exception {
|
||||||
testSdfAndFdp("'d'd'", "d3", true); // should fail (unterminated quote)
|
testSdfAndFdp(dpProvider, "'d'd", "d3", false); // OK
|
||||||
|
testSdfAndFdp(dpProvider, "'d'd'", "d3", true); // should fail (unterminated quote)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testLang1121() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLang1121(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws ParseException {
|
||||||
final TimeZone kst = TimeZone.getTimeZone("KST");
|
final TimeZone kst = TimeZone.getTimeZone("KST");
|
||||||
final DateParser fdp = getInstance("yyyyMMdd", kst, Locale.KOREA);
|
final DateParser fdp = getInstance(dpProvider, "yyyyMMdd", kst, Locale.KOREA);
|
||||||
|
|
||||||
assertThrows(ParseException.class, () -> fdp.parse("2015"));
|
assertThrows(ParseException.class, () -> fdp.parse("2015"));
|
||||||
|
|
||||||
|
@ -359,13 +370,14 @@ public void testLang1121() throws ParseException {
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testLang1380() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLang1380(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws ParseException {
|
||||||
final Calendar expected = Calendar.getInstance(GMT, Locale.FRANCE);
|
final Calendar expected = Calendar.getInstance(GMT, Locale.FRANCE);
|
||||||
expected.clear();
|
expected.clear();
|
||||||
expected.set(2014, Calendar.APRIL, 14);
|
expected.set(2014, Calendar.APRIL, 14);
|
||||||
|
|
||||||
final DateParser fdp = getInstance("dd MMM yyyy", GMT, Locale.FRANCE);
|
final DateParser fdp = getInstance(dpProvider, "dd MMM yyyy", GMT, Locale.FRANCE);
|
||||||
assertEquals(expected.getTime(), fdp.parse("14 avril 2014"));
|
assertEquals(expected.getTime(), fdp.parse("14 avril 2014"));
|
||||||
assertEquals(expected.getTime(), fdp.parse("14 avr. 2014"));
|
assertEquals(expected.getTime(), fdp.parse("14 avr. 2014"));
|
||||||
assertEquals(expected.getTime(), fdp.parse("14 avr 2014"));
|
assertEquals(expected.getTime(), fdp.parse("14 avr 2014"));
|
||||||
|
@ -394,13 +406,14 @@ public void testLang538() throws ParseException {
|
||||||
assertEquals(cal.getTime(), parser.parse("2009-10-16T16:42:16.000Z"));
|
assertEquals(cal.getTime(), parser.parse("2009-10-16T16:42:16.000Z"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testLang996() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLang996(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws ParseException {
|
||||||
final Calendar expected = Calendar.getInstance(NEW_YORK, Locale.US);
|
final Calendar expected = Calendar.getInstance(NEW_YORK, Locale.US);
|
||||||
expected.clear();
|
expected.clear();
|
||||||
expected.set(2014, Calendar.MAY, 14);
|
expected.set(2014, Calendar.MAY, 14);
|
||||||
|
|
||||||
final DateParser fdp = getInstance("ddMMMyyyy", NEW_YORK, Locale.US);
|
final DateParser fdp = getInstance(dpProvider, "ddMMMyyyy", NEW_YORK, Locale.US);
|
||||||
assertEquals(expected.getTime(), fdp.parse("14may2014"));
|
assertEquals(expected.getTime(), fdp.parse("14may2014"));
|
||||||
assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
|
assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
|
||||||
assertEquals(expected.getTime(), fdp.parse("14May2014"));
|
assertEquals(expected.getTime(), fdp.parse("14May2014"));
|
||||||
|
@ -408,74 +421,13 @@ public void testLang996() throws ParseException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocaleMatches() {
|
public void testLocaleMatches() {
|
||||||
final DateParser parser= getInstance(yMdHmsSZ, SWEDEN);
|
final DateParser parser = getInstance(yMdHmsSZ, SWEDEN);
|
||||||
assertEquals(SWEDEN, parser.getLocale());
|
assertEquals(SWEDEN, parser.getLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testLocales(final String format, final boolean eraBC) throws Exception {
|
|
||||||
|
|
||||||
final Calendar cal= Calendar.getInstance(GMT);
|
|
||||||
cal.clear();
|
|
||||||
cal.set(2003, Calendar.FEBRUARY, 10);
|
|
||||||
if (eraBC) {
|
|
||||||
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final Locale locale : Locale.getAvailableLocales() ) {
|
|
||||||
// ja_JP_JP cannot handle dates before 1868 properly
|
|
||||||
if (eraBC && locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
|
|
||||||
final DateParser fdf = getInstance(format, locale);
|
|
||||||
|
|
||||||
// If parsing fails, a ParseException will be thrown and the test will fail
|
|
||||||
checkParse(locale, cal, sdf, fdf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_Long_AD() throws Exception {
|
|
||||||
testLocales(LONG_FORMAT, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_Long_BC() throws Exception {
|
|
||||||
testLocales(LONG_FORMAT, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_LongNoEra_AD() throws Exception {
|
|
||||||
testLocales(LONG_FORMAT_NOERA, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_LongNoEra_BC() throws Exception {
|
|
||||||
testLocales(LONG_FORMAT_NOERA, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_Short_AD() throws Exception {
|
|
||||||
testLocales(SHORT_FORMAT, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_Short_BC() throws Exception {
|
|
||||||
testLocales(SHORT_FORMAT, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_ShortNoEra_AD() throws Exception {
|
|
||||||
testLocales(SHORT_FORMAT_NOERA, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocales_ShortNoEra_BC() throws Exception {
|
|
||||||
testLocales(SHORT_FORMAT_NOERA, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that pre-1000AD years get padded with yyyy
|
* Tests that pre-1000AD years get padded with yyyy
|
||||||
|
*
|
||||||
* @throws ParseException so we don't have to catch it
|
* @throws ParseException so we don't have to catch it
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@ -504,37 +456,42 @@ public void testMilleniumBug() throws ParseException {
|
||||||
assertEquals(cal.getTime(), parser.parse("01.01.1000"));
|
assertEquals(cal.getTime(), parser.parse("01.01.1000"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testParseLongShort() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
|
public void testParseLongShort(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws ParseException {
|
||||||
|
final Calendar cal = Calendar.getInstance(NEW_YORK, Locale.US);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
|
cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
|
||||||
cal.set(Calendar.MILLISECOND, 989);
|
cal.set(Calendar.MILLISECOND, 989);
|
||||||
cal.setTimeZone(NEW_YORK);
|
cal.setTimeZone(NEW_YORK);
|
||||||
|
|
||||||
DateParser fdf = getInstance("yyyy GGGG MMMM dddd aaaa EEEE HHHH mmmm ssss SSSS ZZZZ", NEW_YORK, Locale.US);
|
DateParser fdf = getInstance(dpProvider, "yyyy GGGG MMMM dddd aaaa EEEE HHHH mmmm ssss SSSS ZZZZ", NEW_YORK,
|
||||||
|
Locale.US);
|
||||||
|
|
||||||
assertEquals(cal.getTime(), fdf.parse("2003 AD February 0010 PM Monday 0015 0033 0020 0989 GMT-05:00"));
|
assertEquals(cal.getTime(), fdf.parse("2003 AD February 0010 PM Monday 0015 0033 0020 0989 GMT-05:00"));
|
||||||
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
||||||
|
|
||||||
final Date parse = fdf.parse("2003 BC February 0010 PM Saturday 0015 0033 0020 0989 GMT-05:00");
|
final Date parse = fdf.parse("2003 BC February 0010 PM Saturday 0015 0033 0020 0989 GMT-05:00");
|
||||||
assertEquals(cal.getTime(), parse);
|
assertEquals(cal.getTime(), parse);
|
||||||
|
|
||||||
fdf = getInstance("y G M d a E H m s S Z", NEW_YORK, Locale.US);
|
fdf = getInstance(null, "y G M d a E H m s S Z", NEW_YORK, Locale.US);
|
||||||
assertEquals(cal.getTime(), fdf.parse("03 BC 2 10 PM Sat 15 33 20 989 -0500"));
|
assertEquals(cal.getTime(), fdf.parse("03 BC 2 10 PM Sat 15 33 20 989 -0500"));
|
||||||
|
|
||||||
cal.set(Calendar.ERA, GregorianCalendar.AD);
|
cal.set(Calendar.ERA, GregorianCalendar.AD);
|
||||||
assertEquals(cal.getTime(), fdf.parse("03 AD 2 10 PM Saturday 15 33 20 989 -0500"));
|
assertEquals(cal.getTime(), fdf.parse("03 AD 2 10 PM Saturday 15 33 20 989 -0500"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testParseNumerics() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
|
public void testParseNumerics(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws ParseException {
|
||||||
|
final Calendar cal = Calendar.getInstance(NEW_YORK, Locale.US);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
|
cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
|
||||||
cal.set(Calendar.MILLISECOND, 989);
|
cal.set(Calendar.MILLISECOND, 989);
|
||||||
|
|
||||||
final DateParser fdf = getInstance("yyyyMMddHHmmssSSS", NEW_YORK, Locale.US);
|
final DateParser fdf = getInstance(dpProvider, "yyyyMMddHHmmssSSS", NEW_YORK, Locale.US);
|
||||||
assertEquals(cal.getTime(), fdf.parse("20030210153320989"));
|
assertEquals(cal.getTime(), fdf.parse("20030210153320989"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,18 +509,18 @@ public void testParseOffset() {
|
||||||
@Test
|
@Test
|
||||||
// Check that all Locales can parse the formats we use
|
// Check that all Locales can parse the formats we use
|
||||||
public void testParses() throws Exception {
|
public void testParses() throws Exception {
|
||||||
for (final String format : new String[]{LONG_FORMAT, SHORT_FORMAT}) {
|
for (final String format : new String[] {LONG_FORMAT, SHORT_FORMAT}) {
|
||||||
for (final Locale locale : Locale.getAvailableLocales()) {
|
for (final Locale locale : Locale.getAvailableLocales()) {
|
||||||
for (final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK, GMT}) {
|
for (final TimeZone tz : new TimeZone[] {NEW_YORK, REYKJAVIK, GMT}) {
|
||||||
for (final int year : new int[]{2003, 1940, 1868, 1867, 1, -1, -1940}) {
|
for (final int year : new int[] {2003, 1940, 1868, 1867, 1, -1, -1940}) {
|
||||||
final Calendar cal= getEraStart(year, tz, locale);
|
final Calendar cal = getEraStart(year, tz, locale);
|
||||||
final Date centuryStart= cal.getTime();
|
final Date centuryStart = cal.getTime();
|
||||||
|
|
||||||
cal.set(Calendar.MONTH, 1);
|
cal.set(Calendar.MONTH, 1);
|
||||||
cal.set(Calendar.DAY_OF_MONTH, 10);
|
cal.set(Calendar.DAY_OF_MONTH, 10);
|
||||||
final Date in= cal.getTime();
|
final Date in = cal.getTime();
|
||||||
|
|
||||||
final FastDateParser fdp= new FastDateParser(format, tz, locale, centuryStart);
|
final FastDateParser fdp = new FastDateParser(format, tz, locale, centuryStart);
|
||||||
validateSdfFormatFdpParseEquality(format, locale, tz, fdp, in, year, centuryStart);
|
validateSdfFormatFdpParseEquality(format, locale, tz, fdp, in, year, centuryStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,13 +528,15 @@ public void testParses() throws Exception {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testParseZone() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
|
public void testParseZone(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws ParseException {
|
||||||
|
final Calendar cal = Calendar.getInstance(NEW_YORK, Locale.US);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(2003, Calendar.JULY, 10, 16, 33, 20);
|
cal.set(2003, Calendar.JULY, 10, 16, 33, 20);
|
||||||
|
|
||||||
final DateParser fdf = getInstance(yMdHmsSZ, NEW_YORK, Locale.US);
|
final DateParser fdf = getInstance(dpProvider, yMdHmsSZ, NEW_YORK, Locale.US);
|
||||||
|
|
||||||
assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 -0500"));
|
assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 -0500"));
|
||||||
assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 GMT-05:00"));
|
assertEquals(cal.getTime(), fdf.parse("2003-07-10T15:33:20.000 GMT-05:00"));
|
||||||
|
@ -597,23 +556,24 @@ public void testParseZone() throws ParseException {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPatternMatches() {
|
public void testPatternMatches() {
|
||||||
final DateParser parser= getInstance(yMdHmsSZ);
|
final DateParser parser = getInstance(yMdHmsSZ);
|
||||||
assertEquals(yMdHmsSZ, parser.getPattern());
|
assertEquals(yMdHmsSZ, parser.getPattern());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testQuotes() throws ParseException {
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
|
public void testQuotes(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider) throws ParseException {
|
||||||
|
final Calendar cal = Calendar.getInstance(NEW_YORK, Locale.US);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
|
cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
|
||||||
cal.set(Calendar.MILLISECOND, 989);
|
cal.set(Calendar.MILLISECOND, 989);
|
||||||
|
|
||||||
final DateParser fdf = getInstance("''yyyyMMdd'A''B'HHmmssSSS''", NEW_YORK, Locale.US);
|
final DateParser fdf = getInstance(dpProvider, "''yyyyMMdd'A''B'HHmmssSSS''", NEW_YORK, Locale.US);
|
||||||
assertEquals(cal.getTime(), fdf.parse("'20030210A'B153320989'"));
|
assertEquals(cal.getTime(), fdf.parse("'20030210A'B153320989'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testSdfAndFdp(final String format, final String date, final boolean shouldFail)
|
private void testSdfAndFdp(final TriFunction<String, TimeZone, Locale, DateParser> dbProvider, final String format,
|
||||||
throws Exception {
|
final String date, final boolean shouldFail) throws Exception {
|
||||||
Date dfdp = null;
|
Date dfdp = null;
|
||||||
Date dsdf = null;
|
Date dsdf = null;
|
||||||
Throwable f = null;
|
Throwable f = null;
|
||||||
|
@ -623,7 +583,7 @@ private void testSdfAndFdp(final String format, final String date, final boolean
|
||||||
final SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
|
final SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
|
||||||
sdf.setTimeZone(NEW_YORK);
|
sdf.setTimeZone(NEW_YORK);
|
||||||
dsdf = sdf.parse(date);
|
dsdf = sdf.parse(date);
|
||||||
assertFalse(shouldFail, "Expected SDF failure, but got " + dsdf + " for ["+format+", "+date+"]");
|
assertFalse(shouldFail, "Expected SDF failure, but got " + dsdf + " for [" + format + ", " + date + "]");
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
s = e;
|
s = e;
|
||||||
if (!shouldFail) {
|
if (!shouldFail) {
|
||||||
|
@ -632,9 +592,9 @@ private void testSdfAndFdp(final String format, final String date, final boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final DateParser fdp = getInstance(format, NEW_YORK, Locale.US);
|
final DateParser fdp = getInstance(dbProvider, format, NEW_YORK, Locale.US);
|
||||||
dfdp = fdp.parse(date);
|
dfdp = fdp.parse(date);
|
||||||
assertFalse(shouldFail, "Expected FDF failure, but got " + dfdp + " for ["+format+", "+date+"]");
|
assertFalse(shouldFail, "Expected FDF failure, but got " + dfdp + " for [" + format + ", " + date + "]");
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
f = e;
|
f = e;
|
||||||
if (!shouldFail) {
|
if (!shouldFail) {
|
||||||
|
@ -648,6 +608,7 @@ private void testSdfAndFdp(final String format, final String date, final boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test case for {@link FastDateParser#FastDateParser(String, TimeZone, Locale)}.
|
* Test case for {@link FastDateParser#FastDateParser(String, TimeZone, Locale)}.
|
||||||
|
*
|
||||||
* @throws ParseException so we don't have to catch it
|
* @throws ParseException so we don't have to catch it
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@ -663,44 +624,35 @@ public void testShortDateStyleWithLocales() throws ParseException {
|
||||||
assertEquals(cal.getTime(), fdf.parse("2004-02-03"));
|
assertEquals(cal.getTime(), fdf.parse("2004-02-03"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testSingleLocale(final Locale locale) throws ParseException {
|
@ParameterizedTest
|
||||||
final Calendar cal = Calendar.getInstance(GMT);
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
cal.clear();
|
public void testSpecialCharacters(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
cal.set(2003, Calendar.FEBRUARY, 10);
|
throws Exception {
|
||||||
final SimpleDateFormat sdf = new SimpleDateFormat(LONG_FORMAT, locale);
|
testSdfAndFdp(dpProvider, "q", "", true); // bad pattern character (at present)
|
||||||
final String formattedDate = sdf.format(cal.getTime());
|
testSdfAndFdp(dpProvider, "Q", "", true); // bad pattern character
|
||||||
sdf.parse(formattedDate);
|
testSdfAndFdp(dpProvider, "$", "$", false); // OK
|
||||||
sdf.parse(formattedDate.toUpperCase(locale));
|
testSdfAndFdp(dpProvider, "?.d", "?.12", false); // OK
|
||||||
sdf.parse(formattedDate.toLowerCase(locale));
|
testSdfAndFdp(dpProvider, "''yyyyMMdd'A''B'HHmmssSSS''", "'20030210A'B153320989'", false); // OK
|
||||||
}
|
testSdfAndFdp(dpProvider, "''''yyyyMMdd'A''B'HHmmssSSS''", "''20030210A'B153320989'", false); // OK
|
||||||
|
testSdfAndFdp(dpProvider, "'$\\Ed'", "$\\Ed", false); // OK
|
||||||
@Test
|
|
||||||
public void testSpecialCharacters() throws Exception {
|
|
||||||
testSdfAndFdp("q", "", true); // bad pattern character (at present)
|
|
||||||
testSdfAndFdp("Q", "", true); // bad pattern character
|
|
||||||
testSdfAndFdp("$", "$", false); // OK
|
|
||||||
testSdfAndFdp("?.d", "?.12", false); // OK
|
|
||||||
testSdfAndFdp("''yyyyMMdd'A''B'HHmmssSSS''", "'20030210A'B153320989'", false); // OK
|
|
||||||
testSdfAndFdp("''''yyyyMMdd'A''B'HHmmssSSS''", "''20030210A'B153320989'", false); // OK
|
|
||||||
testSdfAndFdp("'$\\Ed'", "$\\Ed", false); // OK
|
|
||||||
|
|
||||||
// quoted charaters are case sensitive
|
// quoted charaters are case sensitive
|
||||||
testSdfAndFdp("'QED'", "QED", false);
|
testSdfAndFdp(dpProvider, "'QED'", "QED", false);
|
||||||
testSdfAndFdp("'QED'", "qed", true);
|
testSdfAndFdp(dpProvider, "'QED'", "qed", true);
|
||||||
// case sensitive after insensitive Month field
|
// case sensitive after insensitive Month field
|
||||||
testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 QED", false);
|
testSdfAndFdp(dpProvider, "yyyy-MM-dd 'QED'", "2003-02-10 QED", false);
|
||||||
testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 qed", true);
|
testSdfAndFdp(dpProvider, "yyyy-MM-dd 'QED'", "2003-02-10 qed", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTimeZoneMatches() {
|
public void testTimeZoneMatches() {
|
||||||
final DateParser parser= getInstance(yMdHmsSZ, REYKJAVIK);
|
final DateParser parser = getInstance(yMdHmsSZ, REYKJAVIK);
|
||||||
assertEquals(REYKJAVIK, parser.getTimeZone());
|
assertEquals(REYKJAVIK, parser.getTimeZone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToStringContainsName() {
|
public void testToStringContainsName() {
|
||||||
final DateParser parser= getInstance(YMD_SLASH);
|
final DateParser parser = getInstance(YMD_SLASH);
|
||||||
assertTrue(parser.toString().startsWith("FastDate"));
|
assertTrue(parser.toString().startsWith("FastDate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,32 +662,33 @@ public void testToStringContainsName() {
|
||||||
public void testTzParses() throws Exception {
|
public void testTzParses() throws Exception {
|
||||||
// Check that all Locales can parse the time formats we use
|
// Check that all Locales can parse the time formats we use
|
||||||
for (final Locale locale : Locale.getAvailableLocales()) {
|
for (final Locale locale : Locale.getAvailableLocales()) {
|
||||||
final FastDateParser fdp= new FastDateParser("yyyy/MM/dd z", TimeZone.getDefault(), locale);
|
final FastDateParser fdp = new FastDateParser("yyyy/MM/dd z", TimeZone.getDefault(), locale);
|
||||||
|
|
||||||
for (final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK, GMT}) {
|
for (final TimeZone tz : new TimeZone[] {NEW_YORK, REYKJAVIK, GMT}) {
|
||||||
final Calendar cal= Calendar.getInstance(tz, locale);
|
final Calendar cal = Calendar.getInstance(tz, locale);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(Calendar.YEAR, 2000);
|
cal.set(Calendar.YEAR, 2000);
|
||||||
cal.set(Calendar.MONTH, 1);
|
cal.set(Calendar.MONTH, 1);
|
||||||
cal.set(Calendar.DAY_OF_MONTH, 10);
|
cal.set(Calendar.DAY_OF_MONTH, 10);
|
||||||
final Date expected= cal.getTime();
|
final Date expected = cal.getTime();
|
||||||
|
|
||||||
final Date actual = fdp.parse("2000/02/10 "+tz.getDisplayName(locale));
|
final Date actual = fdp.parse("2000/02/10 " + tz.getDisplayName(locale));
|
||||||
assertEquals(expected, actual, "tz:"+tz.getID()+" locale:"+locale.getDisplayName());
|
assertEquals(expected, actual, "tz:" + tz.getID() + " locale:" + locale.getDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateSdfFormatFdpParseEquality(final String format, final Locale locale, final TimeZone tz, final DateParser fdp, final Date in, final int year, final Date cs) throws ParseException {
|
private void validateSdfFormatFdpParseEquality(final String format, final Locale locale, final TimeZone tz,
|
||||||
|
final DateParser fdp, final Date in, final int year, final Date cs) throws ParseException {
|
||||||
final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
|
final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
|
||||||
sdf.setTimeZone(tz);
|
sdf.setTimeZone(tz);
|
||||||
if (format.equals(SHORT_FORMAT)) {
|
if (format.equals(SHORT_FORMAT)) {
|
||||||
sdf.set2DigitYearStart( cs );
|
sdf.set2DigitYearStart(cs);
|
||||||
}
|
}
|
||||||
final String fmt = sdf.format(in);
|
final String fmt = sdf.format(in);
|
||||||
try {
|
try {
|
||||||
final Date out = fdp.parse(fmt);
|
final Date out = fdp.parse(fmt);
|
||||||
assertEquals(in, out, locale.toString()+" "+in+" "+ format+ " "+tz.getID());
|
assertEquals(in, out, locale.toString() + " " + in + " " + format + " " + tz.getID());
|
||||||
} catch (final ParseException pe) {
|
} catch (final ParseException pe) {
|
||||||
if (year >= 1868 || !locale.getCountry().equals("JP")) {// LANG-978
|
if (year >= 1868 || !locale.getCountry().equals("JP")) {// LANG-978
|
||||||
throw pe;
|
throw pe;
|
||||||
|
@ -743,3 +696,4 @@ private void validateSdfFormatFdpParseEquality(final String format, final Locale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.commons.lang3.time;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.function.TriFunction;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These tests fail on Java 15 due to a bug which was only fixed for Java 16.
|
||||||
|
* <ul>
|
||||||
|
* <li>https://bugs.openjdk.java.net/browse/JDK-8248434</li>
|
||||||
|
* <li>https://bugs.openjdk.java.net/browse/JDK-8248655</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class Java15BugFastDateParserTest {
|
||||||
|
|
||||||
|
private static final String DATE_PARSER_PARAMETERS = "org.apache.commons.lang3.time.FastDateParserTest#dateParserParameters()";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void java15BuggyLocaleTest() throws ParseException {
|
||||||
|
final String buggyLocaleName = "ff_LR_#Adlm";
|
||||||
|
Locale buggyLocale = null;
|
||||||
|
for (final Locale locale : Locale.getAvailableLocales()) {
|
||||||
|
if (buggyLocaleName.equals(locale.toString())) {
|
||||||
|
buggyLocale = locale;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buggyLocale == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
testSingleLocale(buggyLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void java15BuggyLocaleTestAll() throws ParseException {
|
||||||
|
for (final Locale locale : Locale.getAvailableLocales()) {
|
||||||
|
testSingleLocale(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testLocales(final TriFunction<String, TimeZone, Locale, DateParser> dbProvider, final String format,
|
||||||
|
final boolean eraBC) throws Exception {
|
||||||
|
|
||||||
|
final Calendar cal = Calendar.getInstance(FastDateParserTest.GMT);
|
||||||
|
cal.clear();
|
||||||
|
cal.set(2003, Calendar.FEBRUARY, 10);
|
||||||
|
if (eraBC) {
|
||||||
|
cal.set(Calendar.ERA, GregorianCalendar.BC);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Locale locale : Locale.getAvailableLocales()) {
|
||||||
|
// ja_JP_JP cannot handle dates before 1868 properly
|
||||||
|
if (eraBC && locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
|
||||||
|
final DateParser fdf = dbProvider.apply(format, TimeZone.getDefault(), locale);
|
||||||
|
|
||||||
|
// If parsing fails, a ParseException will be thrown and the test will fail
|
||||||
|
FastDateParserTest.checkParse(locale, cal, sdf, fdf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_Long_AD(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.LONG_FORMAT, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_Long_BC(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.LONG_FORMAT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_LongNoEra_AD(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.LONG_FORMAT_NOERA, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_LongNoEra_BC(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.LONG_FORMAT_NOERA, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_Short_AD(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.SHORT_FORMAT, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_Short_BC(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.SHORT_FORMAT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_ShortNoEra_AD(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.SHORT_FORMAT_NOERA, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource(DATE_PARSER_PARAMETERS)
|
||||||
|
public void testLocales_ShortNoEra_BC(final TriFunction<String, TimeZone, Locale, DateParser> dpProvider)
|
||||||
|
throws Exception {
|
||||||
|
testLocales(dpProvider, FastDateParserTest.SHORT_FORMAT_NOERA, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testSingleLocale(final Locale locale) throws ParseException {
|
||||||
|
final Calendar cal = Calendar.getInstance(FastDateParserTest.GMT);
|
||||||
|
cal.clear();
|
||||||
|
cal.set(2003, Calendar.FEBRUARY, 10);
|
||||||
|
final SimpleDateFormat sdf = new SimpleDateFormat(FastDateParserTest.LONG_FORMAT, locale);
|
||||||
|
final String formattedDate = sdf.format(cal.getTime());
|
||||||
|
sdf.parse(formattedDate);
|
||||||
|
sdf.parse(formattedDate.toUpperCase(locale));
|
||||||
|
sdf.parse(formattedDate.toLowerCase(locale));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue