Java's SimpleDateFormat class provides a convenient method of parsing arbitrary strings into Date objects, and formatting Dates back into strings. However, like the rest of the standard Date/Time classes in the core API, there are a couple of important things you need to be aware of when working with this class. Ignore these caveats and there is a good chance you will be spending an inordinate amount of time debugging obscure issues with dates!
Can you guess the output of the following program?
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) throws Exception {
String fmt = "yyyyMMdd";
String testDate = "20080530";
Date dt = (new SimpleDateFormat(fmt)).parse
System.out.println(dt.toString());
testDate = "2008-05-30";
dt = (new SimpleDateFormat(fmt)).parse
System.
}
}
Believe it or not, it is:
Fri May 30 00:00:00 EDT 2008
Wed Dec 05 00:00:00 EST 2007
SimpleDateFormat will not throw an error if it receives string input which does not conform to its specified format string; it will instead silently construct an incorrect date! One possible solution (although I have seen cases where this also will not work) is:
DateFormat df = new SimpleDateFormat(fmt);
df.setLenient(false);
System.out.println(df.parse(testDate));
Resulting in:
Exception in thread "main" java.text.ParseException: Unparseable date: "2008-05-30"
at java.text.DateFormat.parse(Unknown Source)
at sandbox.DateTest.main(DateTest.java:23)
This should serve as a good example as any of the importance of good unit tests!
Lastly, it is also important to know that SimpleDateFormat is not thread-safe! This means that you must not use it as a member variable of a multithreaded service class, for example (Servlet, MessageDrivenBean, etc).
Since it can be expensive to keep instantiating a new SimpleDateFormat on each service request, a good practice is to store an instance in a ThreadLocal variable:
private ThreadLocal<DateFormat> myDateFormat = new ThreadLocal<DateFormat>(){
@Override protected DateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
2 comments:
Advice: use Joda-time.
Take a look at the spiffy framework. Its designed so you'll avoid pitfalls like that.
http://spiffyframework.sourceforge.net/
Post a Comment