Foreword
LocalDate, LocalTime and LocalDateTime are new date processing classes in JDK1.8, which can be faster A more elegant and thread-safe way to handle dates. DateTimeFormatter can customize the date format obtained based on LocalDate, LocalTime and LocalDateTime, and Thread Safety. This article will introduce its common usage.
Text
1. Get the current date and time
LocalDate, LocalTime and LocalDateTime provide the static method now() to get the current date and time.
LocalDate date = LocalDate.now(); LocalTime time = LocalTime. now(); LocalDateTime dateTime = LocalDateTime. now(); System.out.println("date: " + date.toString()); System.out.println("time: " + time.toString()); System.out.println("date time: " + dateTime.toString()); Copy Code
2. Date time format
Use DateTimeFormatter to format the obtained date and time according to the preset format.
1. Format LocalDate
DateTimeFormatter dateFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter dateFormatter2 = DateTimeFormatter.ofPattern("yyyyMMdd"); DateTimeFormatter dateFormatter3 = DateTimeFormatter.ofPattern("yyyy.MM.dd"); DateTimeFormatter dateFormatter4 = DateTimeFormatter.ofPattern("yyyy MM dd day"); LocalDate date = LocalDate.now(); System.out.println("date -> " + date.toString()); String formatDate1 = dateFormatter1. format(date); String formatDate2 = dateFormatter2. format(date); String formatDate3 = dateFormatter3. format(date); String formatDate4 = dateFormatter4. format(date); System.out.println("yyyy-MM-dd -> " + formatDate1); System.out.println("yyyyMMdd -> " + formatDate2); System.out.println("yyyy.MM.dd -> " + formatDate3); System.out.println("yyyy MM dd day -> " + formatDate4); Copy Code
2. Format LocalTime
DateTimeFormatter timeFormatter1 = DateTimeFormatter.ofPattern("HH:mm:ss"); DateTimeFormatter timeFormatter2 = DateTimeFormatter.ofPattern("HHmmss"); DateTimeFormatter timeFormatter3 = DateTimeFormatter.ofPattern("HH mm ss"); DateTimeFormatter timeFormatter4 = DateTimeFormatter.ofPattern("HH hour mm minute ss second"); LocalTime time = LocalTime. now(); System.out.println("time -> " + time.toString()); String formatTime1 = timeFormatter1. format(time); String formatTime2 = timeFormatter2. format(time); String formatTime3 = timeFormatter3. format(time); String formatTime4 = timeFormatter4. format(time); System.out.println("HH:mm:ss -> " + formatTime1); System.out.println("HHmmss -> " + formatTime2); System.out.println("HH mm ss -> " + formatTime3); System.out.println("HH hour mm minute ss second -> " + formatTime4); Copy Code
3. Format LocalDateTime
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); DateTimeFormatter dateTimeFormatter3 = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss"); DateTimeFormatter dateTimeFormatter4 = DateTimeFormatter.ofPattern("yyyy year MM month dd day HH hour mm minute ss second"); LocalDateTime dateTime = LocalDateTime. now(); System.out.println("date time -> " + dateTime); String formatDateTime1 = dateTimeFormatter1. format(dateTime); String formatDateTime2 = dateTimeFormatter2. format(dateTime); String formatDateTime3 = dateTimeFormatter3. format(dateTime); String formatDateTime4 = dateTimeFormatter4. format(dateTime); System.out.println("yyyy-MM-dd HH:mm:ss -> " + formatDateTime1); System.out.println("yyyyMMddHHmmss -> " + formatDateTime2); System.out.println("yyyy.MM.dd HH:mm:ss -> " + formatDateTime3); System.out.println("yyyy year MM month dd day HH hour mm minute ss second -> " + formatDateTime4); Copy Code
3. Date time string to LocalDateTime
You can also use DateTimeFormatter to read date and time strings in pre-formatted formats.
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); TemporalAccessor parsedDateTime = dateTimeFormatter. parse("2021-07-01 18:00:00"); LocalDateTime dateTime = LocalDateTime. from(parsedDateTime); Copy Code
4. Conversion between date and time
It is convenient to convert between LocalDate, LocalTime and LocalDateTime.
LocalDateTime dateTime = LocalDateTime.now(); LocalDate date = dateTime.toLocalDate(); LocalTime time = dateTime.toLocalTime(); LocalDateTime gotDateTime = LocalDateTime.of(date, time); System.out.println("date time: " + dateTime.toString()); System.out.println("date: " + date.toString()); System.out.println("time: " + time.toString()); System.out.println("getted date time: " + gottedDateTime.toString()); Copy Code
LocalDate, LocalTime and LocalDateTime provide the static method of() to construct itself to LocalDateTime< /strong> as an example, the method signature is as follows.
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute) public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second) public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute) public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second) public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) public static LocalDateTime of(LocalDate date, LocalTime time) Copy Code
5. Get the day of the year (month, week)
LocalDate and LocalDateTime can easily get the day of the year (month, week).
LocalDate date = LocalDate.now(); LocalDateTime dateTime = LocalDateTime. now(); int dateDayOfYear = date. getDayOfYear(); int dateTimeDayOfYear = dateTime. getDayOfYear(); System.out.println("date day of year: " + dateDayOfYear); System.out.println("date time day of year: " + dateTimeDayOfYear); int dateDayOfMonth = date. getDayOfMonth(); int dateTimeDayOfMonth = dateTime. getDayOfMonth(); System.out.println("date day of month: " + dateDayOfMonth); System.out.println("date time day of month: " + dateTimeDayOfMonth); DayOfWeek dateDayOfWeek = date. getDayOfWeek(); DayOfWeek dateTimeDayOfWeek = dateTime.getDayOfWeek(); System.out.println("date day of week: " + dateDayOfWeek.getValue()); System.out.println("date time day of week: " + dateTimeDayOfWeek.getValue()); Copy Code
6. Get the total number of days in a month
LocalDate and LocalDateTime can get the total number of days in a month, and the way to get it is as follows.
LocalDate date = LocalDate.now(); LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth()); System.out.println("days of month: " + lastDayOfMonth.getDayOfMonth()); LocalDateTime dateTime = LocalDateTime. now(); LocalDateTime lastDateTimeOfMonth = dateTime.with(TemporalAdjusters.lastDayOfMonth()); System.out.println("days of month: " + lastDateTimeOfMonth.getDayOfMonth()); Copy Code
7. Date and time addition and subtraction
LocalDate, LocalTime and LocalDateTime can add and subtract date and time. Take LocalDate as an example to illustrate.
LocalDate date = LocalDate.of(2021, 1, 1); LocalDate fiveDaysAgo = date. minus(5, ChronoUnit. DAYS); LocalDate fiveDaysLater = date. plus(5, ChronoUnit. DAYS); System.out.println("today: " + date.toString()); System.out.println("five days ago: " + fiveDaysAgo.toString()); System.out.println("five days later: " + fiveDaysLater.toString()); Copy Code
VIII. Date and time comparison
LocalDate, LocalTime and LocalDateTime can realize the comparison between dates and times, and LocalDate is used as an example to illustrate.
LocalDate date = LocalDate.of(2021, 1, 1); LocalDate fiveDaysAgo = date. minus(5, ChronoUnit. DAYS); LocalDate fiveDaysLater = date. plus(5, ChronoUnit. DAYS); System.out.println("compare result bwtween date and fiveDaysAgo: " + date.compareTo(fiveDaysAgo)); System.out.println("compare result bwtween date and fiveDaysLater: " + date.compareTo(fiveDaysLater)); System.out.println("compare result bwtween date and date: " + date.compareTo(date)); Copy Code
The result of the comparison is the difference between the two dates and times. By judging whether the comparison result is positive or negative, the order of the dates and times can be judged.
9. Timestamp processing
Take LocalDateTime as an example to demonstrate how to convert between LocalDateTime and timestamp (Pay attention to the processing of time zone).
1. Timestamp converted to LocalDateTime
The sample code is as follows.
public class LocalDateTimeLearnTest { @Test public void timestamp converted to formatted time() { DateTimeFormatter dateTimeFormatter = DateTimeFormatter .ofPattern("yyyy-MM-dd'T'HH:mm:ss"); // 2022-10-01T10:00:00 long timeStamp = 1664589600000L; LocalDateTime localDateTime_8 = LocalDateTime.ofEpochSecond( timeStamp / 1000, 0, ZoneOffset.ofHours(8)); LocalDateTime localDateTime_0 = LocalDateTime.ofEpochSecond( timeStamp / 1000, 0, ZoneOffset.ofHours(0)); System.out.println(dateTimeFormatter.format(localDateTime_8)); System.out.println(dateTimeFormatter.format(localDateTime_0)); } } Copy Code
The running results are as follows.
2. LocalDateTime conversion timestamp
The sample code is as follows.
public class LocalDateTimeLearnTest { @Test public void formatted time converted to timestamp() { DateTimeFormatter dateTimeFormatter = DateTimeFormatter .ofPattern("yyyy-MM-dd'T'HH:mm:ss"); // Get the formatted time LocalDateTime String dateTimeString = "2022-10-01T10:00:00"; TemporalAccessor temporalAccessor = dateTimeFormatter. parse(dateTimeString); LocalDateTime dateTime = LocalDateTime. from(temporalAccessor); // calculate timestamp long timeStamp_8 = dateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); long timeStamp_0 = dateTime.toInstant(ZoneOffset.ofHours(0)).toEpochMilli(); System.out.println("Dongba district time stamp:" + timeStamp_8); System.out.println("Zero time zone timestamp:" + timeStamp_0); // Calculate the hours difference between East Eight District and zero time zone long diff = (timeStamp_0 - timeStamp_8) / 1000 / 60 / 60; System.out.println("The hours difference between East Eighth District and zero time zone:" + diff); } } Copy Code
The running results are as follows.
10. Why thread safety
First explain why SimpleDateFormat thread is not safe. It is known that SimpleDateFormat is a class for formatting and analyzing Date. When the SimpleDateFormat object is declared as a static variable, SimpleDateFormat< /strong> Object usage is thread-unsafe. Take the format() method of SimpleDateFormat as an example to see its implementation.
The format() method will eventually call the following implementation.
private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) { // Called thread-unsafe Calendar object 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 Code
calendar is a Calendar object inherited from the parent class DateFormat by SimpleDateFormat, if SimpleDateFormat If the object is declared as a static variable, there will be multiple threads using the SimpleDateFormat object at the same time, so multiple threads call the format() method of SimpleDateFormat at the same time , it will cause multiple threads to call the setTime() method of Calendar at the same time, and the threads will affect each other, so the thread is not safe. Let’s demonstrate it with a simple example.
public class PrintDate { private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); public void printDate(Date date) { System.out.println(Thread.currentThread().getName() + " -> " + sdf.format(date)); } } Copy Code
The test method is as follows.
public class PrintDateTest { private PrintDate printDate; @Before public void setUp() { printDate = new PrintDate(); } @Test public void givenMultiThreads_whenPrintDateBySimpleDateFormat_thenThreadUnsafe() { ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 2, 10, 10, TimeUnit. SECONDS, new ArrayBlockingQueue<>(15)); threadPool. execute(() -> { Date date = new Date(121, Calendar. JANUARY, 1); Thread.currentThread().setName(date.toString()); for (int i = 0; i < 50; i ++ ) { printDate. printDate(date); } }); threadPool. execute(() -> { Date date = new Date(121, Calendar. JANUARY, 2); Thread.currentThread().setName(date.toString()); for (int i = 0; i < 50; i ++ ) { printDate. printDate(date); } }); LockSupport. parkNanos(1000 * 1000 * 1000L); } } Copy Code
Enable two threads to cycle and call the printDate() method of PrintDate 50 times, and the result is as follows.
It was found that there was an inconsistency between the incoming date and the printed date. Indicates that the use of the SimpleDateFormat object is thread-unsafe when the SimpleDateFormat object is declared as a static variable
So why are LocalDate, LocalTime and LocalDateTime thread-safe. Let’s take a look at their field signatures.
LocalDate field signature.
public final class LocalDate implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable { // omitted private final int year; private final short month; private final short day; // omitted } Copy Code
LocalTime field signature.
public final class LocalTime implements Temporal, TemporalAdjuster, Comparable<LocalTime>, Serializable { // omitted private final byte hour; private final byte minute; private final byte second; private final int nano; // omitted } Copy Code
LocalDateTime field signature.
public final class LocalDateTime implements Temporal, TemporalAdjuster, ChronoLocalDateTime<LocalDate>, Serializable { // omitted private final LocalDate date; private final LocalTime time; // omitted } Copy Code
LocalDate, LocalTime and LocalDateTime field signatures for date and time are private final, which means that once they are specified date and time , it cannot be changed. Second, their changes to the datetime will return a new object. The thread-safe implementation of LocalDate, LocalTime and LocalDateTime is the same as the thread-safe implementation of String,
Summary
LocalDate, LocalTime and LocalDateTime are used more than Date, SimpleDateFormat and Calendar is more convenient and safe to use. Making good use of LocalDate, LocalTime and LocalDateTime can make the processing of date and time more elegant.