Still using SimpleDateFormat? Java 8 has been released for N years. Turn to Local DateTime.

Posted by marian on Sat, 17 Aug 2019 12:09:13 +0200

Preface

Java 8 has been released for several years, but it has been found that many people still insist on using Simple Date Format and Date for time manipulation. The SimpleDateFormat class is not thread-safe and can cause fatal problems if it is used with little attention. Date is a class that can reset the time, which is very unsafe for some of the internal attributes of the class.

SimpleDateFormat is a thread-insecure class

In the Alibaba Protocol Manual, SimpleDateFormat is mandatory as a thread-insecure class and must be locked when defined as a static variable. Ignoring thread safety is the point that most Java beginners are prone to tread holes in time conversion.

Date property can reset the time

For example, User.java is as follows:

public class User {private String username;private Date birthday;public User(String username, Date birthday) {
 this.username = username;
 this.birthday = birthday;
 }public String getUsername() {
 return username;
 }public void setUsername(String username) {
 this.username = username;
 }public Date getBirthday() {
 return birthday;
 }public void setBirthday(Date birthday) {
 this.birthday = birthday;
 }
}

We instantiate the User

public class Main {public static void main(String[] args) {
 User user = new User("happyjava", new Date());
 }}

Of course, that's not a problem, but I can get a reference to birthday through the user.getBirthday() method to modify the value of birthday directly. As follows:

public static void main(String[] args) {
 User user = new User("happyjava", new Date());
 System.out.println(user.getBirthday());
 Date birthday = user.getBirthday();
 birthday.setTime(11111111L);
 System.out.println(user.getBirthday());
}

The output results are as follows:

As you can see here, the birthday attribute of the user object has been modified. This is also the drawback of the Date object, which can be solved by rewriting the getter method to return a new Date object, as follows:

 public Date getBirthday() {
// return birthday;
 return new Date(birthday.getTime());
 }

Keep in mind that you can't use clone method to generate a new Date object, because the Date class can be inherited, you can't determine whether the caller has set a Date subclass for birthday.

New Time Class Library LocalDateTime provided by Java 8

Java 8 provides Local DateTime to replace traditional Date to handle time. Let's explore the use of this class library.

1. Get the current time

You can get the current time by using LocalDateTime localDateTime = LocalDateTime.now(); the test is as follows:

@Test
public void testNow() {
 LocalDateTime localDateTime = LocalDateTime.now();
 System.out.println(localDateTime);
}

Output results

2019-05-06T22:25:07.309

2. Initialization time based on Timestamp

@Test
public void testNewFromTimestamp() {
 Instant instant = Instant.ofEpochMilli(System.currentTimeMillis());
 LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.of("+8"));
 System.out.println(dateTime);
}

The + 8 here means the East Eighth District, the same as below.

Output results:

2019-05-06T22:27:34.567

3. Acquisition time based on strings

LocalDateTime.parse can be used to convert strings into time. If pattern is not passed, the default format is 2019-05-06T11:16:12.361.

@Test
public void testNewFromString() {
 // 1. Default format 2019-05-06T11:16:12.361
 String dateStr = "2019-05-06T11:16:12.361";
 LocalDateTime localDateTime = LocalDateTime.parse(dateStr);
 System.out.println(localDateTime);
 // 2. Custom Format
 String pattern = "yyyy-MM-dd HH:mm:ss";
 dateStr = "2019-01-01 12:12:12";
 localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
 System.out.println(localDateTime);
}

Output results:

2019-05-06T11:16:12.361
2019-01-01T12:12:12

4. Time is converted into strings

Local DateTime can be converted into a string through the format method of DateTimeFormatter.

@Test
public void testToString() {
 LocalDateTime now = LocalDateTime.now(ZoneId.of("+8"));
 String pattern = "yyyy-MM-dd HH:mm:ss";
 DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
 String format = formatter.format(now);
 System.out.println(format);
}

Output results:

2019-05-06 22:33:03

5. Local DateTime timestamp

@Test
public void testDateToTimeMillis() {
 LocalDateTime dateTime = LocalDateTime.now();
 long epochMilli = dateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
 System.out.println(epochMilli);
}

Output results:

1557153504304

summary

Because DateTime Formatter is thread-safe, it can be used in a way that defines DateTime Formatter as a static constant when using Local DateTime in practice. The above list of more commonly used time operations, Local DateTime can also do a lot of things, let the reader dig it. I have encapsulated a LocalDateTime tool class myself, and I have only done a simple self-test. You can refer to it.

package happy.localdatetime;
​
​
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;/**
 * @author Happy
 */
public class DateTimeUtils {private DateTimeUtils() {
 }private final static String COMMON_PATTERN = "yyyy-MM-dd HH:mm:ss";private final static DateTimeFormatter COMMON_FORMATTER = DateTimeFormatter.ofPattern(COMMON_PATTERN);private final static ZoneOffset DEFAULT_ZONE_OFFSET = ZoneOffset.of("+8");/**
 * Default yyyy-MM-dd HH:mm:ss format
 */
 public static String dateToString(LocalDateTime dateTime) {
 assert dateTime != null;
 return COMMON_FORMATTER.format(dateTime);
 }/**
 * Default yyyy-MM-dd HH:mm:ss format
 */
 public static LocalDateTime stringToDate(String dateStr) {
 assert dateStr != null;
 return LocalDateTime.parse(dateStr, COMMON_FORMATTER);
 }public static String dateToString(LocalDateTime dateTime, DateTimeFormatter formatter) {
 assert dateTime != null;
 return formatter.format(dateTime);
 }public static LocalDateTime stringToDate(String dateStr, DateTimeFormatter formatter) {
 assert dateStr != null;
 return LocalDateTime.parse(dateStr, formatter);
 }public static long dateToTimeMillis(LocalDateTime dateTime) {
 assert dateTime != null;
 return dateTime.toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli();
 }public static LocalDateTime timeMillisToDate(long timeMillis) {
 Instant instant = Instant.ofEpochMilli(timeMillis);
 return LocalDateTime.ofInstant(instant, DEFAULT_ZONE_OFFSET);
 }public static void main(String[] args) {
 String s = dateToString(LocalDateTime.now());
 System.out.println(s);
 System.out.println();
 String dateStr = "2019-01-01 12:12:12";
 LocalDateTime localDateTime = stringToDate(dateStr);
 System.out.println(localDateTime);
 System.out.println();
 System.out.println(dateToTimeMillis(localDateTime));
 System.out.println();
 System.out.println(timeMillisToDate(System.currentTimeMillis()));
 }}

Pay attention to public information

Search for public number [Happyjava], reply to [e-book] and [video], you can get a large number of high-quality e-books and large data, kafka, nginx, MySQL and other video materials.

Topics: Java Attribute kafka Nginx