I suggest you use LocalDateTime instead of Date

Keywords: Java Attribute SpringBoot Docker

Time processing is often encountered in the process of project development, but do you really use it right? Do you understand that static decoration SimpleDateFormat is disabled in Alibaba development manual

By reading this article you will learn:

  • Why do I need LocalDate, LocalTime, LocalDateTime [java8's new class]
  • 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 thread unsafe The final calling code of the format method of SimpleDateFormat:

    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. Using SimpleDateFormat in multiple concurrent situations requires special attention SimpleDateFormat except that format is thread unsafe, the 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

      1. Reset attribute value of date object cal
      1. Set cal using the attribute in calb
      1. 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 between threads. Each thread creates a SimpleDateFormat object once when using it = > the cost of creating and destroying objects is high -Lock where format and parse methods are used = > poor thread blocking performance -Using ThreadLocal to ensure that each thread can only create a SimpleDateFormat object at most once = > 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

Come On uses 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 the day of the year, month, day and 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 for 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 Date selection

Application of LocalDateTime in SpringBoot
  • Return the LocalDateTime field to the front end as a time stamp Add 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;
  • Returns the LocalDateTime field to the front end in a way that specifies the formatted date Add @ jsonformat (shape = jsonformat. Shape. String, pattern = "yyyy MM DD HH: mm: SS") annotation on 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 Add @ datetimeformat (pattern = "yyyy MM DD HH: mm: SS") annotation on the LocalDateTime field, as follows:
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    protected LocalDateTime gmtModified;

Focus on the WeChat public. Programmer's dream ], focusing on Java, SpringBoot, SpringCloud, microservices, Docker, front and back end separation and other full stack technologies.

Posted by simwiz on Tue, 05 Nov 2019 10:29:45 -0800