Repository: commons-lang Updated Branches: refs/heads/master cb83f7cb3 -> bea1ae92a
LANG-1116: DateUtilsTest.testLang530 fails for some timezones Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/bea1ae92 Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/bea1ae92 Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/bea1ae92 Branch: refs/heads/master Commit: bea1ae92aa52a985f8c171c6e17ff7fc4aa61fe4 Parents: cb83f7c Author: Chas Honton <[email protected]> Authored: Thu Apr 30 16:19:38 2015 -0700 Committer: Chas Honton <[email protected]> Committed: Thu Apr 30 16:19:38 2015 -0700 ---------------------------------------------------------------------- src/changes/changes.xml | 1 + .../apache/commons/lang3/time/DateUtils.java | 42 ++++++-------------- .../commons/lang3/time/FastDateParser.java | 26 +++++++++++- .../commons/lang3/time/DateFormatUtilsTest.java | 17 ++++++++ 4 files changed, 55 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-lang/blob/bea1ae92/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 27a7f5c..d75b9c6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ <body> <release version="3.5" date="tba" description="tba"> + <action issue="LANG-1116" type="fix" dev="chas" due-to="Aaron Sheldon">DateUtilsTest.testLang530 fails for some timezones</action> <action issue="LANG-1114" type="fix" dev="britter" due-to="Andy Coates">TypeUtils.ParameterizedType#equals doesn't work with wildcard types</action> <action issue="LANG-1119" type="add" dev="britter" due-to="Loic Guibert">Add rotate(string, int) method to StringUtils</action> <action issue="LANG-1118" type="fix" dev="britter" due-to="Loic Guibert">StringUtils.repeat('z', -1) throws NegativeArraySizeException</action> http://git-wip-us.apache.org/repos/asf/commons-lang/blob/bea1ae92/src/main/java/org/apache/commons/lang3/time/DateUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/lang3/time/DateUtils.java b/src/main/java/org/apache/commons/lang3/time/DateUtils.java index 74da2b6..0961073 100644 --- a/src/main/java/org/apache/commons/lang3/time/DateUtils.java +++ b/src/main/java/org/apache/commons/lang3/time/DateUtils.java @@ -18,12 +18,12 @@ package org.apache.commons.lang3.time; import java.text.ParseException; import java.text.ParsePosition; -import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.Locale; import java.util.NoSuchElementException; +import java.util.TimeZone; import java.util.concurrent.TimeUnit; /** @@ -365,37 +365,21 @@ public class DateUtils { if (str == null || parsePatterns == null) { throw new IllegalArgumentException("Date and Patterns must not be null"); } - - SimpleDateFormat parser; - if (locale == null) { - parser = new SimpleDateFormat(); - } else { - parser = new SimpleDateFormat("", locale); - } - - parser.setLenient(lenient); - final ParsePosition pos = new ParsePosition(0); - for (final String parsePattern : parsePatterns) { - - String pattern = parsePattern; - // LANG-530 - need to make sure 'ZZ' output doesn't get passed to SimpleDateFormat - if (parsePattern.endsWith("ZZ")) { - pattern = pattern.substring(0, pattern.length() - 1); - } - - parser.applyPattern(pattern); - pos.setIndex(0); + final TimeZone tz = TimeZone.getDefault(); + final Locale lcl = locale==null ?Locale.getDefault() : locale; + final ParsePosition pos = new ParsePosition(0); - String str2 = str; - // LANG-530 - need to make sure 'ZZ' output doesn't hit SimpleDateFormat as it will ParseException - if (parsePattern.endsWith("ZZ")) { - str2 = str.replaceAll("([-+][0-9][0-9]):([0-9][0-9])$", "$1$2"); + for (final String parsePattern : parsePatterns) { + FastDateParser fdp = new FastDateParser(parsePattern, tz, lcl, null, lenient); + try { + Date date = fdp.parse(str, pos); + if (pos.getIndex() == str.length()) { + return date; + } + pos.setIndex(0); } - - final Date date = parser.parse(str2, pos); - if (date != null && pos.getIndex() == str2.length()) { - return date; + catch(IllegalArgumentException iae) { } } throw new ParseException("Unable to parse the date: " + str, -1); http://git-wip-us.apache.org/repos/asf/commons-lang/blob/bea1ae92/src/main/java/org/apache/commons/lang3/time/FastDateParser.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java index 2d469a6..3f8d021 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java @@ -75,7 +75,7 @@ public class FastDateParser implements DateParser, Serializable { * * @see java.io.Serializable */ - private static final long serialVersionUID = 2L; + private static final long serialVersionUID = 3L; static final Locale JAPANESE_IMPERIAL = new Locale("ja","JP","JP"); @@ -85,6 +85,7 @@ public class FastDateParser implements DateParser, Serializable { private final Locale locale; private final int century; private final int startYear; + private final boolean lenient; // derived fields private transient Pattern parsePattern; @@ -106,7 +107,7 @@ public class FastDateParser implements DateParser, Serializable { * @param locale non-null locale */ protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale) { - this(pattern, timeZone, locale, null); + this(pattern, timeZone, locale, null, true); } /** @@ -121,11 +122,31 @@ public class FastDateParser implements DateParser, Serializable { * @since 3.3 */ protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) { + this(pattern, timeZone, locale, centuryStart, true); + } + + /** + * <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 + * @param lenient if true, non-standard values for Calendar fields should be accepted; + * if false, non-standard values will cause a ParseException to be thrown {@link CalendaretLenient(boolean)} + * + * @since 3.5 + */ + protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale, + final Date centuryStart, final boolean lenient) { this.pattern = pattern; this.timeZone = timeZone; this.locale = locale; + this.lenient = lenient; final Calendar definingCalendar = Calendar.getInstance(timeZone, locale); + int centuryStartYear; if(centuryStart!=null) { definingCalendar.setTime(centuryStart); @@ -336,6 +357,7 @@ public class FastDateParser implements DateParser, Serializable { // timing tests indicate getting new instance is 19% faster than cloning final Calendar cal= Calendar.getInstance(timeZone, locale); cal.clear(); + cal.setLenient(lenient); for(int i=0; i<strategies.length;) { final Strategy strategy= strategies[i++]; http://git-wip-us.apache.org/repos/asf/commons-lang/blob/bea1ae92/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java b/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java index b0a6b5d..5a1d69f 100644 --- a/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; +import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.Locale; @@ -268,4 +269,20 @@ public class DateFormatUtilsTest { String date = "2013-11-18T12:48:05Z"; DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.parse(date); } + + @Test + public void testLang530() throws ParseException { + TimeZone save = TimeZone.getDefault(); + try { + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + final Date d = new Date(); + final String isoDateStr = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(d); + final Date d2 = DateUtils.parseDate(isoDateStr, new String[] { DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern() }); + // the format loses milliseconds so have to reintroduce them + assertEquals("Date not equal to itself ISO formatted and parsed", d.getTime(), d2.getTime() + d.getTime() % 1000); + } + finally { + TimeZone.setDefault(save); + } + } }
