Pro, I suggest you use Local DateTime instead of Date

Posted by barbatruc on Tue, 17 Sep 2019 09:09:10 +0200

Time processing is often encountered in project development, but are you really using it correctly? Understand that the Alibaba Development Manual forbids static s to modify SimpleDateFormat?

By reading this article, you will learn that:

  • Why do you need LocalDate, LocalTime, LocalDateTime [new class provided by Java 8]
  • The usage of Java 8's new time API, including creation, formatting, parsing, calculation and modification

Why do you need LocalDate, LocalTime, LocalDateTime

  • DateIf not formatted, the printed date is poorly readable

    Tue Sep 10 09:34:04 CST 2019
  • SimpleDateFormat is used to format time, but SimpleDateFormat is thread insecure

SimpleDateFormat's format method finally calls the code:

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 does not do thread safety control. When multiple threads invoke format methods simultaneously using the same SimpleDateFormat object (such as SimpleDateFormat modified with static), multiple threads invoke the calendar.setTime method at the same time. Perhaps one thread has just set the time value and another thread immediately changes the set time value to the formatting that results in the return. It may be wrong. Use of SimpleDateFormat in multiple concurrent situations requires special attention
Apart from the fact that format is thread insecure, the parse method is also thread insecure. Parse method actually calls alb.establish(calendar).getTime() method to parse, alb.establish(calendar) method is mainly completed.

- 1. Reset the attribute value of the date object cal
 - 2. Set cal using the middle attribute in calb
 - 3. Return the set cal object

But these three steps are not atomic operations.

How to Ensure Thread Safety in Multithread Concurrency

- Avoid sharing a `SimpleDateFormat'object between threads. It is expensive to create and destroy an `SimpleDateFormat' object => once per thread is used.
- Locking where `format'and `parse' methods are used=> Thread blocking performance is poor
 - A better way to use `ThreadLocal'to ensure that each thread creates `SimpleDateFormat `object=> at most once
  • Date has a lot of trouble with time processing, such as getting the time of a year, a month, a week, and n days later. If Date is used to process time, it's really difficult. You might say that Date class does not have getYear and getMonth methods. Obtaining the date of a month is Easy, but they are all abandoned.

Come On works with Java 8's new date and time API

LocalDate

Only year, month and day are available.

  • Create LocalDate

    //Get the current year, month and day
    LocalDate localDate = LocalDate.now();
    //Construct the specified year, month and day
    LocalDate localDate1 = LocalDate.of(2019, 9, 10);
  • Get the 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

It only takes a few minutes and seconds.

  • Create LocalTime

     LocalTime localTime = LocalTime.of(13, 51, 10);
     LocalTime localTime1 = LocalTime.now();
  • Get time and seconds

    //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.getMinute();
    int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
LocalDateTime

Get the year, month, day, time, second, equal to LocalDate+LocalTime

  • Create Local DateTime

    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 Instant Objects

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

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

    long currentMilli = instant.toEpochMilli();

Personally, I think it would be more convenient to use System.currentTimeMillis() just to get seconds or milliseconds.

Modify LocalDate, LocalTime, LocalDateTime, Instant

LocalDate, LocalTime, LocalDateTime, Instant are immutable objects. Modifying these object objects returns a copy.

  • Increase or decrease the number of years, months, days, etc.

Take Local DateTime as an example

LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10,
              14, 46, 56);
// Increase by one year
localDateTime = localDateTime.plusYears(1);
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
// Reduce by one month
localDateTime = localDateTime.minusMonths(1);
localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);  
  • Modify some values with

    //Revised year is 2019
    localDateTime = localDateTime.withYear(2020);
    //Amendment to 2022
    localDateTime = localDateTime.with(ChronoField.YEAR, 2022);

You can also modify the month and day.

Time calculation

For example, sometimes you want to know the date of 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, first DayOfYear () returns the date of the first day of the current date, and there are many ways not to illustrate here.

Formatting 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 a variety of formatting methods by default. If the default does not meet the requirements, you can create a custom formatting method through the DateTimeFormatter's ofPattern method.

Analytical time
LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);

Compared with SimpleDateFormat, DateTimeFormatter is thread-safe

Summary

Local DateTime: I have everything Date has, and I have everything Date does not have. Pick Me for date selection

Topics: Java Attribute