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
    calendar.setTime(date);

    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:
            toAppendTo.append((char)count);
            break;
        case TAG_QUOTE_CHARS:
            toAppendTo.append(compiledPattern, i, count);
            i += count;
            break;
        default:
            subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
            break;
        }
    }
    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

LocalDate

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);

 

LocalTime

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);

 

LocalDateTime

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();

 

Instant

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

 

Summary

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> {

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

    gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli());
    }
}

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