You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2012/02/29 02:07:22 UTC
svn commit: r1294922 - in /commons/proper/net/trunk/src: changes/changes.xml
main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java
Author: sebb
Date: Wed Feb 29 01:07:22 2012
New Revision: 1294922
URL: http://svn.apache.org/viewvc?rev=1294922&view=rev
Log:
NET-444 FTPTimestampParserImpl fails to parse future dates correctly on Feb 28th in a leap year
Modified:
commons/proper/net/trunk/src/changes/changes.xml
commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java
Modified: commons/proper/net/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/changes/changes.xml?rev=1294922&r1=1294921&r2=1294922&view=diff
==============================================================================
--- commons/proper/net/trunk/src/changes/changes.xml (original)
+++ commons/proper/net/trunk/src/changes/changes.xml Wed Feb 29 01:07:22 2012
@@ -62,6 +62,13 @@ The <action> type attribute can be add,u
-->
<body>
+ <release version="3.2" date="TBA" description="
+ ">
+TBA
+ <action issue="NET-444" dev="sebb" type="fix">
+ FTPTimestampParserImpl fails to parse future dates correctly on Feb 28th in a leap year.
+ </action>
+ </release>
<release version="3.1" date="Feb 20, 2012" description="
This release fixes a few bugs and adds some new functionality (see below).
It is binary compatible with previous releases
Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java?rev=1294922&r1=1294921&r2=1294922&view=diff
==============================================================================
--- commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java (original)
+++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java Wed Feb 29 01:07:22 2012
@@ -90,67 +90,58 @@ public class FTPTimestampParserImpl impl
* @since 1.5
*/
public Calendar parseTimestamp(String timestampStr, Calendar serverTime) throws ParseException {
- Calendar now = (Calendar) serverTime.clone();// Copy this, because we may change it
- now.setTimeZone(this.getServerTimeZone());
- Calendar working = (Calendar) now.clone();
+ Calendar working = (Calendar) serverTime.clone();
working.setTimeZone(getServerTimeZone()); // is this needed?
- ParsePosition pp = new ParsePosition(0);
Date parsed = null;
+
if (recentDateFormat != null) {
+ Calendar now = (Calendar) serverTime.clone();// Copy this, because we may change it
+ now.setTimeZone(this.getServerTimeZone());
if (lenientFutureDates) {
// add a day to "now" so that "slop" doesn't cause a date
// slightly in the future to roll back a full year. (Bug 35181 => NET-83)
now.add(Calendar.DATE, 1);
}
- parsed = recentDateFormat.parse(timestampStr, pp);
- }
- if (parsed != null && pp.getIndex() == timestampStr.length())
- {
- working.setTime(parsed);
- working.set(Calendar.YEAR, now.get(Calendar.YEAR));
-
- if (working.after(now)) {
- working.add(Calendar.YEAR, -1);
- }
- } else {
// Temporarily add the current year to the short date time
// to cope with short-date leap year strings.
// e.g. Java's DateFormatter will assume that "Feb 29 12:00" refers to
// Feb 29 1970 (an invalid date) rather than a potentially valid leap year date.
// This is pretty bad hack to work around the deficiencies of the JDK date/time classes.
- if (recentDateFormat != null) {
- pp = new ParsePosition(0);
- int year = now.get(Calendar.YEAR);
- String timeStampStrPlusYear = timestampStr + " " + year;
- SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy",
- recentDateFormat.getDateFormatSymbols());
- hackFormatter.setLenient(false);
- hackFormatter.setTimeZone(recentDateFormat.getTimeZone());
- parsed = hackFormatter.parse(timeStampStrPlusYear, pp);
- }
- if (parsed != null && pp.getIndex() == timestampStr.length() + 5) {
+ String year = Integer.toString(now.get(Calendar.YEAR));
+ String timeStampStrPlusYear = timestampStr + " " + year;
+ SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy",
+ recentDateFormat.getDateFormatSymbols());
+ hackFormatter.setLenient(false);
+ hackFormatter.setTimeZone(recentDateFormat.getTimeZone());
+ ParsePosition pp = new ParsePosition(0);
+ parsed = hackFormatter.parse(timeStampStrPlusYear, pp);
+ // Check if we parsed the full string, if so it must have been a short date originally
+ if (parsed != null && pp.getIndex() == timeStampStrPlusYear.length()) {
working.setTime(parsed);
- }
- else {
- pp = new ParsePosition(0);
- parsed = defaultDateFormat.parse(timestampStr, pp);
- // note, length checks are mandatory for us since
- // SimpleDateFormat methods will succeed if less than
- // full string is matched. They will also accept,
- // despite "leniency" setting, a two-digit number as
- // a valid year (e.g. 22:04 will parse as 22 A.D.)
- // so could mistakenly confuse an hour with a year,
- // if we don't insist on full length parsing.
- if (parsed != null && pp.getIndex() == timestampStr.length()) {
- working.setTime(parsed);
- } else {
- throw new ParseException(
- "Timestamp could not be parsed with older or recent DateFormat",
- pp.getErrorIndex());
+ if (working.after(now)) { // must have been last year instead
+ working.add(Calendar.YEAR, -1);
}
+ return working;
}
}
+
+ ParsePosition pp = new ParsePosition(0);
+ parsed = defaultDateFormat.parse(timestampStr, pp);
+ // note, length checks are mandatory for us since
+ // SimpleDateFormat methods will succeed if less than
+ // full string is matched. They will also accept,
+ // despite "leniency" setting, a two-digit number as
+ // a valid year (e.g. 22:04 will parse as 22 A.D.)
+ // so could mistakenly confuse an hour with a year,
+ // if we don't insist on full length parsing.
+ if (parsed != null && pp.getIndex() == timestampStr.length()) {
+ working.setTime(parsed);
+ } else {
+ throw new ParseException(
+ "Timestamp could not be parsed with older or recent DateFormat",
+ pp.getErrorIndex());
+ }
return working;
}
Modified: commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java?rev=1294922&r1=1294921&r2=1294922&view=diff
==============================================================================
--- commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java (original)
+++ commons/proper/net/trunk/src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java Wed Feb 29 01:07:22 2012
@@ -97,6 +97,25 @@ public class FTPTimestampParserImplTest
}
}
+ public void testNET444() throws Exception {
+ FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
+ parser.setLenientFutureDates(true);
+ SimpleDateFormat sdf = new SimpleDateFormat(parser.getRecentDateFormatString());
+ GregorianCalendar now = new GregorianCalendar(2012, Calendar.FEBRUARY, 28, 12, 0);
+
+ GregorianCalendar nowplus1 = new GregorianCalendar(2012, Calendar.FEBRUARY, 28, 13, 0);
+ // Create a suitable short date
+ String future1 = sdf.format(nowplus1.getTime());
+ Calendar parsed1 = parser.parseTimestamp(future1, now);
+ assertEquals(nowplus1.get(Calendar.YEAR), parsed1.get(Calendar.YEAR));
+
+ GregorianCalendar nowplus25 = new GregorianCalendar(2012, Calendar.FEBRUARY, 29, 13, 0);
+ // Create a suitable short date
+ String future25 = sdf.format(nowplus25.getTime());
+ Calendar parsed25 = parser.parseTimestamp(future25, now);
+ assertEquals(nowplus25.get(Calendar.YEAR) - 1, parsed25.get(Calendar.YEAR));
+ }
+
public void testParseTimestampAcrossTimeZones() {
@@ -174,8 +193,8 @@ public class FTPTimestampParserImplTest
fail("failed.to.parse.default");
}
try {
- parser.parseTimestamp("f\u00e9v 22 2002");
- fail("should.have.failed.to.parse.default");
+ Calendar c = parser.parseTimestamp("f\u00e9v 22 2002");
+ fail("should.have.failed.to.parse.default, but was: "+c.getTime().toString());
} catch (ParseException e) {
// this is the success case
}