8

I have been debugging some existing code for which unit tests are failing on my system, but not on colleagues' systems. The root cause is that SimpleDateFormat is throwing ParseExceptions when parsing dates that should be parseable. I created a unit test that demonstrates the code that is failing on my system:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import junit.framework.TestCase;

public class FormatsTest extends TestCase {

    public void testParse() throws ParseException {
        DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS Z");
        formatter.setTimeZone(TimeZone.getDefault());
        formatter.setLenient(false);

        formatter.parse(formatter.format(new Date()));
    }
}

This test throws a ParseException on my system, but runs successfully on other systems.

java.text.ParseException: Unparseable date: "20100603100243.118 -0600"
    at java.text.DateFormat.parse(DateFormat.java:352)
    at FormatsTest.testParse(FormatsTest.java:16)

I have found that I can setLenient(true) and the test will succeed. The setLenient(false) is what is used in the production code that this test mimics, so I don't want to change it.

Greg
  • 33,450
  • 15
  • 93
  • 100
  • I am not sure but can you check the TimeZone as well? I think TimeZone can be based on the system, right? – vodkhang Jun 03 '10 at 16:00
  • I have updated my test class and stack trace in the original post to remove naming that was related to the application I found the bug in. The code was copied and pasted from my editor to the browser; the only editing was to indent the code by four spaces as required by Stack Overflow. Likewise with the stack trace, although I removed the lines of the stack trace that are calls in the test running harness. I can add those if you would like to see them. – Greg Jun 03 '10 at 16:08
  • what versions of the JDK are you using to compile and what version of the JRE are you running these on. that is mostl likely the issue. –  Jun 03 '10 at 16:11
  • @Fuzzy I don't think so. How could `format.parse(format.format(new Date()))` would possible throw ParseException in what ever JRE is running? – OscarRyz Jun 03 '10 at 16:14
  • I am using Rational Application Developer 7 to compile and run the tests. The project I am working on targets WebSphere 6.1, so I am running the tests within the IBM JRE associated with it: IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223-20060504 (JIT enabled). This is the same JRE that the rest of the team is using to run this same test, and the test succeeds on the other machines. I just tried running the test with a Sun Java 6 JRE (1.6.0_20), and the test runs successfully. I am not sure what to make of this. – Greg Jun 03 '10 at 16:23
  • your environment is not what you think it is in some way, that was my point about asking about JDK/JRE version. I recently had unit tests that iterated over a Map break when running against Java 6, they order of iteration of keySet() changed under the covers from 1.5 to 6. –  Jun 03 '10 at 16:39
  • @fuzzy lollipop That's why you don't rely on the iteration order of anything that doesn't specify its iteration order. – ColinD Jun 03 '10 at 16:44

3 Answers3

6

--- Edited after response indicating that the developer is using IBM's J9 1.5.0 Java Virtual Machine ---

IBM's J9 JVM seems to have a few bugs and incompatibilities in the parse routine of DateFormat, which SimpleDateFormat likely inherits because it is a subclass of DateFormat. Some evidence to support that IBM's J9 isn't functioning quite the way you might expect other JVMs (like Sun's HotSpot JVM) can be seen here.

Note that these bugs and incompatibilites are not even consistent within the J9 JVM, in other words, the IBM J9 formatting logic might actually generate formatted times that are not compatible with the IBM J9 parsing logic.

It seems that people who are tied to IBM's J9 JVM tend to work around the bug in the JVM by not using DateFormat.parse(...) (or SimpleDateFormat.parse(...)). Instead they tend to use java.util.regex.Matcher to parse the fields out manually.

Perhaps a later release of the J9 JVM fixes the issue, perhaps not.

--- Original post follows ---

Funny, the same code modified to:

import java.util.Date;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.text.ParseException;

public class FormatsTest {

 public void testParse() throws ParseException {
  DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS Z");
  formatter.setTimeZone(TimeZone.getDefault());
  formatter.setLenient(false);
  System.out.println(formatter.format(new Date()));

  formatter.parse(formatter.format(new Date()));
 }

 public static void main(String[] args) throws Exception {
   FormatsTest test = new FormatsTest();
   test.testParse();
 }

}

runs fine on my system. I would wager that it is something in your environment. Either you are compiling the code on one JVM major release and running it on another (which can cause some issues as the libraries could be out of date) or the system you are running it on might be reporting the time zone information oddly.

Finally, you might want to consider if you are using a very early point release of the JVM. Sometimes bugs do creep into the various versions, and they are fixed in later point releases. Could you please modify your question to include the "java -version" information for you system?

Either way, both of these are just educated guesses. The code should work as written.

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
  • java version "1.6.0_17" OpenJDK Runtime Environment (IcedTea 1.7.1) (fedora-37.b17.fc12-x86_64) OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode) – Edwin Buck Jun 03 '10 at 16:08
  • I get: 20100603101026.294 -0600 Exception in thread "main" java.text.ParseException: Unparseable date: "20100603101026.294 -0600" at java.text.DateFormat.parse(DateFormat.java:352) at FormatsTest.testParse(FormatsTest.java:15) at FormatsTest.main(FormatsTest.java:20) Using: java version "1.5.0" Java(TM) 2 Runtime Environment, Standard Edition (build pwi32dev-20060511 (SR2)) IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223-2006050 4 (JIT enabled) J9VM - 20060501_06428_lHdSMR JIT - 20060428_1800_r8 GC - 20060501_AA) JCL - 20060511a – Greg Jun 03 '10 at 16:13
  • I assume that's the same configuration your production environment has? – OscarRyz Jun 03 '10 at 16:21
  • original post edited, the issue is likely not on the compiler side of things, but in the java.util.DateFormat class in the IBM J9 version of the standard java library. – Edwin Buck Jun 03 '10 at 16:24
  • BTW, I agree that the code should work as written, and in fact is working as written on other computers that I have run it on. – Greg Jun 03 '10 at 16:24
  • @Greg Glad to hear it. It's pretty rare for the Java platform to have a bug like this in it, but it's all written by humans, and eventually mistakes are made. Welcome to your first Java platform bug. Raise an issue with IBM, they might have a fix already. If not then perhaps you can meet your goals by temporarily disabling the unit test while you determine if it is worthwhile to get the affected systems migrated to an unaffected JVM. – Edwin Buck Jun 03 '10 at 16:48
1

That should probably be a bug in IBM's J9 VM about the SimpleDateFormat class.

This post show a similar problem, and says it should be fixed on v6.

You may find the list of changes for several releases here.

I see there's a number related to DateFormat. So, you should probably raise a bug report or something with IBM for them to give you a patch.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • BTW, about those other computers, are they using the same configuration as yours? ( probably somebody installed Sun's JDK in their computer and that's why it's running well ) – OscarRyz Jun 03 '10 at 16:41
  • I checked around, and some people have a newer IBM JVM than I do, but they all are using the IBM JVM. I will try upgrading to see if it fixes the problem. – Greg Jun 03 '10 at 17:01
0

Check the LANG environment variable of your computer and of the remote computer.

The date is parsed according to the locale, so 'Jul' works as July only if your LANG is set to english, otherwise a ParseException is raised.

You can make a quick test by running export LANG="en_US.UTF-8" and then running your program.

You can also set the locale programmatically, by using the following method: DateFormat.getDateInstance(int, java.util.Locale)

David Riccitelli
  • 7,491
  • 5
  • 42
  • 56