26

Well aware of performance and thread issues with SimpleDateFormat, I decided to go with FastDateFormat, until I realized that FastDateFormat is for formatting only, no parsing!

Is there an alternative to FastDateFormat, that is ready to use out of the box and much faster than SimpleDateFormat?

I believe FastDateFormat is one of the faster ones, so anything that is about as fast would do.

Just curious , any idea why FastDateFormat does not support parsing? Doesn't it seriously limit its use?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Tom Tucker
  • 11,676
  • 22
  • 89
  • 130

6 Answers6

22

Note that since commons-lang 3.2, FastDateFormat supports parsing as well as printing.

See: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/time/FastDateFormat.html

Gareth
  • 503
  • 4
  • 9
  • surprise surprise, Apache has FastDateParser as well for parsing – ahaaman May 28 '14 at 07:59
  • 1
    I painfully discovered that the parsing is case sensitive. (10Jan10 works. 10JAN10 no). The bug is fixed in 3.4 but at the time of this comment I is not realeased or in Maven. Looking forward for it. https://issues.apache.org/jira/browse/LANG-996 – borjab Jul 31 '14 at 10:05
  • I may be wrong but as of 3.4 there seems to be no way to set the _lenient_ property of your FastDateParser to **false**. – ptha Mar 25 '16 at 14:32
21

At a best guess, it's to keep FastDateFormat... well... fast, by limiting it to display only.

Apache Commons DateUtils has a parseDate function, but that uses SimpleDateFormat internally.

An alternative is to use the JodaTime library. It's a complete replacement for dealing with DateFormat, Date, and Calendar objects.

JodaTime has a DateTimeFormatter that can be used to create DateTime objects (JodaTime's equivalent of Java's Date objects) from strings.

An example of how to use it is like this:

String strInputDateTime = "2010-12-27"; // An example, this would really come from outside
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd");
DateTime dt = fmt.parseDateTime(strInputDateTime);

I don't know if this is really any faster than SimpleDateFormat, though.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Powerlord
  • 87,612
  • 17
  • 125
  • 175
10

Found something interesting here of this case in Android: http://andmob.wikidot.com/faq-simpletimeformat

SimpleDateFormat, the first time you try parsing (or, presumably, formatting) a date, will load in all the timezone data for your locale. This will take 2-3 seconds. It is hoped that this will be fixed in some future edition of Android.

In the interim, consider using AsyncTask to "warm up" SimpleDateFormat in your process before you need it. Just parse some date in the AsyncTask doInBackground() to get it to load the timezones sometime when it will not impact the user so much. Once initialized in your process, SimpleDateFormat will run quickly until your process is terminated.

nhaarman
  • 98,571
  • 55
  • 246
  • 278
8

As of Java 8, one can use DateTimeFormatter along with the the Java 8 Time API to both parse and format dates. From the documentation:

This class is immutable and thread-safe.

It's recommended to use this class if possible for new work going forward instead of using SimpleDateFormat.

Mike
  • 1,791
  • 1
  • 17
  • 23
3

The 'problem' with SimpleDateFormat is not performance, its thread safety.

If you have thousands of threads and synchronizing is not an issue use synchronized (you can also pool the instances to alleviate this a little)

If you have a reasonable amount of threads the recommended way is to have a separate instance for each SimpleDateFormat.

UPDATE

As of Java 8, just use DateTimeFormatter. It is immutable, thread safe, faster, and more flexible. (It also offers nice features like default patterns for ISO-8601 date/time strings.)

jbx
  • 21,365
  • 18
  • 90
  • 144
  • Since SimpleDateFormat is thread-unsafe, you'd need to create a new instance or synchronize concurrent access to a shared instance. It's pretty slow either way. That's what I meant by performance issue. – Tom Tucker Dec 27 '10 at 20:59
  • Depends on your situation, but if you just need one (which is why I suppose you need a thread safe version), you can instantiate a new one at the beginning of each thread and reuse the same one within that thread. If you have thousands of threads being initialized then the overheads of creating a thread is much higher than creating the actual SimpleDateFormat object instance. – jbx Dec 27 '10 at 21:08
  • Simple: Always use ThreadLocal with SimpleDateFormat. (http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html) – Tim Büthe Jul 13 '11 at 08:00
  • 1
    If you are running in a web container, then you'll want to take care with the use of ThreadLocals: http://blog.maxant.co.uk/pebble/2008/09/23/1222200780000.html – michaelok Jun 05 '12 at 16:49
  • @michaelok AFAICT, TL can be used in a safe manner, but it's [pretty ugly](http://codereview.stackexchange.com/questions/62208/ugly-optimized-caching-of-simpledateformat). – maaartinus Sep 08 '14 at 04:28
1

Do you really need to parse dates that quickly? Have you tested SimpleDateFormat and found it too slow for your needs?

Note, there are a variety of ways to cache slow-to-construct, non-thread-safe class instances (e.g. ThreadLocal, pools).

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • I realize that there are some techniques that involve pooling or multi-threading, but I'm looking for something off the shelf. – Tom Tucker Dec 27 '10 at 21:00
  • what about my other question? have you confirmed that SimpleDateFormat is too slow for your needs? – jtahlborn Dec 27 '10 at 23:19
  • +1 for ThreadLocal and "do you really need performance here". – Tim Büthe Jul 13 '11 at 08:01
  • SimpleDateFormat is pretty slow, if you want to do intensive Date format and parsing for example serialize a big object tree to JSON String. SimpleDateFormat internally uses StringBuffer which is not optimal. – Jianwu Chen May 13 '15 at 14:44