Java8发布,已有数年之久,可是发现不少人都仍是坚持着用SimpleDateFormat和Date进行时间操做。SimpleDateFormat这个类不是线程安全的,在使用的时候稍不注意,就会产生致命的问题。Date这个类,是能够从新设置时间的,这对于一些类内部的属性来讲,是很是不安全的。java
在阿里巴巴规约手册里,强制规定SimpleDateFormat是线程不安全的类,当定义为静态变量时,必须加锁处理。忽略线程安全问题,正是大多数Java初学者在进行时间转化时容易踩坑的点。安全
好比有User.java以下:bash
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;
}
}
复制代码
咱们实例化该Userapp
public class Main {
public static void main(String[] args) {
User user = new User("happyjava", new Date());
}
}
复制代码
这固然没什么问题,可是我能够经过user.getBirthday()方法获取到birthday的引用,从而修改直接修改birthday的值。以下:工具
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());
}
复制代码
输出结果以下:测试
这里能够看到,user对象的birthday属性被修改掉了。这也是Date对象的弊端所在,咱们能够经过改写getter方法,使它返回一个新的Date对象便可解决,以下:ui
public Date getBirthday() {
// return birthday;
return new Date(birthday.getTime());
}
复制代码
切记这里是不能够用clone方法来生成返回一个新的Date对象的,由于Date类能够被继承,你不能肯定调用者是否给birthday设置了一个Date的子类。this
Java8提供了LocalDateTime来替代传统的Date来处理时间,下面,咱们就来探讨下这个类库的使用方法吧。spa
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方法对字符串进行转化成时间,若是不传pattern,默认是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.时间转化成字符串
能够经过DateTimeFormatter的format方法,将LocalDateTime转化成字符串。
@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还能够作不少事情,这个就让读者自行去挖掘吧。我本身封装了个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()));
}
}
复制代码