Все еще используете SimpleDateFormat? Java8 выпущен N лет, переключитесь на LocalDateTime

Java

предисловие

Java8 выпущен уже несколько лет, но многие люди по-прежнему настаивают на использовании SimpleDateFormat и Date для операций со временем. Класс SimpleDateFormat не является потокобезопасным, и если вы не будете осторожны при его использовании, это вызовет фатальные проблемы. Класс Date может сбрасывать время, что очень небезопасно для некоторых свойств внутри класса.

SimpleDateFormat не является потокобезопасным классом

Руководство по уставу Alibaba, обязательное. SimpleDateFormat не является потокобезопасным классом, когда он определен как статическая переменная, он должен блокировать обработку. Не обращайте внимания на проблемы безопасности потоков, новичкам легко наступить на большую часть времени преобразования Java-точки во время ямы.

还在用SimpleDateFormat?Java8都发布N年了,转LocalDateTime吧

Свойство Date может сбросить время

Например, есть User.java следующим образом:

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;
 }
}

Мы создаем экземпляр пользователя

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

Это, конечно, не проблема, но я могу получить ссылку на день рождения с помощью метода user.getBirthday(), чтобы напрямую изменить значение дня рождения. следующее:

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());
}

Результат выглядит следующим образом:

还在用SimpleDateFormat?Java8都发布N年了,转LocalDateTime吧

Здесь вы можете увидеть, что свойство дня рождения пользовательского объекта изменяется. Это также недостаток объекта даты, мы можем разрешить новый объект даты, переопределив метод Getter, следующим образом:

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

Помните, что вы не можете использовать метод clone для создания и возврата нового объекта Date, потому что класс Date может быть унаследован, и вы не можете быть уверены, что вызывающий объект установил подкласс Date для дня рождения.

Новая библиотека времени LocalDateTime, предоставляемая Java 8

Java8 предоставляет LocalDateTime вместо традиционного Date для обработки времени Давайте обсудим использование этой библиотеки классов ниже.

1. Получить текущее время

Текущее время можно получить с помощью метода LocalDateTime localDateTime = LocalDateTime.now();. Тест выглядит следующим образом:

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

выходной результат

2019-05-06T22:25:07.309

2. Инициализируйте время в соответствии с отметкой времени

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

+8 здесь означает район Дунба, то же самое ниже.

Выходной результат:

2019-05-06T22:27:34.567

3. Получить время по строке

Вы можете использовать метод LocalDateTime.parse для преобразования строки во время.Если шаблон не передается, по умолчанию используется формат 2019-05-06T11:16:12.361.

@Test
public void testNewFromString() {
 // 1.默认格式 2019-05-06T11:16:12.361
 String dateStr = "2019-05-06T11:16:12.361";
 LocalDateTime localDateTime = LocalDateTime.parse(dateStr);
 System.out.println(localDateTime);
 // 2. 自定义格式
 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);
}

Выходной результат:

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

4. Преобразование времени в строку

Метод формата Can DateTimeFormatterter будет преобразован в строку.

@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);
}

Выходной результат:

2019-05-06 22:33:03

5. LocalDateTime для отметки времени

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

Выходной результат:

1557153504304

Суммировать

Поскольку DateTimeFormatter является потокобезопасным, при фактическом использовании LocalDateTime DateTimeFormatter можно определить как статическую константу для использования. Выше перечислены наиболее часто используемые операции со временем. Я сам инкапсулировал класс инструментов LocalDateTime и провел только простую самопроверку.

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");
​
 /**
 * 默认 yyyy-MM-dd HH:mm:ss 格式
 */
 public static String dateToString(LocalDateTime dateTime) {
 assert dateTime != null;
 return COMMON_FORMATTER.format(dateTime);
 }
​
 /**
 * 默认 yyyy-MM-dd HH:mm:ss 格式
 */
 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()));
 }
​
}