This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/2.x by this push:
new f9766bb3b7 Removed unused `FastDateParser` (LOG4J2-3672, #1848)
f9766bb3b7 is described below
commit f9766bb3b7cf7a914c3ae36358aa053ee088b097
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Thu Nov 2 18:28:44 2023 +0100
Removed unused `FastDateParser` (LOG4J2-3672, #1848)
---
.../core/util/datetime/FastDateParserTest.java | 724 ---------------
log4j-core/pom.xml | 15 +
.../log4j/core/util/datetime/DateParser.java | 131 ---
.../log4j/core/util/datetime/FastDateFormat.java | 53 +-
.../log4j/core/util/datetime/FastDateParser.java | 992 ---------------------
.../logging/log4j/core/util/datetime/Format.java | 12 -
src/changelog/.2.x.x/remove_FastDateParser.xml | 9 +
src/site/_release-notes/_2.x.x.adoc | 4 +
8 files changed, 30 insertions(+), 1910 deletions(-)
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/util/datetime/FastDateParserTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/util/datetime/FastDateParserTest.java
deleted file mode 100644
index 1859435941..0000000000
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/util/datetime/FastDateParserTest.java
+++ /dev/null
@@ -1,724 +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.logging.log4j.core.util.datetime;
-
-import java.io.Serializable;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-
-import org.apache.commons.lang3.LocaleUtils;
-import org.apache.commons.lang3.SerializationUtils;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-/**
- * Unit tests {@link org.apache.commons.lang3.time.FastDateParser}.
- *
- * Copied from Apache Commons Lang 3 on 2016-11-16.
- */
-public class FastDateParserTest {
- private static enum Expected1806 {
- India(INDIA, "+05", "+0530", "+05:30", true),
- Greenwich(GMT, "Z", "Z", "Z", false),
- NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
-
- final TimeZone zone;
-
- final String one;
- final String two;
- final String three;
- final long offset;
- private Expected1806(final TimeZone zone, final String one, final
String two, final String three, final boolean hasHalfHourOffset) {
- this.zone = zone;
- this.one = one;
- this.two = two;
- this.three = three;
- 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;
- 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 YMD_SLASH = "yyyy/MM/dd";
- private static final String MDY_DASH = "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 NEW_YORK =
TimeZone.getTimeZone("America/New_York");
- private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
-
- private static final TimeZone INDIA =
TimeZone.getTimeZone("Asia/Calcutta");
-
- private static final Locale SWEDEN = new Locale("sv", "SE");
-
- private static Calendar initializeCalendar(final TimeZone tz) {
- final Calendar cal = Calendar.getInstance(tz);
- cal.set(Calendar.YEAR, 2001);
- cal.set(Calendar.MONTH, 1); // not daylight savings
- cal.set(Calendar.DAY_OF_MONTH, 4);
- cal.set(Calendar.HOUR_OF_DAY, 12);
- cal.set(Calendar.MINUTE, 8);
- cal.set(Calendar.SECOND, 56);
- cal.set(Calendar.MILLISECOND, 235);
- return cal;
- }
-
- private void checkParse(final Locale locale, final Calendar cal, final
SimpleDateFormat sdf, final DateParser fdf) throws ParseException {
- final String formattedDate= sdf.format(cal.getTime());
- checkParse(locale, sdf, fdf, formattedDate);
- checkParse(locale, sdf, fdf, formattedDate.toLowerCase(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 {
- final Date expectedTime = sdf.parse(formattedDate);
- final Date actualTime = fdf.parse(formattedDate);
- assertEquals(expectedTime, actualTime, locale.toString() + " " +
formattedDate + "\n");
- }
-
- private DateParser getDateInstance(final int dateStyle, final Locale
locale) {
- return
getInstance(FormatCache.getPatternForStyle(Integer.valueOf(dateStyle), null,
locale), TimeZone.getDefault(), Locale.getDefault());
- }
-
- private Calendar getEraStart(int year, final TimeZone zone, final Locale
locale) {
- final Calendar cal = Calendar.getInstance(zone, locale);
- cal.clear();
-
- //
http://docs.oracle.com/javase/6/docs/technotes/guides/intl/calendar.doc.html
- if (locale.equals(FastDateParser.JAPANESE_IMPERIAL)) {
- if(year < 1868) {
- cal.set(Calendar.ERA, 0);
- cal.set(Calendar.YEAR, 1868-year);
- }
- }
- else {
- if (year < 0) {
- cal.set(Calendar.ERA, GregorianCalendar.BC);
- year= -year;
- }
- cal.set(Calendar.YEAR, year/100 * 100);
- }
- return cal;
- }
-
- DateParser getInstance(final String format) {
- return getInstance(format, TimeZone.getDefault(), Locale.getDefault());
- }
-
- private DateParser getInstance(final String format, final Locale locale) {
- return getInstance(format, TimeZone.getDefault(), locale);
- }
-
- private DateParser getInstance(final String format, final TimeZone
timeZone) {
- return getInstance(format, timeZone, Locale.getDefault());
- }
-
- /**
- * Override this method in derived tests to change the construction of
instances
- *
- * @param format the format string to use
- * @param timeZone the time zone to use
- * @param locale the locale to use
- *
- * @return the DateParser instance to use for testing
- */
- protected DateParser getInstance(final String format, final TimeZone
timeZone, final Locale locale) {
- return new FastDateParser(format, timeZone, locale, null);
- }
-
- @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++));
- }
-
- i= 0;
- for(final DateParser parser:parsers) {
- assertEquals(i++, map.get(parser).intValue());
- }
- }
-
- @Test
- public void test1806() throws ParseException {
- final String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
- final String dateStub = "2001-02-04T12:08:56.235";
-
- for (final Expected1806 trial : Expected1806.values()) {
- final Calendar cal = initializeCalendar(trial.zone);
-
- final String message = trial.zone.getDisplayName()+";";
-
- DateParser parser = getInstance(formatStub+"X", trial.zone);
- assertEquals(cal.getTime().getTime(), parser.parse(dateStub +
trial.one).getTime() - trial.offset,
- message + trial.one);
-
- parser = getInstance(formatStub+"XX", trial.zone);
- assertEquals(cal.getTime(), parser.parse(dateStub + trial.two),
message + trial.two);
-
- parser = getInstance(formatStub+"XXX", trial.zone);
- assertEquals(cal.getTime(), parser.parse(dateStub + trial.three),
message + trial.three);
- }
- }
-
- @Test
- public void test1806Argument() {
- assertThrows(IllegalArgumentException.class, () ->
getInstance("XXXX"));
- }
-
-
- @Test
- public void testAmPm() throws ParseException {
- final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
- cal.clear();
-
- final DateParser h = getInstance("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("yyyy-MM-dd kk:mm:ss", NEW_YORK,
Locale.US);
- final DateParser H = getInstance("yyyy-MM-dd HH:mm:ss", NEW_YORK,
Locale.US);
-
- cal.set(2010, Calendar.AUGUST, 1, 0, 33, 20);
- assertEquals(cal.getTime(), h.parse("2010-08-01 12 AM 33:20"));
- assertEquals(cal.getTime(), K.parse("2010-08-01 0 AM 33:20"));
- assertEquals(cal.getTime(), k.parse("2010-08-01 00:33:20"));
- assertEquals(cal.getTime(), H.parse("2010-08-01 00:33:20"));
-
- cal.set(2010, Calendar.AUGUST, 1, 3, 33, 20);
- assertEquals(cal.getTime(), h.parse("2010-08-01 3 AM 33:20"));
- assertEquals(cal.getTime(), K.parse("2010-08-01 3 AM 33:20"));
- assertEquals(cal.getTime(), k.parse("2010-08-01 03:33:20"));
- assertEquals(cal.getTime(), H.parse("2010-08-01 03:33:20"));
-
- cal.set(2010, Calendar.AUGUST, 1, 15, 33, 20);
- assertEquals(cal.getTime(), h.parse("2010-08-01 3 PM 33:20"));
- assertEquals(cal.getTime(), K.parse("2010-08-01 3 PM 33:20"));
- assertEquals(cal.getTime(), k.parse("2010-08-01 15:33:20"));
- assertEquals(cal.getTime(), H.parse("2010-08-01 15:33:20"));
-
- cal.set(2010, Calendar.AUGUST, 1, 12, 33, 20);
- assertEquals(cal.getTime(), h.parse("2010-08-01 12 PM 33:20"));
- assertEquals(cal.getTime(), K.parse("2010-08-01 0 PM 33:20"));
- assertEquals(cal.getTime(), k.parse("2010-08-01 12:33:20"));
- assertEquals(cal.getTime(), H.parse("2010-08-01 12:33:20"));
- }
-
- @Test
- public void testDayNumberOfWeek() throws ParseException {
- final DateParser parser = getInstance("u");
- final Calendar calendar = Calendar.getInstance();
-
- calendar.setTime(parser.parse("1"));
- assertEquals(Calendar.MONDAY, calendar.get(Calendar.DAY_OF_WEEK));
-
- calendar.setTime(parser.parse("6"));
- assertEquals(Calendar.SATURDAY, calendar.get(Calendar.DAY_OF_WEEK));
-
- calendar.setTime(parser.parse("7"));
- assertEquals(Calendar.SUNDAY, calendar.get(Calendar.DAY_OF_WEEK));
- }
-
- @Test
- public void testDayOf() throws ParseException {
- final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
- cal.clear();
- cal.set(2003, Calendar.FEBRUARY, 10);
-
- final DateParser fdf = getInstance("W w F D y", NEW_YORK, Locale.US);
- assertEquals(cal.getTime(), fdf.parse("3 7 2 41 03"));
- }
-
- @Test
- public void testEquals() {
- final DateParser parser1= getInstance(YMD_SLASH);
- final DateParser parser2= getInstance(YMD_SLASH);
-
- assertEquals(parser1, parser2);
- assertEquals(parser1.hashCode(), parser2.hashCode());
-
- assertFalse(parser1.equals(new Object()));
- }
-
- @Test
- public void testJpLocales() {
-
- final Calendar cal= Calendar.getInstance(GMT);
- cal.clear();
- cal.set(2003, Calendar.FEBRUARY, 10);
- cal.set(Calendar.ERA, GregorianCalendar.BC);
-
- final Locale locale = LocaleUtils.toLocale("zh"); {
- // ja_JP_JP cannot handle dates before 1868 properly
-
- final SimpleDateFormat sdf = new SimpleDateFormat(LONG_FORMAT,
locale);
- final DateParser fdf = getInstance(LONG_FORMAT, locale);
-
- try {
- checkParse(locale, cal, sdf, fdf);
- } catch(final ParseException ex) {
- fail("Locale " + locale + " failed with " + LONG_FORMAT + "\n"
+ trimMessage(ex.toString()));
- }
- }
- }
-
- @Test
- public void testLANG_831() throws Exception {
- testSdfAndFdp("M E","3 Tue", true);
- }
-
- @Test
- public void testLANG_832() throws Exception {
- testSdfAndFdp("'d'd" ,"d3", false); // OK
- testSdfAndFdp("'d'd'","d3", true); // should fail (unterminated quote)
- }
-
- @Test
- public void testLang1121() throws ParseException {
- final TimeZone kst = TimeZone.getTimeZone("Asia/Seoul");
- final DateParser fdp = getInstance("yyyyMMdd", kst, Locale.KOREA);
-
- try {
- fdp.parse("2015");
- fail("expected parse exception");
- } catch (final ParseException pe) {
- // expected parse exception
- }
-
- // Wed Apr 29 00:00:00 KST 2015
- Date actual = fdp.parse("20150429");
- final Calendar cal = Calendar.getInstance(kst, Locale.KOREA);
- cal.clear();
- cal.set(2015, 3, 29);
- Date expected = cal.getTime();
- assertEquals(expected, actual);
-
- final SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd",
Locale.KOREA);
- df.setTimeZone(kst);
- expected = df.parse("20150429113100");
-
- // Thu Mar 16 00:00:00 KST 81724
- actual = fdp.parse("20150429113100");
- assertEquals(expected, actual);
- }
-
- @Test
- public void testLang303() throws ParseException {
- DateParser parser = getInstance(YMD_SLASH);
- final Calendar cal = Calendar.getInstance();
- cal.set(2004, Calendar.DECEMBER, 31);
-
- final Date date = parser.parse("2004/11/31");
-
- parser =
SerializationUtils.deserialize(SerializationUtils.serialize((Serializable)
parser));
- assertEquals(date, parser.parse("2004/11/31"));
- }
-
- @Test
- public void testLang538() throws ParseException {
- final DateParser parser = getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
GMT);
-
- final Calendar cal =
Calendar.getInstance(TimeZone.getTimeZone("GMT-8"));
- cal.clear();
- cal.set(2009, Calendar.OCTOBER, 16, 8, 42, 16);
-
- assertEquals(cal.getTime(), parser.parse("2009-10-16T16:42:16.000Z"));
- }
-
- @Test
- public void testLang996() throws ParseException {
- final Calendar expected = Calendar.getInstance(NEW_YORK, Locale.US);
- expected.clear();
- expected.set(2014, Calendar.MAY, 14);
-
- final DateParser fdp = getInstance("ddMMMyyyy", NEW_YORK, Locale.US);
- assertEquals(expected.getTime(), fdp.parse("14may2014"));
- assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
- assertEquals(expected.getTime(), fdp.parse("14May2014"));
- }
-
- @Test
- public void testLocaleMatches() {
- final DateParser parser= getInstance(yMdHmsSZ, SWEDEN);
- 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);
-
- try {
- checkParse(locale, cal, sdf, fdf);
- } catch(final ParseException ex) {
- fail("Locale " + locale + " failed with " + format + " era " +
(eraBC ? "BC" : "AD") + "\n"
- + trimMessage(ex.toString()));
- }
- }
- }
-
- @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
- * @throws ParseException so we don't have to catch it
- */
- @Test
- public void testLowYearPadding() throws ParseException {
- final DateParser parser = getInstance(YMD_SLASH);
- final Calendar cal = Calendar.getInstance();
- cal.clear();
-
- cal.set(1, Calendar.JANUARY, 1);
- assertEquals(cal.getTime(), parser.parse("0001/01/01"));
- cal.set(10, Calendar.JANUARY, 1);
- assertEquals(cal.getTime(), parser.parse("0010/01/01"));
- cal.set(100, Calendar.JANUARY, 1);
- assertEquals(cal.getTime(), parser.parse("0100/01/01"));
- cal.set(999, Calendar.JANUARY, 1);
- assertEquals(cal.getTime(), parser.parse("0999/01/01"));
- }
-
- @Test
- public void testMilleniumBug() throws ParseException {
- final DateParser parser = getInstance(DMY_DOT);
- final Calendar cal = Calendar.getInstance();
- cal.clear();
-
- cal.set(1000, Calendar.JANUARY, 1);
- assertEquals(cal.getTime(), parser.parse("01.01.1000"));
- }
-
- @Test
- public void testParseLongShort() throws ParseException {
- final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
- cal.clear();
- cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
- cal.set(Calendar.MILLISECOND, 989);
- cal.setTimeZone(NEW_YORK);
-
- DateParser fdf = getInstance("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"));
- cal.set(Calendar.ERA, GregorianCalendar.BC);
-
- final Date parse = fdf.parse("2003 BC February 0010 PM Saturday 0015
0033 0020 0989 GMT-05:00");
- assertEquals(cal.getTime(), parse);
-
- fdf = getInstance("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"));
-
- cal.set(Calendar.ERA, GregorianCalendar.AD);
- assertEquals(cal.getTime(), fdf.parse("03 AD 2 10 PM Saturday 15 33 20
989 -0500"));
- }
-
- @Test
- public void testParseNumerics() throws ParseException {
- final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
- cal.clear();
- cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
- cal.set(Calendar.MILLISECOND, 989);
-
- final DateParser fdf = getInstance("yyyyMMddHHmmssSSS", NEW_YORK,
Locale.US);
- assertEquals(cal.getTime(), fdf.parse("20030210153320989"));
- }
-
- @Test
- public void testParseOffset() {
- final DateParser parser = getInstance(YMD_SLASH);
- final Date date = parser.parse("Today is 2015/07/04", new
ParsePosition(9));
-
- final Calendar cal = Calendar.getInstance();
- cal.clear();
- cal.set(2015, Calendar.JULY, 4);
- assertEquals(cal.getTime(), date);
- }
-
- @Test
- // Check that all Locales can parse the formats we use
- public void testParses() throws Exception {
- for(final String format : new String[]{LONG_FORMAT, SHORT_FORMAT}) {
- for(final Locale locale : Locale.getAvailableLocales()) {
- for(final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK,
GMT}) {
- for(final int year : new int[]{2003, 1940, 1868, 1867, 1,
-1, -1940}) {
- final Calendar cal= getEraStart(year, tz, locale);
- final Date centuryStart= cal.getTime();
-
- cal.set(Calendar.MONTH, 1);
- cal.set(Calendar.DAY_OF_MONTH, 10);
- final Date in= cal.getTime();
-
- final FastDateParser fdp= new FastDateParser(format,
tz, locale, centuryStart);
- validateSdfFormatFdpParseEquality(format, locale, tz,
fdp, in, year, centuryStart);
- }
- }
- }
- }
- }
-
- @Test
- public void testParseZone() throws ParseException {
- final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
- cal.clear();
- cal.set(2003, Calendar.JULY, 10, 16, 33, 20);
-
- final DateParser fdf = getInstance(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
GMT-05:00"));
- assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 Eastern
Daylight Time"));
- assertEquals(cal.getTime(), fdf.parse("2003-07-10T16:33:20.000 EDT"));
-
- cal.setTimeZone(TimeZone.getTimeZone("GMT-3"));
- cal.set(2003, Calendar.FEBRUARY, 10, 9, 0, 0);
-
- assertEquals(cal.getTime(), fdf.parse("2003-02-10T09:00:00.000
-0300"));
-
- cal.setTimeZone(TimeZone.getTimeZone("GMT+5"));
- cal.set(2003, Calendar.FEBRUARY, 10, 15, 5, 6);
-
- assertEquals(cal.getTime(), fdf.parse("2003-02-10T15:05:06.000
+0500"));
- }
-
- @Test
- public void testPatternMatches() {
- final DateParser parser= getInstance(yMdHmsSZ);
- assertEquals(yMdHmsSZ, parser.getPattern());
- }
-
- @Test
- public void testQuotes() throws ParseException {
- final Calendar cal= Calendar.getInstance(NEW_YORK, Locale.US);
- cal.clear();
- cal.set(2003, Calendar.FEBRUARY, 10, 15, 33, 20);
- cal.set(Calendar.MILLISECOND, 989);
-
- final DateParser fdf = getInstance("''yyyyMMdd'A''B'HHmmssSSS''",
NEW_YORK, Locale.US);
- assertEquals(cal.getTime(), fdf.parse("'20030210A'B153320989'"));
- }
-
- private void testSdfAndFdp(final String format, final String date, final
boolean shouldFail)
- throws Exception {
- Date dfdp = null;
- Date dsdf = null;
- Throwable f = null;
- Throwable s = null;
-
- try {
- final SimpleDateFormat sdf = new SimpleDateFormat(format,
Locale.US);
- sdf.setTimeZone(NEW_YORK);
- dsdf = sdf.parse(date);
- if (shouldFail) {
- fail("Expected SDF failure, but got " + dsdf + " for [" +
format + "," + date + "]");
- }
- } catch (final Exception e) {
- s = e;
- if (!shouldFail) {
- throw e;
- }
- }
-
- try {
- final DateParser fdp = getInstance(format, NEW_YORK, Locale.US);
- dfdp = fdp.parse(date);
- if (shouldFail) {
- fail("Expected FDF failure, but got " + dfdp + " for [" +
format + "," + date + "]");
- }
- } catch (final Exception e) {
- f = e;
- if (!shouldFail) {
- throw e;
- }
- }
- // SDF and FDF should produce equivalent results
- assertTrue((f == null) == (s == null), "Should both or neither throw
Exceptions");
- assertEquals(dsdf, dfdp, "Parsed dates should be equal");
- }
-
- /**
- * Test case for {@link FastDateParser#FastDateParser(String, TimeZone,
Locale)}.
- * @throws ParseException so we don't have to catch it
- */
- @Test
- public void testShortDateStyleWithLocales() throws ParseException {
- DateParser fdf = getDateInstance(FastDateFormat.SHORT, Locale.US);
- final Calendar cal = Calendar.getInstance();
- cal.clear();
-
- cal.set(2004, Calendar.FEBRUARY, 3);
- assertEquals(cal.getTime(), fdf.parse("2/3/04"));
-
- fdf = getDateInstance(FastDateFormat.SHORT, SWEDEN);
- assertEquals(cal.getTime(), fdf.parse("2004-02-03"));
- }
-
- @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
- testSdfAndFdp("'QED'", "QED", false);
- testSdfAndFdp("'QED'", "qed", true);
- // case sensitive after insensitive Month field
- testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 QED", false);
- testSdfAndFdp("yyyy-MM-dd 'QED'", "2003-02-10 qed", true);
- }
-
- @Test
- public void testTimeZoneMatches() {
- final DateParser parser= getInstance(yMdHmsSZ, REYKJAVIK);
- assertEquals(REYKJAVIK, parser.getTimeZone());
- }
-
- @Test
- public void testToStringContainsName() {
- final DateParser parser= getInstance(YMD_SLASH);
- assertTrue(parser.toString().startsWith("FastDate"));
- }
-
- // we cannot use historic dates to test timezone parsing, some timezones
have second offsets
- // as well as hours and minutes which makes the z formats a low fidelity
round trip
- @Test
- public void testTzParses() throws Exception {
- // Check that all Locales can parse the time formats we use
- for(final Locale locale : Locale.getAvailableLocales()) {
- final FastDateParser fdp= new FastDateParser("yyyy/MM/dd z",
TimeZone.getDefault(), locale);
-
- for(final TimeZone tz : new TimeZone[]{NEW_YORK, REYKJAVIK, GMT})
{
- final Calendar cal= Calendar.getInstance(tz, locale);
- cal.clear();
- cal.set(Calendar.YEAR, 2000);
- cal.set(Calendar.MONTH, 1);
- cal.set(Calendar.DAY_OF_MONTH, 10);
- final Date expected= cal.getTime();
-
- final Date actual = fdp.parse("2000/02/10
"+tz.getDisplayName(locale));
- assertEquals(expected, actual, "tz:" + tz.getID() + " locale:"
+ locale.getDisplayName());
- }
- }
- }
-
- private String trimMessage(final String msg) {
- if (msg.length() < 100) {
- return msg;
- }
- final int gmt = msg.indexOf("(GMT");
- if (gmt > 0) {
- return msg.substring(0, gmt+4)+"...)";
- }
- return msg.substring(0, 100)+"...";
- }
-
- 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);
- sdf.setTimeZone(tz);
- if (format.equals(SHORT_FORMAT)) {
- sdf.set2DigitYearStart( cs );
- }
- final String fmt = sdf.format(in);
- try {
- final Date out = fdp.parse(fmt);
- assertEquals(in, out, locale.toString() + " " + in + " " + format
+ " " + tz.getID());
- } catch (final ParseException pe) {
- if (year >= 1868 || !locale.getCountry().equals("JP")) {// LANG-978
- throw pe;
- }
- }
- }
-}
diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index 7202eef410..2f8f8c3689 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -296,6 +296,21 @@
</executions>
</plugin>
+ <!-- Remove this override after `2.22.0` release!
+ In `2.22.0`, we have removed *unused* `FastDateParser` due to
LOG4J2-3672 and #1848.
+ Though `bnd-baseline-m-p` doesn't allow such breaking changes in
non-major version upgrades.
+ Hence, we suppress it until `2.22.0` gets released. -->
+ <plugin>
+ <groupId>biz.aQute.bnd</groupId>
+ <artifactId>bnd-baseline-maven-plugin</artifactId>
+ <configuration>
+ <diffpackages>
+
<diffpackage>!org.apache.logging.log4j.core.util.datetime</diffpackage>
+ <diffpackage>*</diffpackage>
+ </diffpackages>
+ </configuration>
+ </plugin>
+
</plugins>
</build>
</project>
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/DateParser.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/DateParser.java
deleted file mode 100644
index 5d42fafdc2..0000000000
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/DateParser.java
+++ /dev/null
@@ -1,131 +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.logging.log4j.core.util.datetime;
-
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- * DateParser is the "missing" interface for the parsing methods of
- * {@link java.text.DateFormat}. You can obtain an object implementing this
- * interface by using one of the FastDateFormat factory methods.
- * <p>
- * Warning: Since binary compatible methods may be added to this interface in
any
- * release, developers are not expected to implement this interface.
- *
- * <p>
- * Copied and modified from <a
href="https://commons.apache.org/proper/commons-lang/">Apache Commons Lang</a>.
- * </p>
- *
- * @since Apache Commons Lang 3.2
- */
-public interface DateParser {
-
- /**
- * Equivalent to DateFormat.parse(String).
- *
- * See {@link java.text.DateFormat#parse(String)} for more information.
- * @param source A <code>String</code> whose beginning should be parsed.
- * @return A <code>Date</code> parsed from the string
- * @throws ParseException if the beginning of the specified string cannot
be parsed.
- */
- Date parse(String source) throws ParseException;
-
- /**
- * Equivalent to DateFormat.parse(String, ParsePosition).
- *
- * See {@link java.text.DateFormat#parse(String, ParsePosition)} for more
information.
- *
- * @param source A <code>String</code>, part of which should be parsed.
- * @param pos A <code>ParsePosition</code> object with index and error
index information
- * as described above.
- * @return A <code>Date</code> parsed from the string. In case of error,
returns null.
- * @throws NullPointerException if text or pos is null.
- */
- Date parse(String source, ParsePosition pos);
-
- /**
- * Parses a formatted date string according to the format. Updates the
Calendar with parsed fields.
- * Upon success, the ParsePosition index is updated to indicate how much
of the source text was consumed.
- * Not all source text needs to be consumed. Upon parse failure,
ParsePosition error index is updated to
- * the offset of the source text which does not match the supplied format.
- *
- * @param source The text to parse.
- * @param pos On input, the position in the source to start parsing, on
output, updated position.
- * @param calendar The calendar into which to set parsed fields.
- * @return true, if source has been parsed (pos parsePosition is updated);
otherwise false (and pos errorIndex is updated)
- * @throws IllegalArgumentException when Calendar has been set to be not
lenient, and a parsed field is
- * out of range.
- *
- * @since 3.5
- */
- boolean parse(String source, ParsePosition pos, Calendar calendar);
-
- // Accessors
- //-----------------------------------------------------------------------
- /**
- * <p>Gets the pattern used by this parser.</p>
- *
- * @return the pattern, {@link java.text.SimpleDateFormat} compatible
- */
- String getPattern();
-
- /**
- * <p>
- * Gets the time zone used by this parser.
- * </p>
- *
- * <p>
- * The default {@link TimeZone} used to create a {@link Date} when the
{@link TimeZone} is not specified by
- * the format pattern.
- * </p>
- *
- * @return the time zone
- */
- TimeZone getTimeZone();
-
- /**
- * <p>Gets the locale used by this parser.</p>
- *
- * @return the locale
- */
- Locale getLocale();
-
- /**
- * Parses text from a string to produce a Date.
- *
- * @param source A <code>String</code> whose beginning should be parsed.
- * @return a <code>java.util.Date</code> object
- * @throws ParseException if the beginning of the specified string cannot
be parsed.
- * @see java.text.DateFormat#parseObject(String)
- */
- Object parseObject(String source) throws ParseException;
-
- /**
- * Parses a date/time string according to the given parse position.
- *
- * @param source A <code>String</code> whose beginning should be parsed.
- * @param pos the parse position
- * @return a <code>java.util.Date</code> object
- * @see java.text.DateFormat#parseObject(String, ParsePosition)
- */
- Object parseObject(String source, ParsePosition pos);
-}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateFormat.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateFormat.java
index 9381b4d171..914a6dfff6 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateFormat.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateFormat.java
@@ -18,8 +18,6 @@ package org.apache.logging.log4j.core.util.datetime;
import java.text.DateFormat;
import java.text.FieldPosition;
-import java.text.ParseException;
-import java.text.ParsePosition;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
@@ -72,15 +70,7 @@ import java.util.TimeZone;
*
* @since Apache Commons Lang 2.0
*/
-public class FastDateFormat extends Format implements DateParser, DatePrinter {
-
- /**
- * Required for serialization support.
- *
- * @see java.io.Serializable
- */
- @SuppressWarnings("unused")
- private static final long serialVersionUID = 2L;
+public class FastDateFormat extends Format implements DatePrinter {
/**
* FULL locale dependent date or time style.
@@ -110,7 +100,6 @@ public class FastDateFormat extends Format implements
DateParser, DatePrinter {
};
private final FastDatePrinter printer;
- private final FastDateParser parser;
//-----------------------------------------------------------------------
/**
@@ -399,7 +388,6 @@ public class FastDateFormat extends Format implements
DateParser, DatePrinter {
*/
protected FastDateFormat(final String pattern, final TimeZone timeZone,
final Locale locale, final Date centuryStart) {
printer= new FastDatePrinter(pattern, timeZone, locale);
- parser= new FastDateParser(pattern, timeZone, locale, centuryStart);
}
// Format methods
@@ -495,43 +483,6 @@ public class FastDateFormat extends Format implements
DateParser, DatePrinter {
return printer.format(calendar, buf);
}
- // Parsing
- //-----------------------------------------------------------------------
-
-
- /* (non-Javadoc)
- * @see DateParser#parse(java.lang.String)
- */
- @Override
- public Date parse(final String source) throws ParseException {
- return parser.parse(source);
- }
-
- /* (non-Javadoc)
- * @see DateParser#parse(java.lang.String, java.text.ParsePosition)
- */
- @Override
- public Date parse(final String source, final ParsePosition pos) {
- return parser.parse(source, pos);
- }
-
- /*
- * (non-Javadoc)
- * @see org.apache.commons.lang3.time.DateParser#parse(java.lang.String,
java.text.ParsePosition, java.util.Calendar)
- */
- @Override
- public boolean parse(final String source, final ParsePosition pos, final
Calendar calendar) {
- return parser.parse(source, pos, calendar);
- }
-
- /* (non-Javadoc)
- * @see java.text.Format#parseObject(java.lang.String,
java.text.ParsePosition)
- */
- @Override
- public Object parseObject(final String source, final ParsePosition pos) {
- return parser.parseObject(source, pos);
- }
-
// Accessors
//-----------------------------------------------------------------------
/**
@@ -589,7 +540,7 @@ public class FastDateFormat extends Format implements
DateParser, DatePrinter {
*/
@Override
public boolean equals(final Object obj) {
- if (obj instanceof FastDateFormat == false) {
+ if (!(obj instanceof FastDateFormat)) {
return false;
}
final FastDateFormat other = (FastDateFormat) obj;
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateParser.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateParser.java
deleted file mode 100644
index 0b7f4b4cdc..0000000000
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/FastDateParser.java
+++ /dev/null
@@ -1,992 +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.logging.log4j.core.util.datetime;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.Serializable;
-import java.text.DateFormatSymbols;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.logging.log4j.core.util.Integers;
-
-import static org.apache.logging.log4j.util.Strings.toRootUpperCase;
-
-/**
- * <p>FastDateParser is a fast and thread-safe version of
- * {@link java.text.SimpleDateFormat}.</p>
- *
- * <p>To obtain a proxy to a FastDateParser, use {@link
FastDateFormat#getInstance(String, TimeZone, Locale)}
- * or another variation of the factory methods of {@link FastDateFormat}.</p>
- *
- * <p>Since FastDateParser is thread safe, you can use a static member
instance:</p>
- * <code>
- * private static final DateParser DATE_PARSER =
FastDateFormat.getInstance("yyyy-MM-dd");
- * </code>
- *
- * <p>This class can be used as a direct replacement for
- * <code>SimpleDateFormat</code> in most parsing situations.
- * This class is especially useful in multi-threaded server environments.
- * <code>SimpleDateFormat</code> is not thread-safe in any JDK version,
- * nor will it be as Sun has closed the
- * <a href="https://bugs.openjdk.org/browse/JDK-4228335">bug</a>/RFE.
- * </p>
- *
- * <p>Only parsing is supported by this class, but all patterns are compatible
with
- * SimpleDateFormat.</p>
- *
- * <p>The class operates in lenient mode, so for example a time of 90 minutes
is treated as 1 hour 30 minutes.</p>
- *
- * <p>Timing tests indicate this class is as about as fast as SimpleDateFormat
- * in single thread applications and about 25% faster in multi-thread
applications.</p>
- *
- * <p>
- * Copied and modified from <a
href="https://commons.apache.org/proper/commons-lang/">Apache Commons Lang</a>.
- * </p>
- *
- * @since Apache Commons Lang 3.2
- * @see FastDatePrinter
- */
-public class FastDateParser implements DateParser, Serializable {
-
- /**
- * Required for serialization support.
- *
- * @see java.io.Serializable
- */
- private static final long serialVersionUID = 3L;
-
- static final Locale JAPANESE_IMPERIAL = new Locale("ja","JP","JP");
-
- // defining fields
- private final String pattern;
- private final TimeZone timeZone;
- private final Locale locale;
- private final int century;
- private final int startYear;
-
- // derived fields
- private transient List<StrategyAndWidth> patterns;
-
- // comparator used to sort regex alternatives
- // alternatives should be ordered longer first, and shorter last.
('february' before 'feb')
- // all entries must be lowercase by locale.
- private static final Comparator<String> LONGER_FIRST_LOWERCASE = (left,
right) -> right.compareTo(left);
-
- /**
- * <p>Constructs a new FastDateParser.</p>
- *
- * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)} or
another variation of the
- * factory methods of {@link FastDateFormat} to get a cached
FastDateParser instance.
- *
- * @param pattern non-null {@link java.text.SimpleDateFormat} compatible
- * pattern
- * @param timeZone non-null time zone to use
- * @param locale non-null locale
- */
- protected FastDateParser(final String pattern, final TimeZone timeZone,
final Locale locale) {
- this(pattern, timeZone, locale, null);
- }
-
- /**
- * <p>Constructs a new FastDateParser.</p>
- *
- * @param pattern non-null {@link java.text.SimpleDateFormat} compatible
- * pattern
- * @param timeZone non-null time zone to use
- * @param locale non-null locale
- * @param centuryStart The start of the century for 2 digit year parsing
- *
- * @since 3.5
- */
- protected FastDateParser(final String pattern, final TimeZone timeZone,
final Locale locale, final Date centuryStart) {
- this.pattern = pattern;
- this.timeZone = timeZone;
- this.locale = locale;
-
- final Calendar definingCalendar = Calendar.getInstance(timeZone,
locale);
-
- int centuryStartYear;
- if(centuryStart!=null) {
- definingCalendar.setTime(centuryStart);
- centuryStartYear= definingCalendar.get(Calendar.YEAR);
- }
- else if(locale.equals(JAPANESE_IMPERIAL)) {
- centuryStartYear= 0;
- }
- else {
- // from 80 years ago to 20 years from now
- definingCalendar.setTime(new Date());
- centuryStartYear= definingCalendar.get(Calendar.YEAR)-80;
- }
- century= centuryStartYear / 100 * 100;
- startYear= centuryStartYear - century;
-
- init(definingCalendar);
- }
-
- /**
- * Initialize derived fields from defining fields.
- * This is called from constructor and from readObject (de-serialization)
- *
- * @param definingCalendar the {@link java.util.Calendar} instance used to
initialize this FastDateParser
- */
- private void init(final Calendar definingCalendar) {
- patterns = new ArrayList<>();
-
- final StrategyParser fm = new StrategyParser(definingCalendar);
- for(;;) {
- final StrategyAndWidth field = fm.getNextStrategy();
- if(field==null) {
- break;
- }
- patterns.add(field);
- }
- }
-
- // helper classes to parse the format string
- //-----------------------------------------------------------------------
-
- /**
- * Holds strategy and field width
- */
- private static class StrategyAndWidth {
- final Strategy strategy;
- final int width;
-
- StrategyAndWidth(final Strategy strategy, final int width) {
- this.strategy = strategy;
- this.width = width;
- }
-
- int getMaxWidth(final ListIterator<StrategyAndWidth> lt) {
- if(!strategy.isNumber() || !lt.hasNext()) {
- return 0;
- }
- final Strategy nextStrategy = lt.next().strategy;
- lt.previous();
- return nextStrategy.isNumber() ?width :0;
- }
- }
-
- /**
- * Parse format into Strategies
- */
- private class StrategyParser {
- final private Calendar definingCalendar;
- private int currentIdx;
-
- StrategyParser(final Calendar definingCalendar) {
- this.definingCalendar = definingCalendar;
- }
-
- StrategyAndWidth getNextStrategy() {
- if (currentIdx >= pattern.length()) {
- return null;
- }
-
- final char c = pattern.charAt(currentIdx);
- if (isFormatLetter(c)) {
- return letterPattern(c);
- }
- return literal();
- }
-
- private StrategyAndWidth letterPattern(final char c) {
- final int begin = currentIdx;
- while (++currentIdx < pattern.length()) {
- if (pattern.charAt(currentIdx) != c) {
- break;
- }
- }
-
- final int width = currentIdx - begin;
- return new StrategyAndWidth(getStrategy(c, width,
definingCalendar), width);
- }
-
- private StrategyAndWidth literal() {
- boolean activeQuote = false;
-
- final StringBuilder sb = new StringBuilder();
- while (currentIdx < pattern.length()) {
- final char c = pattern.charAt(currentIdx);
- if (!activeQuote && isFormatLetter(c)) {
- break;
- } else if (c == '\'' && (++currentIdx == pattern.length() ||
pattern.charAt(currentIdx) != '\'')) {
- activeQuote = !activeQuote;
- continue;
- }
- ++currentIdx;
- sb.append(c);
- }
-
- if (activeQuote) {
- throw new IllegalArgumentException("Unterminated quote");
- }
-
- final String formatField = sb.toString();
- return new StrategyAndWidth(new CopyQuotedStrategy(formatField),
formatField.length());
- }
- }
-
- private static boolean isFormatLetter(final char c) {
- return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
- }
-
- // Accessors
- //-----------------------------------------------------------------------
- /* (non-Javadoc)
- * @see org.apache.commons.lang3.time.DateParser#getPattern()
- */
- @Override
- public String getPattern() {
- return pattern;
- }
-
- /* (non-Javadoc)
- * @see org.apache.commons.lang3.time.DateParser#getTimeZone()
- */
- @Override
- public TimeZone getTimeZone() {
- return timeZone;
- }
-
- /* (non-Javadoc)
- * @see org.apache.commons.lang3.time.DateParser#getLocale()
- */
- @Override
- public Locale getLocale() {
- return locale;
- }
-
-
- // Basics
- //-----------------------------------------------------------------------
- /**
- * <p>Compare another object for equality with this object.</p>
- *
- * @param obj the object to compare to
- * @return <code>true</code>if equal to this instance
- */
- @Override
- public boolean equals(final Object obj) {
- if (!(obj instanceof FastDateParser)) {
- return false;
- }
- final FastDateParser other = (FastDateParser) obj;
- return pattern.equals(other.pattern)
- && timeZone.equals(other.timeZone)
- && locale.equals(other.locale);
- }
-
- /**
- * <p>Return a hash code compatible with equals.</p>
- *
- * @return a hash code compatible with equals
- */
- @Override
- public int hashCode() {
- return pattern.hashCode() + 13 * (timeZone.hashCode() + 13 *
locale.hashCode());
- }
-
- /**
- * <p>Get a string version of this formatter.</p>
- *
- * @return a debugging string
- */
- @Override
- public String toString() {
- return "FastDateParser[" + pattern + "," + locale + "," +
timeZone.getID() + "]";
- }
-
- // Serializing
- //-----------------------------------------------------------------------
- /**
- * Create the object after serialization. This implementation
reinitializes the
- * transient properties.
- *
- * @param in ObjectInputStream from which the object is being deserialized.
- * @throws IOException if there is an IO issue.
- * @throws ClassNotFoundException if a class cannot be found.
- */
- private void readObject(final ObjectInputStream in) throws IOException,
ClassNotFoundException {
- in.defaultReadObject();
-
- final Calendar definingCalendar = Calendar.getInstance(timeZone,
locale);
- init(definingCalendar);
- }
-
- /* (non-Javadoc)
- * @see
org.apache.commons.lang3.time.DateParser#parseObject(java.lang.String)
- */
- @Override
- public Object parseObject(final String source) throws ParseException {
- return parse(source);
- }
-
- /* (non-Javadoc)
- * @see org.apache.commons.lang3.time.DateParser#parse(java.lang.String)
- */
- @Override
- public Date parse(final String source) throws ParseException {
- final ParsePosition pp = new ParsePosition(0);
- final Date date= parse(source, pp);
- if (date == null) {
- // Add a note re supported date range
- if (locale.equals(JAPANESE_IMPERIAL)) {
- throw new ParseException(
- "(The " +locale + " locale does not support dates
before 1868 AD)\n" +
- "Unparseable date: \""+source,
pp.getErrorIndex());
- }
- throw new ParseException("Unparseable date: "+source,
pp.getErrorIndex());
- }
- return date;
- }
-
- /* (non-Javadoc)
- * @see
org.apache.commons.lang3.time.DateParser#parseObject(java.lang.String,
java.text.ParsePosition)
- */
- @Override
- public Object parseObject(final String source, final ParsePosition pos) {
- return parse(source, pos);
- }
-
- /**
- * This implementation updates the ParsePosition if the parse succeeds.
- * However, it sets the error index to the position before the failed
field unlike
- * the method {@link java.text.SimpleDateFormat#parse(String,
ParsePosition)} which sets
- * the error index to after the failed field.
- * <p>
- * To determine if the parse has succeeded, the caller must check if the
current parse position
- * given by {@link ParsePosition#getIndex()} has been updated. If the
input buffer has been fully
- * parsed, then the index will point to just after the end of the input
buffer.
- *
- * @see <a
href="https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/time/DateParser.html#parse-java.lang.String-java.text.ParsePosition-">
- * org.apache.commons.lang3.time.DateParser#parse(String,
ParsePosition)</a>
- */
- @Override
- public Date parse(final String source, final ParsePosition pos) {
- // timing tests indicate getting new instance is 19% faster than
cloning
- final Calendar cal= Calendar.getInstance(timeZone, locale);
- cal.clear();
-
- return parse(source, pos, cal) ? cal.getTime() : null;
- }
-
- /**
- * Parse a formatted date string according to the format. Updates the
Calendar with parsed fields.
- * Upon success, the ParsePosition index is updated to indicate how much
of the source text was consumed.
- * Not all source text needs to be consumed. Upon parse failure,
ParsePosition error index is updated to
- * the offset of the source text which does not match the supplied format.
- *
- * @param source The text to parse.
- * @param pos On input, the position in the source to start parsing, on
output, updated position.
- * @param calendar The calendar into which to set parsed fields.
- * @return true, if source has been parsed (pos parsePosition is updated);
otherwise false (and pos errorIndex is updated)
- * @throws IllegalArgumentException when Calendar has been set to be not
lenient, and a parsed field is
- * out of range.
- */
- @Override
- public boolean parse(final String source, final ParsePosition pos, final
Calendar calendar) {
- final ListIterator<StrategyAndWidth> lt = patterns.listIterator();
- while (lt.hasNext()) {
- final StrategyAndWidth strategyAndWidth = lt.next();
- final int maxWidth = strategyAndWidth.getMaxWidth(lt);
- if (!strategyAndWidth.strategy.parse(this, calendar, source, pos,
maxWidth)) {
- return false;
- }
- }
- return true;
- }
-
- // Support for strategies
- //-----------------------------------------------------------------------
-
- private static StringBuilder simpleQuote(final StringBuilder sb, final
String value) {
- for (int i = 0; i < value.length(); ++i) {
- final char c = value.charAt(i);
- switch (c) {
- case '\\':
- case '^':
- case '$':
- case '.':
- case '|':
- case '?':
- case '*':
- case '+':
- case '(':
- case ')':
- case '[':
- case '{':
- sb.append('\\');
- default:
- sb.append(c);
- }
- }
- return sb;
- }
-
- /**
- * Get the short and long values displayed for a field
- * @param cal The calendar to obtain the short and long values
- * @param locale The locale of display names
- * @param field The field of interest
- * @param regex The regular expression to build
- * @return The map of string display names to field values
- */
- private static Map<String, Integer> appendDisplayNames(final Calendar cal,
final Locale locale, final int field, final StringBuilder regex) {
- final Map<String, Integer> values = new HashMap<>();
-
- final Map<String, Integer> displayNames = cal.getDisplayNames(field,
Calendar.ALL_STYLES, locale);
- final TreeSet<String> sorted = new TreeSet<>(LONGER_FIRST_LOWERCASE);
- for (final Map.Entry<String, Integer> displayName :
displayNames.entrySet()) {
- final String key = displayName.getKey().toLowerCase(locale);
- if (sorted.add(key)) {
- values.put(key, displayName.getValue());
- }
- }
- for (final String symbol : sorted) {
- simpleQuote(regex, symbol).append('|');
- }
- return values;
- }
-
- /**
- * Adjust dates to be within appropriate century
- * @param twoDigitYear The year to adjust
- * @return A value between centuryStart(inclusive) to
centuryStart+100(exclusive)
- */
- private int adjustYear(final int twoDigitYear) {
- final int trial = century + twoDigitYear;
- return twoDigitYear >= startYear ? trial : trial + 100;
- }
-
- /**
- * A strategy to parse a single field from the parsing pattern
- */
- private static abstract class Strategy {
- /**
- * Is this field a number?
- * The default implementation returns false.
- *
- * @return true, if field is a number
- */
- boolean isNumber() {
- return false;
- }
-
- abstract boolean parse(FastDateParser parser, Calendar calendar,
String source, ParsePosition pos, int maxWidth);
- }
-
- /**
- * A strategy to parse a single field from the parsing pattern
- */
- private static abstract class PatternStrategy extends Strategy {
-
- private Pattern pattern;
-
- void createPattern(final StringBuilder regex) {
- createPattern(regex.toString());
- }
-
- void createPattern(final String regex) {
- this.pattern = Pattern.compile(regex);
- }
-
- /**
- * Is this field a number?
- * The default implementation returns false.
- *
- * @return true, if field is a number
- */
- @Override
- boolean isNumber() {
- return false;
- }
-
- @Override
- boolean parse(final FastDateParser parser, final Calendar calendar,
final String source, final ParsePosition pos, final int maxWidth) {
- final Matcher matcher =
pattern.matcher(source.substring(pos.getIndex()));
- if (!matcher.lookingAt()) {
- pos.setErrorIndex(pos.getIndex());
- return false;
- }
- pos.setIndex(pos.getIndex() + matcher.end(1));
- setCalendar(parser, calendar, matcher.group(1));
- return true;
- }
-
- abstract void setCalendar(FastDateParser parser, Calendar cal, String
value);
- }
-
- /**
- * Obtain a Strategy given a field from a SimpleDateFormat pattern
- * @param formatField A sub-sequence of the SimpleDateFormat pattern
- * @param definingCalendar The calendar to obtain the short and long values
- * @return The Strategy that will handle parsing for the field
- */
- private Strategy getStrategy(final char f, final int width, final Calendar
definingCalendar) {
- switch(f) {
- default:
- throw new IllegalArgumentException("Format '"+f+"' not supported");
- case 'D':
- return DAY_OF_YEAR_STRATEGY;
- case 'E':
- return getLocaleSpecificStrategy(Calendar.DAY_OF_WEEK,
definingCalendar);
- case 'F':
- return DAY_OF_WEEK_IN_MONTH_STRATEGY;
- case 'G':
- return getLocaleSpecificStrategy(Calendar.ERA, definingCalendar);
- case 'H': // Hour in day (0-23)
- return HOUR_OF_DAY_STRATEGY;
- case 'K': // Hour in am/pm (0-11)
- return HOUR_STRATEGY;
- case 'M':
- return width >= 3 ? getLocaleSpecificStrategy(Calendar.MONTH,
definingCalendar) : NUMBER_MONTH_STRATEGY;
- case 'S':
- return MILLISECOND_STRATEGY;
- case 'W':
- return WEEK_OF_MONTH_STRATEGY;
- case 'a':
- return getLocaleSpecificStrategy(Calendar.AM_PM, definingCalendar);
- case 'd':
- return DAY_OF_MONTH_STRATEGY;
- case 'h': // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0
- return HOUR12_STRATEGY;
- case 'k': // Hour in day (1-24), i.e. midnight is 24, not 0
- return HOUR24_OF_DAY_STRATEGY;
- case 'm':
- return MINUTE_STRATEGY;
- case 's':
- return SECOND_STRATEGY;
- case 'u':
- return DAY_OF_WEEK_STRATEGY;
- case 'w':
- return WEEK_OF_YEAR_STRATEGY;
- case 'y':
- case 'Y':
- return width > 2 ? LITERAL_YEAR_STRATEGY :
ABBREVIATED_YEAR_STRATEGY;
- case 'X':
- return ISO8601TimeZoneStrategy.getStrategy(width);
- case 'Z':
- if (width==2) {
- return ISO8601TimeZoneStrategy.ISO_8601_3_STRATEGY;
- }
- //$FALL-THROUGH$
- case 'z':
- return getLocaleSpecificStrategy(Calendar.ZONE_OFFSET,
definingCalendar);
- }
- }
-
- @SuppressWarnings("unchecked") // OK because we are creating an array with
no entries
- private static final ConcurrentMap<Locale, Strategy>[] caches = new
ConcurrentMap[Calendar.FIELD_COUNT];
-
- /**
- * Get a cache of Strategies for a particular field
- * @param field The Calendar field
- * @return a cache of Locale to Strategy
- */
- private static ConcurrentMap<Locale, Strategy> getCache(final int field) {
- synchronized (caches) {
- if (caches[field] == null) {
- caches[field] = new ConcurrentHashMap<>(3);
- }
- return caches[field];
- }
- }
-
- /**
- * Construct a Strategy that parses a Text field
- * @param field The Calendar field
- * @param definingCalendar The calendar to obtain the short and long values
- * @return a TextStrategy for the field and Locale
- */
- private Strategy getLocaleSpecificStrategy(final int field, final Calendar
definingCalendar) {
- final ConcurrentMap<Locale, Strategy> cache = getCache(field);
- Strategy strategy = cache.get(locale);
- if (strategy == null) {
- strategy = field == Calendar.ZONE_OFFSET
- ? new TimeZoneStrategy(locale)
- : new CaseInsensitiveTextStrategy(field, definingCalendar,
locale);
- final Strategy inCache = cache.putIfAbsent(locale, strategy);
- if (inCache != null) {
- return inCache;
- }
- }
- return strategy;
- }
-
- /**
- * A strategy that copies the static or quoted field in the parsing pattern
- */
- private static class CopyQuotedStrategy extends Strategy {
-
- final private String formatField;
-
- /**
- * Construct a Strategy that ensures the formatField has literal text
- * @param formatField The literal text to match
- */
- CopyQuotedStrategy(final String formatField) {
- this.formatField = formatField;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- boolean isNumber() {
- return false;
- }
-
- @Override
- boolean parse(final FastDateParser parser, final Calendar calendar,
final String source, final ParsePosition pos, final int maxWidth) {
- for (int idx = 0; idx < formatField.length(); ++idx) {
- final int sIdx = idx + pos.getIndex();
- if (sIdx == source.length()) {
- pos.setErrorIndex(sIdx);
- return false;
- }
- if (formatField.charAt(idx) != source.charAt(sIdx)) {
- pos.setErrorIndex(sIdx);
- return false;
- }
- }
- pos.setIndex(formatField.length() + pos.getIndex());
- return true;
- }
- }
-
- /**
- * A strategy that handles a text field in the parsing pattern
- */
- private static class CaseInsensitiveTextStrategy extends PatternStrategy {
- private final int field;
- final Locale locale;
- private final Map<String, Integer> lKeyValues;
-
- /**
- * Construct a Strategy that parses a Text field
- * @param field The Calendar field
- * @param definingCalendar The Calendar to use
- * @param locale The Locale to use
- */
- CaseInsensitiveTextStrategy(final int field, final Calendar
definingCalendar, final Locale locale) {
- this.field = field;
- this.locale = locale;
-
- final StringBuilder regex = new StringBuilder();
- regex.append("((?iu)");
- lKeyValues = appendDisplayNames(definingCalendar, locale, field,
regex);
- regex.setLength(regex.length()-1);
- regex.append(")");
- createPattern(regex);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void setCalendar(final FastDateParser parser, final Calendar cal,
final String value) {
- final Integer iVal = lKeyValues.get(value.toLowerCase(locale));
- cal.set(field, iVal.intValue());
- }
- }
-
-
- /**
- * A strategy that handles a number field in the parsing pattern
- */
- private static class NumberStrategy extends Strategy {
- private final int field;
-
- /**
- * Construct a Strategy that parses a Number field
- * @param field The Calendar field
- */
- NumberStrategy(final int field) {
- this.field= field;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- boolean isNumber() {
- return true;
- }
-
- @Override
- boolean parse(final FastDateParser parser, final Calendar calendar,
final String source, final ParsePosition pos, final int maxWidth) {
- int idx = pos.getIndex();
- int last = source.length();
-
- if (maxWidth == 0) {
- // if no maxWidth, strip leading white space
- for (; idx < last; ++idx) {
- final char c = source.charAt(idx);
- if (!Character.isWhitespace(c)) {
- break;
- }
- }
- pos.setIndex(idx);
- } else {
- final int end = idx + maxWidth;
- if (last > end) {
- last = end;
- }
- }
-
- for (; idx < last; ++idx) {
- final char c = source.charAt(idx);
- if (!Character.isDigit(c)) {
- break;
- }
- }
-
- if (pos.getIndex() == idx) {
- pos.setErrorIndex(idx);
- return false;
- }
-
- final int value =
Integers.parseInt(source.substring(pos.getIndex(), idx));
- pos.setIndex(idx);
-
- calendar.set(field, modify(parser, value));
- return true;
- }
-
- /**
- * Make any modifications to parsed integer
- * @param parser The parser
- * @param iValue The parsed integer
- * @return The modified value
- */
- int modify(final FastDateParser parser, final int iValue) {
- return iValue;
- }
-
- }
-
- private static final Strategy ABBREVIATED_YEAR_STRATEGY = new
NumberStrategy(Calendar.YEAR) {
- /**
- * {@inheritDoc}
- */
- @Override
- int modify(final FastDateParser parser, final int iValue) {
- return iValue < 100 ? parser.adjustYear(iValue) : iValue;
- }
- };
-
- /**
- * A strategy that handles a timezone field in the parsing pattern
- */
- static class TimeZoneStrategy extends PatternStrategy {
- private static final String RFC_822_TIME_ZONE = "[+-]\\d{4}";
- private static final String GMT_OPTION= "GMT[+-]\\d{1,2}:\\d{2}";
-
- private final Locale locale;
- private final Map<String, TzInfo> tzNames= new HashMap<>();
-
- private static class TzInfo {
- TimeZone zone;
- int dstOffset;
-
- TzInfo(final TimeZone tz, final boolean useDst) {
- zone = tz;
- dstOffset = useDst ?tz.getDSTSavings() :0;
- }
- }
-
- /**
- * Index of zone id
- */
- private static final int ID = 0;
-
- /**
- * Construct a Strategy that parses a TimeZone
- * @param locale The Locale
- */
- TimeZoneStrategy(final Locale locale) {
- this.locale = locale;
-
- final StringBuilder sb = new StringBuilder();
- sb.append("((?iu)" + RFC_822_TIME_ZONE + "|" + GMT_OPTION );
-
- final Set<String> sorted = new TreeSet<>(LONGER_FIRST_LOWERCASE);
-
- final String[][] zones =
DateFormatSymbols.getInstance(locale).getZoneStrings();
- for (final String[] zoneNames : zones) {
- // offset 0 is the time zone ID and is not localized
- final String tzId = zoneNames[ID];
- if (tzId.equalsIgnoreCase("GMT")) {
- continue;
- }
- final TimeZone tz = TimeZone.getTimeZone(tzId);
- // offset 1 is long standard name
- // offset 2 is short standard name
- final TzInfo standard = new TzInfo(tz, false);
- TzInfo tzInfo = standard;
- for (int i = 1; i < zoneNames.length; ++i) {
- switch (i) {
- case 3: // offset 3 is long daylight savings (or
summertime) name
- // offset 4 is the short summertime name
- tzInfo = new TzInfo(tz, true);
- break;
- case 5: // offset 5 starts additional names, probably
standard time
- tzInfo = standard;
- break;
- }
- if (zoneNames[i] != null) {
- final String key = zoneNames[i].toLowerCase(locale);
- // ignore the data associated with duplicates supplied
in
- // the additional names
- if (sorted.add(key)) {
- tzNames.put(key, tzInfo);
- }
- }
- }
- }
- // order the regex alternatives with longer strings first, greedy
- // match will ensure longest string will be consumed
- for (final String zoneName : sorted) {
- simpleQuote(sb.append('|'), zoneName);
- }
- sb.append(")");
- createPattern(sb);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void setCalendar(final FastDateParser parser, final Calendar cal,
final String value) {
- if (value.charAt(0) == '+' || value.charAt(0) == '-') {
- final TimeZone tz = TimeZone.getTimeZone("GMT" + value);
- cal.setTimeZone(tz);
- } else if (value.regionMatches(true, 0, "GMT", 0, 3)) {
- final TimeZone tz =
TimeZone.getTimeZone(toRootUpperCase(value));
- cal.setTimeZone(tz);
- } else {
- final TzInfo tzInfo = tzNames.get(value.toLowerCase(locale));
- cal.set(Calendar.DST_OFFSET, tzInfo.dstOffset);
- cal.set(Calendar.ZONE_OFFSET, tzInfo.zone.getRawOffset());
- }
- }
- }
-
- private static class ISO8601TimeZoneStrategy extends PatternStrategy {
- // Z, +hh, -hh, +hhmm, -hhmm, +hh:mm or -hh:mm
-
- /**
- * Construct a Strategy that parses a TimeZone
- * @param pattern The Pattern
- */
- ISO8601TimeZoneStrategy(final String pattern) {
- createPattern(pattern);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void setCalendar(final FastDateParser parser, final Calendar cal,
final String value) {
- if (value.equals("Z")) {
- cal.setTimeZone(TimeZone.getTimeZone("UTC"));
- } else {
- cal.setTimeZone(TimeZone.getTimeZone("GMT" + value));
- }
- }
-
- private static final Strategy ISO_8601_1_STRATEGY = new
ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}))");
- private static final Strategy ISO_8601_2_STRATEGY = new
ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}\\d{2}))");
- private static final Strategy ISO_8601_3_STRATEGY = new
ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::)\\d{2}))");
-
- /**
- * Factory method for ISO8601TimeZoneStrategies.
- *
- * @param tokenLen a token indicating the length of the TimeZone
String to be formatted.
- * @return a ISO8601TimeZoneStrategy that can format TimeZone String
of length {@code tokenLen}. If no such
- * strategy exists, an IllegalArgumentException will be
thrown.
- */
- static Strategy getStrategy(final int tokenLen) {
- switch(tokenLen) {
- case 1:
- return ISO_8601_1_STRATEGY;
- case 2:
- return ISO_8601_2_STRATEGY;
- case 3:
- return ISO_8601_3_STRATEGY;
- default:
- throw new IllegalArgumentException("invalid number of X");
- }
- }
- }
-
- private static final Strategy NUMBER_MONTH_STRATEGY = new
NumberStrategy(Calendar.MONTH) {
- @Override
- int modify(final FastDateParser parser, final int iValue) {
- return iValue-1;
- }
- };
- private static final Strategy LITERAL_YEAR_STRATEGY = new
NumberStrategy(Calendar.YEAR);
- private static final Strategy WEEK_OF_YEAR_STRATEGY = new
NumberStrategy(Calendar.WEEK_OF_YEAR);
- private static final Strategy WEEK_OF_MONTH_STRATEGY = new
NumberStrategy(Calendar.WEEK_OF_MONTH);
- private static final Strategy DAY_OF_YEAR_STRATEGY = new
NumberStrategy(Calendar.DAY_OF_YEAR);
- private static final Strategy DAY_OF_MONTH_STRATEGY = new
NumberStrategy(Calendar.DAY_OF_MONTH);
- private static final Strategy DAY_OF_WEEK_STRATEGY = new
NumberStrategy(Calendar.DAY_OF_WEEK) {
- @Override
- int modify(final FastDateParser parser, final int iValue) {
- return iValue != 7 ? iValue + 1 : Calendar.SUNDAY;
- }
- };
- private static final Strategy DAY_OF_WEEK_IN_MONTH_STRATEGY = new
NumberStrategy(Calendar.DAY_OF_WEEK_IN_MONTH);
- private static final Strategy HOUR_OF_DAY_STRATEGY = new
NumberStrategy(Calendar.HOUR_OF_DAY);
- private static final Strategy HOUR24_OF_DAY_STRATEGY = new
NumberStrategy(Calendar.HOUR_OF_DAY) {
- @Override
- int modify(final FastDateParser parser, final int iValue) {
- return iValue == 24 ? 0 : iValue;
- }
- };
- private static final Strategy HOUR12_STRATEGY = new
NumberStrategy(Calendar.HOUR) {
- @Override
- int modify(final FastDateParser parser, final int iValue) {
- return iValue == 12 ? 0 : iValue;
- }
- };
- private static final Strategy HOUR_STRATEGY = new
NumberStrategy(Calendar.HOUR);
- private static final Strategy MINUTE_STRATEGY = new
NumberStrategy(Calendar.MINUTE);
- private static final Strategy SECOND_STRATEGY = new
NumberStrategy(Calendar.SECOND);
- private static final Strategy MILLISECOND_STRATEGY = new
NumberStrategy(Calendar.MILLISECOND);
-}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/Format.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/Format.java
index b81059b151..414ba9c4dc 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/Format.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/datetime/Format.java
@@ -17,8 +17,6 @@
package org.apache.logging.log4j.core.util.datetime;
import java.text.FieldPosition;
-import java.text.ParseException;
-import java.text.ParsePosition;
/**
* The basic methods for performing date formatting.
@@ -31,14 +29,4 @@ public abstract class Format {
public abstract StringBuilder format(Object obj, StringBuilder toAppendTo,
FieldPosition pos);
- public abstract Object parseObject (String source, ParsePosition pos);
-
- public Object parseObject(final String source) throws ParseException {
- final ParsePosition pos = new ParsePosition(0);
- final Object result = parseObject(source, pos);
- if (pos.getIndex() == 0) {
- throw new ParseException("Format.parseObject(String) failed",
pos.getErrorIndex());
- }
- return result;
- }
}
diff --git a/src/changelog/.2.x.x/remove_FastDateParser.xml
b/src/changelog/.2.x.x/remove_FastDateParser.xml
new file mode 100644
index 0000000000..f3b2f4f424
--- /dev/null
+++ b/src/changelog/.2.x.x/remove_FastDateParser.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://logging.apache.org/log4j/changelog"
+ xsi:schemaLocation="http://logging.apache.org/log4j/changelog
https://logging.apache.org/log4j/changelog-0.1.2.xsd"
+ type="removed">
+ <issue id="LOG4J2-3672"
link="https://issues.apache.org/jira/browse/LOG4J2-3672"/>
+ <issue id="1848" link="https://github.com/apache/logging-log4j2/pull/1848"/>
+ <description format="asciidoc">Removed unused `FastDateParser` which was
causing unnecessary heap overhead</description>
+</entry>
diff --git a/src/site/_release-notes/_2.x.x.adoc
b/src/site/_release-notes/_2.x.x.adoc
index cc91f1be77..56f75c4852 100644
--- a/src/site/_release-notes/_2.x.x.adoc
+++ b/src/site/_release-notes/_2.x.x.adoc
@@ -64,6 +64,10 @@ The module name of four bridges (`log4j-slf4j-impl`,
`log4j-slf4j2-impl`, `log4j
* Update `uk.org.webcompere:system-stubs-core` to version `2.0.3`
(https://github.com/apache/logging-log4j2/pull/1892[1892])
* Update Spring Framework from version 5.3.29 to 5.3.30;
+=== Removed
+
+* Removed unused `FastDateParser` which was causing unnecessary heap overhead
(https://issues.apache.org/jira/browse/LOG4J2-3672[LOG4J2-3672],
https://github.com/apache/logging-log4j2/pull/1848[1848])
+
=== Fixed
* Export missing OSGi & JPMS modules in `log4j-layout-template-json` and
`log4j-1.2-api` (https://github.com/apache/logging-log4j2/issues/1895[1895])