Johan's blog
Leap year issues in apache commons-net
I never encountered any real Y2K bugs in code I was involved in. Today, however, I ran into a nasty problem caused by date parsing in the apache commons-net library.
We have a project where files are being processed, xslt transformations are applied and so on. Some of these files have to be retrieved using FTP (I know...). We use the Apache commons-net 1.4.1 library for doing this.
Today, a number of files were not processed. I had to dive into the Apache code (Open Source is cool) to find the problem.
The method we are calling is this:
org.apache.commons.net.ftp.FTPClient.listFiles (String dir).
Following a long trail with engines and parsers, I discovered that the FTPFiles that are created get a Date that is obtained by parsing the date provided by the ftp server. The Unix ftp server returns the date in the format "MMM d HH:mm". No year info is supplied. This caused problems, of course, since Feb 29 is not a valid day in the default year 1970.
For those interested in the code: have a look at org.apache.commons.net.ftp.parser.FTPTimestampParserImpl.parseTimestamp(String s).
Fixing this is not too hard, but it is easier to manually change the date of the File back to Feb 28 23:59
I feel like it's April fools' day. I am curious how many other people run into a similar leap year issue.
comments:
Changing the dates solved my problem, although I agree it is a dirty way. But then, doing this every 4 year is ok ;)
I don't have my project code here at the moment, but if you want to solve it by changing the apache code, here is a quick way:
If I recall it correctly, the listFiles() returns a null entry for the files created on Feb 29. This is because somewhere in the code (e.g. UnixFTPEntryParser.parseFTPEntry(String entry), but this class might be dependend on what FTP Server you have), this ishappening:
try
{
file.setTimestamp(super.parseTimestamp(datestr));
}
catch (ParseException e)
{
return null; // this is a parsing failure too.
}
As a consequence, when the date can't be parsed, the complete entry is set to null. I think that removing this line ("return null") should solve it. But again, I can't test it right now. Another solution could be to change the ConfigurableFTPFileEntryParserImpl.parseTimestamp method in a way that it does not throw a ParseException when it cannot parse a date, but that it just silently ignores the error.
Or you can change the real parse code in such a way that the SimpleDateformat.parse works correctly.
Good luck!
