You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ch...@apache.org on 2015/04/08 04:19:03 UTC
svn commit: r1671992 - in /commons/proper/lang/trunk/src: changes/
main/java/org/apache/commons/lang3/time/
test/java/org/apache/commons/lang3/time/
Author: chas
Date: Wed Apr 8 02:19:02 2015
New Revision: 1671992
URL: http://svn.apache.org/r1671992
Log:
LANG-1107 Fix parsing edge cases in FastDateParser
Modified:
commons/proper/lang/trunk/src/changes/changes.xml
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.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=1671992&r1=1671991&r2=1671992&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/changes/changes.xml [utf-8] (original)
+++ commons/proper/lang/trunk/src/changes/changes.xml [utf-8] Wed Apr 8 02:19:02 2015
@@ -22,7 +22,7 @@
<body>
<release version="3.5" date="tba" description="tba">
-
+ <action issue="LANG-1107" type="update" dev="chas">Fix parsing edge cases in FastDateParser</action>
</release>
<release version="3.4" date="2014-04-06" description="Feature and bugfix release">
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=1671992&r1=1671991&r2=1671992&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 Wed Apr 8 02:19:02 2015
@@ -744,9 +744,13 @@ public class FastDateParser implements D
/**
* A strategy that handles a timezone field in the parsing pattern
*/
- private static class TimeZoneStrategy extends Strategy {
-
- private final String validTimeZoneChars;
+ static class TimeZoneStrategy extends Strategy {
+ private static final String RFC_822_TIME_ZONE = "[+-]\\d{4}";
+ private static final String GMT_OPTION= "GMT[+-]\\d{1,2}:\\d{2}";
+ // see http://www.iana.org/time-zones and http://cldr.unicode.org/translation/timezones
+ static final String TZ_DATABASE= "(?:\\p{L}[\\p{L}\\p{Mc}\\p{Nd}\\p{Zs}\\p{P}&&[^-]]*-?\\p{Zs}?)*";
+ private static final String VALID_TZ = "((?iu)"+RFC_822_TIME_ZONE+"|"+GMT_OPTION+"|"+TZ_DATABASE+")";
+
private final SortedMap<String, TimeZone> tzNames= new TreeMap<String, TimeZone>(String.CASE_INSENSITIVE_ORDER);
/**
@@ -777,9 +781,6 @@ public class FastDateParser implements D
TimeZoneStrategy(final Locale locale) {
final String[][] zones = DateFormatSymbols.getInstance(locale).getZoneStrings();
for (final String[] zone : zones) {
- if (zone[ID].startsWith("GMT")) {
- continue;
- }
final TimeZone tz = TimeZone.getTimeZone(zone[ID]);
if (!tzNames.containsKey(zone[LONG_STD])){
tzNames.put(zone[LONG_STD], tz);
@@ -795,16 +796,7 @@ public class FastDateParser implements D
tzNames.put(zone[SHORT_DST], tz);
}
}
- }
-
- final StringBuilder sb= new StringBuilder();
- 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('|');
- }
- sb.setCharAt(sb.length()-1, ')');
- validTimeZoneChars= sb.toString();
+ }
}
/**
@@ -812,7 +804,7 @@ public class FastDateParser implements D
*/
@Override
boolean addRegex(final FastDateParser parser, final StringBuilder regex) {
- regex.append(validTimeZoneChars);
+ regex.append(VALID_TZ);
return true;
}
@@ -825,8 +817,8 @@ public class FastDateParser implements D
if(value.charAt(0)=='+' || value.charAt(0)=='-') {
tz= TimeZone.getTimeZone("GMT"+value);
}
- else if(value.startsWith("GMT")) {
- tz= TimeZone.getTimeZone(value);
+ else if(value.regionMatches(true, 0, "GMT", 0, 3)) {
+ tz= TimeZone.getTimeZone(value.toUpperCase());
}
else {
tz= tzNames.get(value);
Modified: 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=1671992&r1=1671991&r2=1671992&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java Wed Apr 8 02:19:02 2015
@@ -27,7 +27,6 @@ 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;
@@ -138,13 +137,11 @@ public class FastDateParserSDFTest {
}
@Test
- @Ignore // not currently supported
public void testLowerCase() throws Exception {
checkParse(input.toLowerCase(locale));
}
@Test
- @Ignore // not currently supported
public void testLowerCasePP() throws Exception {
checkParsePosition(input.toLowerCase(locale));
}
Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java?rev=1671992&r1=1671991&r2=1671992&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java Wed Apr 8 02:19:02 2015
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertFal
import static org.junit.Assert.assertTrue;
import java.io.Serializable;
+import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -30,6 +31,7 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
+import java.util.regex.Pattern;
import org.apache.commons.lang3.SerializationUtils;
import org.junit.Assert;
@@ -260,21 +262,21 @@ public class FastDateParserTest {
@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 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();
- 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));
- Assert.assertEquals("tz:"+tz.getID()+" locale:"+locale.getDisplayName(), expected, actual);
- }
- }
+ final Date actual = fdp.parse("2000/02/10 "+tz.getDisplayName(locale));
+ Assert.assertEquals("tz:"+tz.getID()+" locale:"+locale.getDisplayName(), expected, actual);
+ }
+ }
}
@@ -640,4 +642,19 @@ public class FastDateParserTest {
}
}
+ @Test
+ public void testTimeZoneStrategyPattern() {
+ Pattern tz = Pattern.compile(FastDateParser.TimeZoneStrategy.TZ_DATABASE);
+ Assert.assertFalse(tz.matcher("GMT-1234").matches());
+
+ for (Locale locale : Locale.getAvailableLocales()) {
+ final String[][] zones = DateFormatSymbols.getInstance(locale).getZoneStrings();
+ for (final String[] zone : zones) {
+ for (String zoneExpr : zone) {
+ Assert.assertTrue(locale.getDisplayName() + ":" + zoneExpr, tz.matcher(zoneExpr).matches());
+ }
+ }
+ }
+ }
+
}