I want to do some formatting in my webapp, using MessageFormat, DateFormat, DecimalFormat, etc.
Since these are not thread-safe, one static instance for each usage won't work, but it seems wasteful to create a new XXXXFormat object each time one is needed. Caching and re-using them with a ThreadLocal seems like an obvious optimization.
This seems like a very common pattern, so I'm wondering if there are any appropriate libraries.
Instead of calling:
DecimalFormat formatter = new DecimalFormat("###,##0.00");
String formatted = formatter.format(value);
every time I need to format something, why not:
String formatted = FormatCache.formatDecimal("###,##0.00",numberValue);
where FormatCache would do the ThreadLocal caching with a HashMap keyed on the format pattern?
Presumably there'd be other methods like:
String FormatCache.formatDecimal(String, Number);
String FormatCache.formatDate(String, Date);
String FormatCache.formatMessage(String, Object...);
Cache a thread-safe DateTimeFormatter
object (immutable).
Never use SimpleDateFormat
. Use only java.time package for date-time work.
The troublesome old date-time classes such as DateFormat
& SimpleDateFormat
are now supplanted by the modern java.time classes. Specifically here, the DateTimeFormatter
class.
The java.time classes were designed to be Immutable Objects. This means that rather than modifying any content in the object, a new distinct object is generated. The original is left intact.
This, and other techniques, make the java.time classes thread-safe by design and are so documented.
DateTimeFormatter
DateTimeFormatter dateTimeFormatterFullQuébec = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
You can cache that object dateTimeFormatterFullQuébec
, keep it around.
ZoneId
Likewise, you could keep a ZoneId
time zone object cached.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId zoneMontréal = ZoneId.of( "America/Montreal" ) ;
Then use them any time, even across threads.
ZonedDateTime zdt = ZonedDateTime.now( zoneMontréal ) ;
String output = zdt.format( dateTimeFormatterFullQuébec ) ;
dimanche 4 mars 2018 à 18:36:32 Eastern Standard Time
The java.time objects such as ZonedDateTime
and Instant
are also immutable and thread-safe, just like the ZoneId
& DateTimeFormatter
. You can cache all of these, and use them across threads.
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With