java 8发布时间_还在用SimpleDateFormat?Java8都发布N年了,转LocalDateTime吧

前言

Java8发布,已有数年之久,但是发现很多人都还是坚持着用SimpleDateFormat和Date进行时间操作。SimpleDateFormat这个类不是线程安全的,在使用的时候稍不注意,就会产生致命的问题。Date这个类,是可以重新设置时间的,这对于一些类内部的属性来说,是非常不安全的。

SimpleDateFormat是线程不安全的类

在阿里巴巴规约手册里,强制规定SimpleDateFormat是线程不安全的类,当定义为静态变量时,必须加锁处理。忽略线程安全问题,正是大多数Java初学者在进行时间转化时容易踩坑的点。

3fbee4827caf07e534ef74ea86ec3e2e.png

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;

}

}

我们实例化该User

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

}

输出结果如下:

6bbc0ee59fb0ce9f1281aa8cd60dbf79.png

这里可以看到,user对象的birthday属性被修改掉了。这也是Date对象的弊端所在,我们可以通过改写getter方法,使它返回一个新的Date对象即可解决,如下:

public Date getBirthday() {

// return birthday;

return new Date(birthday.getTime());

}

切记这里是不可以用clone方法来生成返回一个新的Date对象的,因为Date类可以被继承,你不能确定调用者是否给birthday设置了一个Date的子类。

Java8提供的新的时间类库LocalDateTime

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方法对字符串进行转化成时间,如果不传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()));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值