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 2019
Copy 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 date
LocalDate localDate = LocalDate.now();
// Construct the specified year, month and day
LocalDate localDate1 = LocalDate.of(2019, 9, 12);
// Get the year, month, day and day of the 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);
Copy the code
LocalTime will only get minutes and seconds
/ / create a LocalTime
LocalTime localTime = LocalTime.of(14, 14, 14);
LocalTime localTime1 = LocalTime.now();
// Get the hour
int hour = localTime.getHour();
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
/ / to get points
int minute = localTime.getMinute();
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
/ / for seconds
int second = localTime.getMinute();
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
Copy the code
LocalDateTime The value is the same as 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 a LocalTime
LocalTime 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 objects
Instant instant = Instant.now();
// Get the number of seconds
long currentSecond = instant.getEpochSecond();
// Get the number of milliseconds
long currentMilli = instant.toEpochMilli();
Copy the code
Duration Indicates a period of time
The duration.between () method creates a Duration object
LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 1, 00, 0, 0); / / 2017-01-01 00:00:00
LocalDateTime to = LocalDateTime.of(2019, Month.SEPTEMBER, 12, 14, 28, 0); / / the 2019-09-15 14:28:00
Duration duration = Duration.between(from, to); // Indicates the interval between from and to
long days = duration.toDays(); // Total number of days during this period
long hours = duration.toHours(); // The number of hours during this period
long minutes = duration.toMinutes(); // The number of minutes during this period
long seconds = duration.getSeconds(); // The number of seconds during this period
long milliSeconds = duration.toMillis(); // The number of milliseconds during this period
long nanoSeconds = duration.toNanos(); // The number of nanoseconds during this period
Copy 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 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 with
// Change the year to 2020
localDateTime = localDateTime.withYear(2020);
localDateTime = localDateTime.with(ChronoField.YEAR, 2020);
// Time count
// Get the first day of the year
LocalDate 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 formatting
DateTimeFormatter 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.