in src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java [261:318]
public Calendar parseTimestamp(final String timestampStr, final Calendar serverTime) throws ParseException {
final Calendar working = (Calendar) serverTime.clone();
working.setTimeZone(getServerTimeZone()); // is this needed?
Date parsed;
if (recentDateFormat != null) {
final 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.DAY_OF_MONTH, 1);
}
// The Java SimpleDateFormat class uses the epoch year 1970 if not present in the input
// As 1970 was not a leap year, it cannot parse "Feb 29" correctly.
// Java 1.5+ returns Mar 1 1970
// Temporarily add the current year to the short date time
// to cope with short-date leap year strings.
// Since Feb 29 is more that 6 months from the end of the year, this should be OK for
// all instances of short dates which are +- 6 months from current date.
// TODO this won't always work for systems that use short dates +0/-12months
// e.g. if today is Jan 1 2001 and the short date is Feb 29
final String year = Integer.toString(now.get(Calendar.YEAR));
final String timeStampStrPlusYear = timestampStr + " " + year;
final SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy", recentDateFormat.getDateFormatSymbols());
hackFormatter.setLenient(false);
hackFormatter.setTimeZone(recentDateFormat.getTimeZone());
final 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);
if (working.after(now)) { // must have been last year instead
working.add(Calendar.YEAR, -1);
}
setPrecision(recentDateSmallestUnitIndex, working);
return working;
}
}
final 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())) {
throw new ParseException("Timestamp '" + timestampStr + "' could not be parsed using a server time of " + serverTime.getTime().toString(),
pp.getErrorIndex());
}
working.setTime(parsed);
setPrecision(defaultDateSmallestUnitIndex, working);
return working;
}