SoFunction
Updated on 2025-04-22

Detailed explanation of Java's solution to implement elegant date processing

Preface

In our daily work, we need to deal with various formats, various similar dates or times frequently.

For example: 2025-04-21, 2025/04/21, April 21, 2025, etc.

Some fields are of String type, some are of Date type, and some are of Long type.

If different data types often need to be converted to each other, if they are not processed properly, many unexpected problems may arise.

This article will talk to you about common problems in date processing and related solutions, and I hope it will be helpful to you.

1. The pit of date

1.1 Date Format Trap

At the beginning of the article, let me list a very classic date formatting problem:

// Old code snippets (classic writing of thread unsafe)public class OrderService {

  private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");*

    public void saveOrder(Order order) {
        // Thread A and thread B enter this method at the same time        String createTime = (()); 
        // There may be a date like "2023-02-30 12:00:00" that does not exist at all        (createTime);**
    }

}

Problem scene:

  • In the high concurrency flash sale scenario, 10 threads process orders at the same time.
  • The () obtained by each thread is 2023-02-28 23:59:59.
  • Due to thread scheduling order issues, a thread executes().
  • The internal Calendar instance has been modified to an illegal state by other threads.
  • An invalid date such as 2023-02-30 appears in the final database.

The root of the problem: SimpleDateFormat uses a shared Calendar instance internally, and multi-threaded concurrent modifications will cause data pollution.

1.2 Time zone conversion

When we process dates, we may also encounter problems with daylight saving time conversion:

// Error demonstration: simple addition and subtraction 8 hourspublic Date convertToBeijingTime(Date utcDate) {
    Calendar cal = ();
    (utcDate);
    (, 8); // The daylight saving time switching problem was not considered    return ();
}

Daylight saving time is a system that advances time by one hour during the summer season, aiming to make the most of the daylight and save energy.

In some countries and regions, the start and end time of daylight saving time is fixed.

In some countries and regions, adjustments may be made as needed.

In programming, we often need to deal with the issue of daylight saving time conversion to ensure the correctness of time.

Hidden danger analysis: On October 27, 2024, it will suddenly jump back to 1 o'clock in the morning of Beijing time, which will directly lead to an error in the calculation of the order time

2. The path to advancement of elegant solutions

2.1 Thread-safe refactoring

Before Java 8, ThreadLocal was generally used to solve the problem of date conversion in multi-thread scenarios.

For example, this is as follows:

// ThreadLocal packaging solution (suitable for JDK7 and below)public class SafeDateFormatter {
    private static final ThreadLocal<DateFormat> THREAD_LOCAL = (() -> 
        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    );

    public static String format(Date date) {
        return THREAD_LOCAL.get().format(date);
    }
}

Thread safety principle:

  • When each thread calls the format() method for the first time
  • A separate DateFormat instance will be created through the withInitial() initialization method.
  • The thread will directly reuse existing instances when it is called again.
  • When threads are destroyed, instances of ThreadLocal storage will be automatically cleaned.

Revealing the principle: Assign independent DateFormat instances to each thread through ThreadLocal to completely avoid thread safety issues.

2.2 Java8 Time API Revolution

After Java 8, the LocalDateTime class is provided to convert time, which is the officially recommended solution.

For example, this is as follows:

// New era writing method (thread safety + expression enhancement)public class ModernDateUtils {
    public static String format(LocalDateTime dateTime) {
        return (("yyyy-MM-dd HH:mm:ss"));
    }

    public static LocalDateTime parse(String str) {
        return (str, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
}

Black technology features

  • 288 predefined formatters
  • Support international standards such as ISO-8601/ZonedDateTime
  • Natural thread-safe for immutable objects

3. Advanced scenario solutions

3.1 Cross-time zone computing (must-have for multinational companies)

The following example calculates the business duration based on the time zone:

// Correct demonstration: Calculate business hours based on time zonepublic Duration calculateBusinessHours(ZonedDateTime start, ZonedDateTime end) {
    // Explicitly specify the time zone to avoid ambiguity    ZonedDateTime shanghaiStart = (("Asia/Shanghai"));
    ZonedDateTime newYorkEnd = (("America/New_York"));
    
    // Automatically handle daylight saving time switching    return (shanghaiStart, newYorkEnd);
}

The underlying principle: Maintain a complete time zone rule library (including historical change data) through ZoneId, and automatically handle daylight saving time switching.

3.2 Performance optimization practice

Solution for handling requests of average daily level:

// Precompiled mode (300% performance improvement)public class CachedDateFormatter {
    private static final Map<String, DateTimeFormatter> CACHE = new ConcurrentHashMap<>();

    public static DateTimeFormatter getFormatter(String pattern) {
        return (pattern, DateTimeFormatter::ofPattern);
    }
}

We can use static final precompilation mode to improve the performance of date conversion.

Performance comparison

plan Memory usage Time to initialize Format speed
Create a new Formatter every time 1.2GB 2.3s 1200 req/s
Precompiled cache 230MB 0.8s 5800 req/s

3.3 Global time zone context + interceptor

In order to facilitate the unified solution to time zone problems, we can use the global time zone context + interceptor.

For example, this is as follows:

// Global time zone context deliverypublic class TimeZoneContext {
    private static final ThreadLocal<ZoneId> CONTEXT_HOLDER = new ThreadLocal<>();

    public static void setTimeZone(ZoneId zoneId) {
        CONTEXT_HOLDER.set(zoneId);
    }

    public static ZoneId getTimeZone() {
        return CONTEXT_HOLDER.get();
    }
}

// Set time zone in Spring Boot interceptor@Component
public class TimeZoneInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String timeZoneId = ("X-Time-Zone");
        ((timeZoneId));
        return true;
    }
}

In addition, it is also necessary to pass the X-Time-Zone time zone parameter in the header of the request interface.

4. The underlying logic of elegant design

4.1 The principle of immutability

// LocalDate's immutable designLocalDate date = ();
(1); // Return to the new instance, the original object remains unchanged(date); // Output the current date, not affected

4.2 Functional programming thinking

// Stream API handles time seriesList<Transaction> transactions = 
    ()
        .filter(t -> ().isAfter(yesterday)) // Declarative filtering        .sorted((Transaction::getTimestamp)) // Natural sorting        .collect(()); // Delay execution

5. Summary

Here are the various solutions for date processing:

realm Code Features Typical Problem Repair cost
primary Use String splicing extensively Confused format/parsing exception high
Advanced Proficient in using the new JDK8 API Improper time zone handling middle
Expert Precompilation + cache + defensive programming Performance bottleneck Low
master Design time type in combination with domain model Business logic vulnerability Extremely low

Ultimate advice: In the microservice architecture, it is recommended to establish a unified time processing middleware to intercept all time-related operations through AOP to completely eliminate the time processing differences at the code level.

This is the end of this article about the detailed explanation of Java's implementation of elegant date processing. For more related Java date processing content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!