Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SimpleDateFormat takes too long when the time zone is included

I am using this simple date format

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");

the problem is when I use this it takes too long to convert the time, in logcat I see something like this

I/Resources( 4284): Loaded time zone names for en in 272ms.
I/Resources( 4284): Loaded time zone names for en in 194ms.
I/Resources( 4284): Loaded time zone names for en in 112ms.
I/Resources( 4284): Loaded time zone names for en in 111ms.
I/Resources( 4284): Loaded time zone names for en in 113ms.
I/Resources( 4284): Loaded time zone names for en in 127ms.
I/Resources( 4284): Loaded time zone names for en in 253ms.
I/Resources( 4284): Loaded time zone names for en in 110ms.
I/Resources( 4284): Loaded time zone names for en in 154ms.
I/Resources( 4284): Loaded time zone names for en in 112ms.

How can I use simple date formater but to speed the things up, I do not want to take ~150ms for every conversion...

Does anybody had this problem before ?

like image 546
Lukap Avatar asked Jan 16 '12 14:01

Lukap


People also ask

What is the difference between DateFormat and SimpleDateFormat?

The java SimpleDateFormat allows construction of arbitrary non-localized formats. The java DateFormat allows construction of three localized formats each for dates and times, via its factory methods.

How do I add time zones to a date format?

Java SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") gives timezone as IST.

How do I change TimeZone in SimpleDateFormat?

SimpleDateFormat myDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); myDate. setTimeZone(TimeZone. getTimeZone("UTC")); Date newDate = myDate. parse("2010-05-23T09:01:02");

How to convert date to SimpleDateFormat in Java?

Creating A Simple Date Format A SimpleDateFormat is a concrete class for formatting and parsing dates in a locale-sensitive manner. String pattern = "yyyy-MM-dd" ; SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); The specified parameter “pattern” is the pattern used for formatting and parsing dates.


2 Answers

This is due to the lazy initialization of the timezone zone strings. Only the first call will take this long. If the SimpleDateFormat is used again afterwards it's loaded from cache and shouldn't take that long anymore.

Before this was changed it was done when the class was loaded and thus the start of an activity took those 2-3 seconds longer. This had a much worse impact on the user experience than if it takes those seconds when it's actually used the first time. The problem is that there's no way right now to circumvent this issue due to the design of the SimpleDateFormat api. Only faster phones might fix this by just taking less time to collect those strings.

The caching happens in the DateFormatSymbols that SimpleDateFormat is using. By reusing that instance it's possible to only have to load the stings once (for the same loale). You could also create that Instance in a thread at the startup of the activity so that it's already cached once it's used. To init the strings just call .hashCode() which does force initialize the cache. A bit faster but less simple would be to serialize the instance. This also forces the cache to be initialized.

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.

like image 116
Pulkit Goyal Avatar answered Sep 22 '22 04:09

Pulkit Goyal


This isn't true on recent releases of Android (and from the text of the log message I can tell that you're running an old release; modern releases tell you how much time was spent in icu4c versus managed code). Note that the answer from "Pulkit Goyal" was copy and pasted from http://code.google.com/p/android/issues/detail?id=3147 and the text refers to Donut. I've rewritten this code several times since then. Currently, en_US and the system's default locale (at boot time) are cached in the zygote. There's a further per-app cache so that for other locales you should only pay once.

The worst case in modern releases is where the user changes the system's default locale. It would require a restart of the zygote (a "runtime restart" or a reboot) to get the new default locale's time zone strings cached in the zygote where they could be shared. (i described this behavior in comment 11 on the bug, and it's shipped with ICS.)

like image 23
Elliott Hughes Avatar answered Sep 20 '22 04:09

Elliott Hughes