Why is LocalDateTime recommended instead of Date?

Keywords: Programming Attribute SpringBoot

Change from: Why is LocalDateTime recommended instead of Date?

By reading this article you will learn:

  • Why do I need LocalDate, LocalTime and LocalDateTime

  • How to use java8's new time API, including creation, formatting, parsing, calculation and modification

Why LocalDate, LocalTime and LocalDateTime are needed

Date if not formatted, the printed date is not readable

Tue Sep 10 09:34:04 CST 2019

Use SimpleDateFormat to format the time, but SimpleDateFormat is the final calling code of the format method of SimpleDateFormat which is not thread safe:

private StringBuffer format(Date date, StringBuffer toAppendTo,FieldDelegate delegate) {

    // Convert input date to time field list

    boolean useDateFormatSymbols = useDateFormatSymbols();

    for (int i = 0; i < compiledPattern.length; ) {
        int tag = compiledPattern[i] >>> 8;
        int count = compiledPattern[i++] & 0xff;
        if (count == 255) {
            count = compiledPattern[i++] << 16;
            count |= compiledPattern[i++];

        switch (tag) {
        case TAG_QUOTE_ASCII_CHAR:
        case TAG_QUOTE_CHARS:
            toAppendTo.append(compiledPattern, i, count);
            i += count;
            subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
    return toAppendTo;


Calendar is a shared variable, and this shared variable is not under thread safety control. When multiple threads use the same SimpleDateFormat object (such as SimpleDateFormat decorated with static) to call the format method at the same time, multiple threads will call the calendar.setTime method at the same time. It is possible that one thread has just set the time value and another thread will immediately change the set time value to modify the returned format time, which may be wrong. When using SimpleDateFormat in multiple concurrent situations, it should be noted that SimpleDateFormat is not thread safe except for format, and parse method is thread unsafe. The parse method actually calls the alb.establish(calendar).getTime() method to parse, and the alb.establish(calendar) method mainly completes

  • Reset attribute value of date object cal

  • Set cal using the attribute in calb

  • Return the set cal object

But these three steps are not atomic operations

How to ensure thread safety in multithreading concurrency - avoid sharing a SimpleDateFormat object among threads, and create a SimpleDateFormat object once when each thread is used = > the cost of creating and destroying objects is large - lock the places where format and parse methods are used = > poor thread blocking performance - use ThreadLocal to ensure that each thread can create a simpledateform at most once At object = > a better method

Date is troublesome to process time. For example, if you want to get the time of a year, a month, a week, or n days later, it's too difficult to process it with date. You may say that the date class has getYear and getMonth methods. It's Easy to get the date, but they are all discarded

Using java8's new date and time API together


Only date

  • Create LocalDate

//Get current date
LocalDate localDate = LocalDate.now();

//Date of construction
LocalDate localDate1 = LocalDate.of(2019, 9, 10);
  • Get year, month, day, week

int year = localDate.getYear();
int year1 = localDate.get(ChronoField.YEAR);

Month month = localDate.getMonth();
int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);

int day = localDate.getDayOfMonth();
int day1 = localDate.get(ChronoField.DAY_OF_MONTH);

DayOfWeek dayOfWeek = localDate.getDayOfWeek();
int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);



Only a few minutes and seconds

  • Create LocalTime

LocalTime localTime = LocalTime.of(13, 51, 10);

LocalTime localTime1 = LocalTime.now();
  • Get time, minute and second

 //Acquisition hours
int hour = localTime.getHour();
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);

//Acquisition score
int minute = localTime.getMinute();
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);

//Get seconds
int second = localTime.getSecond();
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);



Get month, day, hour, minute and second, equal to LocalDate+LocalTime

  • Create LocalDateTime

LocalDateTime localDateTime = LocalDateTime.now();

LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);

LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);

LocalDateTime localDateTime3 = localDate.atTime(localTime);

LocalDateTime localDateTime4 = localTime.atDate(localDate);


  • Get LocalDate

LocalDate localDate2 = localDateTime.toLocalDate();
  • Get LocalTime

 LocalTime localTime2 = localDateTime.toLocalTime();



Get seconds

  • Create an Instant object

Instant instant = Instant.now();
  • Get seconds

long currentSecond = instant.getEpochSecond();
  • Get milliseconds

long currentMilli = instant.toEpochMilli();


I think it's more convenient to use System.currentTimeMillis() if it's just to get seconds or milliseconds


Modify LocalDate, LocalTime, LocalDateTime, Instant

LocalDate, LocalTime, LocalDateTime, and Instant are immutable objects. Modifying these object objects will return a copy

  • Increase or decrease the number of juveniles, months, days, etc. take LocalDateTime as an example

LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10,14, 46, 56);

//Increase for one year
localDateTime = localDateTime.plusYears(1);
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);

//Decrease by one month
localDateTime = localDateTime.minusMonths(1);
localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);  
  • Modify some values with

//Revised to 2019
localDateTime = localDateTime.withYear(2020);

//Revised to 2022
localDateTime = localDateTime.with(ChronoField.YEAR, 2022);

You can also modify the month and day


Time calculation

For example, if you want to know the last day of this month and the next weekend, you can get the answer quickly through the time and date API provided

LocalDate localDate = LocalDate.now();

LocalDate localDate1 = localDate.with(firstDayOfYear())

For example, the first day of the current date is returned through firstDayOfYear(). There are many other methods that are not illustrated here


Format time

LocalDate localDate = LocalDate.of(2019, 9, 10);

String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);

//Custom formatting
DateTimeFormatter dateTimeFormatter =   DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter)

DateTimeFormatter provides multiple formatting methods by default. If the default cannot meet the requirements, you can create a custom formatting method through the ofPattern method of DateTimeFormatter


Analytical time

LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);

LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE)

DateTimeFormatter is thread safe compared to SimpleDateFormat



LocalDateTime: I have all the dates, and I have none of the dates. Please pick me for the Date selection

Application of LocalDateTime in SpringBoot

  • Return the LocalDateTime field to the front end as a time stamp to add a date conversion class

Return the LocalDateTime field to the front end as a time stamp to add a date conversion class

public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> {

    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {


And add @ JsonSerialize(using=LocalDateTimeConverter.class) annotation on the LocalDateTime field, as follows:

@JsonSerialize(using = LocalDateTimeConverter.class)
protected LocalDateTime gmtModified;


  • Return the LocalDateTime field to the front end by specifying the format date. Add @ jsonformat (shape = jsonformat. Shape. String, pattern = "yyyy MM DD HH: mm: SS") annotation to the LocalDateTime field, as follows:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
protected LocalDateTime gmtModified;
  • Format the date passed in from the front end and add @ datetimeformat (pattern = "yyyy MM DD HH: mm: SS") annotation on the local datetime field, as follows:

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
protected LocalDateTime gmtModified;

Posted by imperialized on Wed, 06 Nov 2019 00:51:16 -0800