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
             }