Author: niallp
Date: Sat Jan 30 17:49:28 2010
New Revision: 904829
URL: http://svn.apache.org/viewvc?rev=904829&view=rev
Log:
Port LANG-530 to 2.x branch - Fix parseDate() cannot parse ISO8601 dates
produced by FastDateFormat
Modified:
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/time/DateUtils.java
commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/time/DateUtilsTest.java
Modified:
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/time/DateUtils.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/time/DateUtils.java?rev=904829&r1=904828&r2=904829&view=diff
==============================================================================
---
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/time/DateUtils.java
(original)
+++
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/time/DateUtils.java
Sat Jan 30 17:49:28 2010
@@ -25,6 +25,8 @@
import java.util.NoSuchElementException;
import java.util.TimeZone;
+import org.apache.commons.lang.StringUtils;
+
/**
* <p>A suite of utilities surrounding the use of the
* {...@link java.util.Calendar} and {...@link java.util.Date} object.</p>
@@ -78,6 +80,9 @@
*/
public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;
+ /** Sign characters */
+ private static final char[] SIGN_CHARS = new char[] {'+', '-'};
+
/**
* This is half a month, so this represents whether a date is in the top
* or bottom half of the month.
@@ -286,19 +291,66 @@
SimpleDateFormat parser = null;
ParsePosition pos = new ParsePosition(0);
for (int i = 0; i < parsePatterns.length; i++) {
+
+ String pattern = parsePatterns[i];
+
+ // LANG-530 - need to make sure 'ZZ' output doesn't get passed to
SimpleDateFormat
+ if (parsePatterns[i].endsWith("ZZ")) {
+ pattern = pattern.substring(0, pattern.length() - 1);
+ }
+
if (i == 0) {
- parser = new SimpleDateFormat(parsePatterns[0]);
+ parser = new SimpleDateFormat(pattern);
} else {
- parser.applyPattern(parsePatterns[i]);
+ parser.applyPattern(pattern); // cannot be null if i != 0
}
pos.setIndex(0);
- Date date = parser.parse(str, pos);
- if (date != null && pos.getIndex() == str.length()) {
+
+ String str2 = str;
+ // LANG-530 - need to make sure 'ZZ' output doesn't hit
SimpleDateFormat as it will ParseException
+ if (parsePatterns[i].endsWith("ZZ")) {
+ int signIdx = indexOfSignChars(str2, 0);
+ while (signIdx >=0) {
+ str2 = reformatTimezone(str2, signIdx);
+ signIdx = indexOfSignChars(str2, ++signIdx);
+ }
+ }
+
+ Date date = parser.parse(str2, pos);
+ if (date != null && pos.getIndex() == str2.length()) {
return date;
}
}
throw new ParseException("Unable to parse the date: " + str, -1);
}
+ private static int indexOfSignChars(String str, int startPos) {
+ int idx = StringUtils.indexOf(str, '+', startPos);
+ if (idx < 0) {
+ idx = StringUtils.indexOf(str, '-', startPos);
+ }
+ return idx;
+ }
+
+ /**
+ * Reformat the timezone in a date string.
+ *
+ * @param str The input string
+ * @param signIdx The index position of the sign characters
+ * @return The reformatted string
+ */
+ private static String reformatTimezone(String str, int signIdx) {
+ String str2 = str;
+ if (signIdx >= 0 &&
+ signIdx + 5 < str.length() &&
+ Character.isDigit(str.charAt(signIdx + 1)) &&
+ Character.isDigit(str.charAt(signIdx + 2)) &&
+ str.charAt(signIdx + 3) == ':' &&
+ Character.isDigit(str.charAt(signIdx + 4)) &&
+ Character.isDigit(str.charAt(signIdx + 5))) {
+ str2 = str.substring(0, signIdx + 3) + str.substring(signIdx + 4);
+ }
+ return str2;
+ }
//-----------------------------------------------------------------------
/**
Modified:
commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/time/DateUtilsTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/time/DateUtilsTest.java?rev=904829&r1=904828&r2=904829&view=diff
==============================================================================
---
commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/time/DateUtilsTest.java
(original)
+++
commons/proper/lang/branches/LANG_2_X/src/test/java/org/apache/commons/lang/time/DateUtilsTest.java
Sat Jan 30 17:49:28 2010
@@ -1170,6 +1170,15 @@
TimeZone.setDefault(defaultZone);
}
+ // http://issues.apache.org/jira/browse/LANG-520
+ public void testLang520() throws ParseException {
+ Date d = new Date();
+ String isoDateStr =
DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(d);
+ 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);
+ }
+
/**
* Tests various values with the ceiling method
*/