Author: sebb Date: Sun Mar 1 17:59:34 2015 New Revision: 1663140 URL: http://svn.apache.org/r1663140 Log: LANG-1061 FastDateParser error - timezones not handled correctly
Added: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java Modified: commons/proper/lang/trunk/src/changes/changes.xml commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java Modified: commons/proper/lang/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/changes/changes.xml?rev=1663140&r1=1663139&r2=1663140&view=diff ============================================================================== --- commons/proper/lang/trunk/src/changes/changes.xml [utf-8] (original) +++ commons/proper/lang/trunk/src/changes/changes.xml [utf-8] Sun Mar 1 17:59:34 2015 @@ -22,6 +22,7 @@ <body> <release version="3.4" date="tba" description="tba"> + <action issue="LANG-1061" type="fix" dev="sebb" due-to="dmeneses">FastDateParser error - timezones not handled correctly</action> <action issue="LANG-1087" type="fix" dev="britter" due-to="Renat Zhilkibaev">NumberUtils#createNumber() returns positive BigDecimal when negative Float is expected</action> <action issue="LANG-1081" type="fix" dev="britter" due-to="Jonathan Baker">DiffBuilder.append(String, Object left, Object right) does not do a left.equals(right) check</action> <action issue="LANG-1055" type="fix" dev="britter" due-to="Jonathan Baker">StrSubstitutor.replaceSystemProperties does not work consistently</action> Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java?rev=1663140&r1=1663139&r2=1663140&view=diff ============================================================================== --- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java (original) +++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java Sun Mar 1 17:59:34 2015 @@ -780,7 +780,8 @@ public class FastDateParser implements D } final StringBuilder sb= new StringBuilder(); - sb.append("(GMT[+\\-]\\d{0,1}\\d{2}|[+\\-]\\d{2}:?\\d{2}|"); + sb.append("(GMT[+-]\\d{1,2}:\\d{2}").append('|'); + sb.append("[+-]\\d{4}").append('|'); for(final String id : tzNames.keySet()) { escapeRegex(sb, id, false).append('|'); } Added: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java?rev=1663140&view=auto ============================================================================== --- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java (added) +++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java Sun Mar 1 17:59:34 2015 @@ -0,0 +1,118 @@ +package org.apache.commons.lang3.time; + +import static org.junit.Assert.*; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Compare FastDateParser with SimpleDateFormat + */ +@RunWith(Parameterized.class) +public class FastDateParserSDFTest { + + @Parameters(name= "{index}: {0} {1} {2}") + public static Collection<Object[]> data() { + return Arrays.asList(new Object [][]{ + // General Time zone tests + {"z yyyy", "GMT 2010", Locale.UK, true}, // no offset specified, but seems to be allowed + {"z yyyy", "GMT-123 2010", Locale.UK, false}, + {"z yyyy", "GMT-1234 2010", Locale.UK, false}, + {"z yyyy", "GMT-12:34 2010", Locale.UK, true}, + {"z yyyy", "GMT-1:23 2010", Locale.UK, true}, + // RFC 822 tests + {"z yyyy", "-1234 2010", Locale.UK, true}, + {"z yyyy", "-12:34 2010", Locale.UK, false}, + {"z yyyy", "-123 2010", Locale.UK, false}, + // year tests + { "MM/dd/yyyy", "01/11/12", Locale.UK, true}, + { "MM/dd/yy", "01/11/12", Locale.UK, true}, + }); + } + + private final String format; + private final String input; + private final Locale locale; + private final boolean valid; + + public FastDateParserSDFTest(String format, String input, Locale locale, boolean valid) { + this.format = format; + this.input = input; + this.locale = locale; + this.valid = valid; + } + + @Test + public void testOriginal() throws Exception { + final SimpleDateFormat sdf = new SimpleDateFormat(format, locale); + final TimeZone timeZone = TimeZone.getDefault(); + final DateParser fdf = new FastDateParser(format, timeZone, locale); + checkParse(locale, sdf, fdf, input); + } + + @Test + public void testUpperCase() throws Exception { + final SimpleDateFormat sdf = new SimpleDateFormat(format, locale); + final TimeZone timeZone = TimeZone.getDefault(); + final DateParser fdf = new FastDateParser(format, timeZone , locale); + checkParse(locale, sdf, fdf, input.toUpperCase(locale)); + } + + @Test + @Ignore // not currently supported + public void testLowerCase() throws Exception { + final SimpleDateFormat sdf = new SimpleDateFormat(format, locale); + final TimeZone timeZone = TimeZone.getDefault(); + final DateParser fdf = new FastDateParser(format, timeZone , locale); + checkParse(locale, sdf, fdf, input.toLowerCase(locale)); + } + + private void checkParse(final Locale locale, final SimpleDateFormat sdf, final DateParser fdf, final String formattedDate) throws ParseException { + Date expectedTime=null; + Class<?> sdfE = null; + try { + expectedTime = sdf.parse(formattedDate); + if (!valid) { + // Error in test data + throw new RuntimeException("Test data error: expected SDF parse to fail, but got " + expectedTime); + } + } catch (ParseException e) { + if (valid) { + // Error in test data + throw new RuntimeException("Test data error: expected SDF parse to succeed, but got " + e); + } + sdfE = e.getClass(); + } + Date actualTime = null; + Class<?> fdfE = null; + try { + actualTime = fdf.parse(formattedDate); + if (!valid) { + // failure in test + fail("Expected FDP parse to fail, but got " + actualTime); + } + } catch (ParseException e) { + if (valid) { + // failure in test + fail("Expected FDP parse to succeed, but got " + e); + } + fdfE = e.getClass(); + } + if (valid) { + assertEquals(locale.toString()+" "+formattedDate +"\n",expectedTime, actualTime); + } else { + assertEquals(locale.toString()+" "+formattedDate + " expected same Exception ", sdfE, fdfE); + } + } +}