Index: src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java =================================================================== --- src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java (revision 636484) +++ src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java (working copy) @@ -23,7 +23,6 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -import java.util.GregorianCalendar; import java.util.TimeZone; import org.apache.commons.net.ftp.Configurable; @@ -98,10 +97,22 @@ ParsePosition pp = new ParsePosition(0); Date parsed = null; + String timeStampStrPlusYear=""; if (recentDateFormat != null) { - parsed = recentDateFormat.parse(timestampStr, pp); + // 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. + int year = now.get(Calendar.YEAR); + 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()) + if (parsed != null && pp.getIndex() == timeStampStrPlusYear.length()) { working.setTime(parsed); working.set(Calendar.YEAR, now.get(Calendar.YEAR)); @@ -115,41 +126,21 @@ 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) { + 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 { - 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.getIndex()); - } + } else { + throw new ParseException( + "Timestamp could not be parsed with older or recent DateFormat", + pp.getIndex()); } } return working;