Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

Converting dates to and from strings is a very common action in Java, so it’s easy to think of using the SimpleDateFormat class. Today we’ll talk about what’s wrong with this class and how we can handle converting dates to and from strings.

Let’s start with a piece of code that looks correct but actually has problems.

import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public final class DateUtils { public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); public static Date parse(String target) { try { return SIMPLE_DATE_FORMAT.parse(target); } catch (ParseException e) { e.printStackTrace(); } return null; } public static String format(Date target) { return SIMPLE_DATE_FORMAT.format(target); }}Copy the code

This code is fine in a single-threaded environment, but the problem is that the SimpleDateFormat class is not thread-safe and will report an error in a multi-threaded environment.

To do this, just make sure that each thread uses a different SimpleDateFormat object. An easier way to do this is to put the object definition statement inside the method body. This way, even with multithreading, every time a method is executed, a new Format object is created, and the method ends and the object disappears, so there’s definitely no security issue.

Of course, the above method is not recommended. In a large project, the transformation method may be called hundreds or thousands of times, creating recycled objects repeatedly, which can affect performance.

Prior to JDK1.8, we could use ThreadLocal to store SimpleDateFormat objects. Uh, we could think of ThreadLocal as a thread-private Map that stored objects exclusively for the thread. This way, each thread has its own Format object, and there are no security issues.

However, there is a better way to do this, and several thread-safe transformation classes are available in JDK1.8. DateTimeFormatter, OffsetDateTime, ZonedDateTime, LocalDateTime, LocalDate, and LocalTime. Here is a DateTimeFormatter in use.

import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class DateUtilsJava8 { public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); private DateUtilsJava8() {} public static LocalDate parse(String target) { return LocalDate.parse(target, DATE_TIME_FORMATTER); } public static String format(LocalDate target) { return target.format(DATE_TIME_FORMATTER); }}Copy the code

One more thing, why is the DateTimeFormatter thread-safe? Because it’s an immutable class, and immutable classes are inherently thread-safe.

Take a second look at the documentation for the DateTimeFormatter.

* This class is immutable and threadsafe. * * @since 1.8 */ public final class DateTimeFormatter {Copy the code

So forget SimpleDateFormat and use DateTimeFormatter. If not, use ThreadLocal wrapping.