You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by rw...@apache.org on 2008/03/02 21:29:08 UTC

svn commit: r632831 - /commons/proper/net/trunk/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java

Author: rwinston
Date: Sun Mar  2 12:29:07 2008
New Revision: 632831

URL: http://svn.apache.org/viewvc?rev=632831&view=rev
Log:
NET-188

Modified:
    commons/proper/net/trunk/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java

Modified: commons/proper/net/trunk/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java?rev=632831&r1=632830&r2=632831&view=diff
==============================================================================
--- commons/proper/net/trunk/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java (original)
+++ commons/proper/net/trunk/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java Sun Mar  2 12:29:07 2008
@@ -6,7 +6,7 @@
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.commons.net.ftp.parser;
 
 import java.text.DateFormatSymbols;
@@ -22,6 +23,7 @@
 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;
@@ -71,44 +73,65 @@
 	public Calendar parseTimestamp(String timestampStr) throws ParseException {
 		Calendar now = Calendar.getInstance();
 		now.setTimeZone(this.getServerTimeZone());
-		
+
 		Calendar working = Calendar.getInstance();
-		working.setTimeZone(this.getServerTimeZone());
+		working.setTimeZone(getServerTimeZone());
 		ParsePosition pp = new ParsePosition(0);
 
 		Date parsed = null;
-		if (this.recentDateFormat != null) {
+		if (recentDateFormat != null) {
 			parsed = recentDateFormat.parse(timestampStr, pp);
 		}
 		if (parsed != null && pp.getIndex() == timestampStr.length()) 
 		{
 			working.setTime(parsed);
 			working.set(Calendar.YEAR, now.get(Calendar.YEAR));
-			
-			if (this.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)
-			    now.add(Calendar.DATE, 1);
+
+			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)
+				now.add(Calendar.DATE, 1);
 			}    
 			if (working.after(now)) {
 				working.add(Calendar.YEAR, -1);
 			}
 		} 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()) {
+			// 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 && 
+					new GregorianCalendar().isLeapYear(now.get(Calendar.YEAR))) {
+				pp = new ParsePosition(0);
+				int year = Calendar.getInstance().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) {
 				working.setTime(parsed);
-			} else {
-				throw new ParseException(
-					"Timestamp could not be parsed with older or recent DateFormat", 
-					pp.getIndex());
+			}
+			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());
+				}
 			}
 		}
 		return working;
@@ -257,3 +280,4 @@
         this.lenientFutureDates = lenientFutureDates;
     }
 }
+