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
-
Date
If not formatted, the printed date is poorly readableTue 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