Java 8: New time and date API

Prior to Java 8, all the time and date apis had various usage drawbacks. Therefore, it is recommended to use the new time and date API to explain the disadvantages of the old time and date API and the solutions, and the new Time and date API of Java 8.

Bugs in the old time and date API

Java’s java.util.Date and java.util.Calendar classes are poorly used, do not support time zones, and are not thread-safe.

Date If no format is used, the printed Date is not readable.

Thu Sep 12 13:47:34 CST 2019Copy the code

SimpleDateFormat can be used to format time, but SimpleDateFormat is not thread safe, SimpleDateFormat format method source as follows:

    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;    }Copy the code

Calendar is a shared variable, and this shared variable has no thread-safe control. When the format method is called by multiple threads using the same SimpleDateFormat object, the calendar. SetTime method is called by multiple threads simultaneously. It is possible that one thread has just set the time value and another thread changes the time value so that the formatting time returned may be incorrect.

Beware of using SimpleDateFormat in multiple concurrent scenarios.

SimpleDateFormat In addition to format being thread-safe, the parse method is thread-safe as well. The parse method actually calls alb.establish(calendar).getTime() to parse, which is mostly done in the alb.establish(calendar) method

• Reset the date object CAL’s property value • Set the CAL using the property in calb • Return the CAL object that was set

But these three steps are not atomic operations, so the resolved times can be wrong.

GetYear and getMonth are deprecated from the Date class. For example, if you want to obtain the Date of a year, a month, a week, or n days later, it is too difficult to use the Date class.

How to ensure thread safety in multi-threaded concurrency

Avoid sharing a SimpleDateFormat object between threads. The SimpleDateFormat object is created once for each thread

Locking where format and parse methods are used => Thread blocking performance is poor

Better to use ThreadLocal to ensure that each thread creates a SimpleDateFormat object at most once

Java 8’s new time and date API

Java 8’s date and time classes include LocalDate, LocalTime, Instant, Duration, and Period, all of which are included in the java.time package. This includes creating, formatting, parsing, calculating, and modifying. Let’s look at how to use it.

LocalDate will only get the year, month and day

/ / create a LocalDate// Get the current year, month and dateLocalDate localDate = LocalDate.now();// Construct the specified year, month and dayLocalDate localDate1 = LocalDate.of(2019, 9, 12);// Get the year, month, day and day of the weekint 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);Copy the code

LocalTime will only get minutes and seconds

/ / create a LocalTimeLocalTime localTime = LocalTime.of(14, 14, 14);LocalTime localTime1 = LocalTime.now();// Get the hourint hour = localTime.getHour();int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);/ / to get pointsint minute = localTime.getMinute();int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);/ / for secondsint second = localTime.getMinute();int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);Copy the code

LocalDateTime The value is the same as LocalDate + LocalTime

/ / create LocalDateTimeLocalDateTime 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 LocalDateLocalDate localDate2 = localDateTime.toLocalDate();/ / get a LocalTimeLocalTime localTime2 = localDateTime.toLocalTime();Copy the code

Instant Gets the number of seconds used to represent a timestamp (accurate to nanosecond)

To simply get the number of seconds or milliseconds, use System.currentTimemillis ().

// Create Instant objectsInstant instant = Instant.now();// Get the number of secondslong currentSecond = instant.getEpochSecond();// Get the number of millisecondslong currentMilli = instant.toEpochMilli();Copy the code

Duration Indicates a period of time

The duration.between () method creates a Duration objectLocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 1, 00, 0, 0); / / 2017-01-01 00:00:00LocalDateTime to = LocalDateTime.of(2019, Month.SEPTEMBER, 12, 14, 28, 0); / / the 2019-09-15 14:28:00Duration duration = Duration.between(from, to); // Indicates the interval between from and tolong days = duration.toDays(); // Total number of days during this periodlong hours = duration.toHours(); // The number of hours during this periodlong minutes = duration.toMinutes(); // The number of minutes during this periodlong seconds = duration.getSeconds(); // The number of seconds during this periodlong milliSeconds = duration.toMillis(); // The number of milliseconds during this periodlong nanoSeconds = duration.toNanos(); // The number of nanoseconds during this periodCopy the code

Modify LocalDate, LocalTime, LocalDateTime, and Instant.

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

Add or subtract years, months, days, etc., using LocalDateTime as an example:

LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 12, 14, 32, 0);// Add a yearlocalDateTime = localDateTime.plusYears(1);localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);// Reduce by one monthlocalDateTime = localDateTime.minusMonths(1);localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);  // Modify some values with with// Change the year to 2020localDateTime = localDateTime.withYear(2020);localDateTime = localDateTime.with(ChronoField.YEAR, 2020);// Time count// Get the first day of the yearLocalDate localDate = LocalDate.now();LocalDate localDate1 = localDate.with(firstDayOfYear());Copy the code

TemporalAdjusters contains a number of static methods that can be invoked directly, some of which are listed below:

The method name describe
dayOfWeekInMonth Returns the day of the week in the same month
firstDayOfMonth Returns the first day of the month
firstDayOfNextMonth Return to the first day of the next month
firstDayOfNextYear Return to the first day of the next year
firstDayOfYear Return to the first day of the year
firstInMonth Returns the first day of the month
lastDayOfMonth Returns the last day of the month
lastDayOfNextMonth Return to the last day of the next month
lastDayOfNextYear Return to the last day of the next year
lastDayOfYear Return to the last day of the year
lastInMonth Returns the last day of the month
next / previous Returns the day of the following/preceding given week
nextOrSame / previousOrSame Returns the next/previous given day of the week, or if the value meets the criteria

Formatting time

LocalDate localDate = LocalDate.of(2019, 9, 12);String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);// Custom formattingDateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String s3 = localDate.format(dateTimeFormatter);Copy the code

Parsing time

LocalDate localDate1 = LocalDate.parse("20190912", DateTimeFormatter.BASIC_ISO_DATE);LocalDate localDate2 = LocalDate.parse("2019-09-12", DateTimeFormatter.ISO_LOCAL_DATE);Copy the code

conclusion

Compared to SimpleDateFormat, DateTimeFormatter is thread-safe.

Instant is more accurate, down to nanoseconds.

Duration Indicates the number of days, hours, etc.

LocalDateTime can quickly get year, month, day, next month, etc.

The TemporalAdjusters class incorporates many of the usual static methods to avoid writing your own utility classes.