在JDK8以前,处理日期时间,咱们主要使用3个类,Date
、SimpleDateFormat
和Calendar
。java
这3个类在使用时都或多或少的存在一些问题,好比SimpleDateFormat
不是线程安全的,web
好比Date
和Calendar
获取到的月份是0到11,而不是现实生活中的1到12,关于这一点,《阿里巴巴Java开发手册》中也有说起,由于很容易犯错:安全
不过,JDK8推出了全新的日期时间处理类解决了这些问题,好比Instant
、LocalDate
、LocalTime
、LocalDateTime
、DateTimeFormatter
,在《阿里巴巴Java开发手册》中也推荐使用Instant
、微信
LocalDateTime
、DateTimeFormatter
:svg
但我发现好多项目中其实并无使用这些类,使用的仍是以前的Date
、SimpleDateFormat
和Calendar
,因此本篇博客就讲解下JDK8新推出的日期时间类,主要是下面几个:spa
既然Instant
能够代替Date
类,那它确定能够获取当前时间:线程
Instant instant = Instant.now(); System.out.println(instant);
输出结果:设计
2020-06-10T08:22:13.759Z3d
细心的你会发现,这个时间比北京时间少了8个小时,若是要输出北京时间,能够加上默认时区:code
System.out.println(instant.atZone(ZoneId.systemDefault()));
输出结果:
2020-06-10T16:22:13.759+08:00[Asia/Shanghai]
Instant instant = Instant.now(); // 当前时间戳:单位为秒 System.out.println(instant.getEpochSecond()); // 当前时间戳:单位为毫秒 System.out.println(instant.toEpochMilli());
输出结果:
1591777752
1591777752613
固然,也能够经过System.currentTimeMillis()
获取当前毫秒数。
1)根据秒数时间戳转换:
Instant instant = Instant.now(); System.out.println(instant); long epochSecond = instant.getEpochSecond(); System.out.println(Instant.ofEpochSecond(epochSecond)); System.out.println(Instant.ofEpochSecond(epochSecond, instant.getNano()));
输出结果:
2020-06-10T08:40:54.046Z
2020-06-10T08:40:54Z
2020-06-10T08:40:54.046Z
2)根据毫秒数时间戳转换:
Instant instant = Instant.now(); System.out.println(instant); long epochMilli = instant.toEpochMilli(); System.out.println(Instant.ofEpochMilli(epochMilli));
输出结果:
2020-06-10T08:43:25.607Z
2020-06-10T08:43:25.607Z
String text = "2020-06-10T08:46:55.967Z"; Instant parseInstant = Instant.parse(text); System.out.println("秒时间戳:" + parseInstant.getEpochSecond()); System.out.println("豪秒时间戳:" + parseInstant.toEpochMilli()); System.out.println("纳秒:" + parseInstant.getNano());
输出结果:
秒时间戳:1591778815
豪秒时间戳:1591778815967
纳秒:967000000
若是字符串格式不对,好比修改为2020-06-10T08:46:55.967
,就会抛出java.time.format.DateTimeParseException
异常,以下图所示:
使用LocalDate
获取当前日期很是简单,以下所示:
LocalDate today = LocalDate.now(); System.out.println("today: " + today);
输出结果:
today: 2020-06-10
不用任何格式化,输出结果就很是友好,若是使用Date
,输出这样的格式,还得配合SimpleDateFormat
指定yyyy-MM-dd
进行格式化,一不当心还会出个bug,好比去年年末很火的1个bug,我当时仍是截了图的:
这2个好友是2019/12/31关注个人,但我2020年1月2号查看时,却显示成了2020/12/31,为啥呢?格式化日期时格式写错了,应该是yyyy/MM/dd
,却写成了YYYY/MM/dd
,恰好那周跨年,就显示成下一年,也就是2020年了,当时好几个博主写过文章解析缘由,我这里就不作过多解释了。
划重点:都说到这了,给你们安利下我新注册的公众号「申城异乡人」,欢迎你们关注,更多原创文章等着你哦,哈哈。
LocalDate today = LocalDate.now(); int year = today.getYear(); int month = today.getMonthValue(); int day = today.getDayOfMonth(); System.out.println("year: " + year); System.out.println("month: " + month); System.out.println("day: " + day);
输出结果:
year: 2020
month: 6
day: 10
获取月份终于返回1到12了,不像java.util.Calendar
获取月份返回的是0到11,获取完还得加1。
LocalDate specifiedDate = LocalDate.of(2020, 6, 1); System.out.println("specifiedDate: " + specifiedDate);
输出结果:
specifiedDate: 2020-06-01
若是肯定月份,推荐使用另外一个重载方法,使用枚举指定月份:
LocalDate specifiedDate = LocalDate.of(2020, Month.JUNE, 1);
LocalDate localDate1 = LocalDate.now(); LocalDate localDate2 = LocalDate.of(2020, 6, 10); if (localDate1.equals(localDate2)) { System.out.println("localDate1 equals localDate2"); }
输出结果:
localDate1 equals localDate2
LocalDate today = LocalDate.now(); System.out.println("Today:" + today); System.out.println("Today is:" + today.getDayOfWeek()); System.out.println("今天是本周的第" + today.getDayOfWeek().getValue() + "天"); System.out.println("今天是本月的第" + today.getDayOfMonth() + "天"); System.out.println("今天是本年的第" + today.getDayOfYear() + "天");
输出结果:
Today:2020-06-11
Today is:THURSDAY
今天是本周的第4天
今天是本月的第11天
今天是本年的第163天
LocalDate today = LocalDate.now(); System.out.println(today.getYear() + " is leap year:" + today.isLeapYear());
输出结果:
2020 is leap year:true
若是使用java.util.Date
,那代码是下面这样的:
Date date = new Date(); int hour = date.getHours(); int minute = date.getMinutes(); int second = date.getSeconds(); System.out.println("hour: " + hour); System.out.println("minute: " + minute); System.out.println("second: " + second);
输出结果:
注意事项:这几个方法已通过期了,所以强烈不建议在项目中使用:
若是使用java.util.Calendar
,那代码是下面这样的:
Calendar calendar = Calendar.getInstance(); // 12小时制 int hourOf12 = calendar.get(Calendar.HOUR); // 24小时制 int hourOf24 = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); int milliSecond = calendar.get(Calendar.MILLISECOND); System.out.println("hourOf12: " + hourOf12); System.out.println("hourOf24: " + hourOf24); System.out.println("minute: " + minute); System.out.println("second: " + second); System.out.println("milliSecond: " + milliSecond);
输出结果:
**注意事项:**获取小时时,有2个选项,1个返回12小时制的小时数,1个返回24小时制的小时数,由于如今是晚上8点,因此calendar.get(Calendar.HOUR)
返回8,而calendar.get(Calendar.HOUR_OF_DAY)
返回20。
若是使用java.time.LocalTime
,那代码是下面这样的:
LocalTime localTime = LocalTime.now(); System.out.println("localTime:" + localTime); int hour = localTime.getHour(); int minute = localTime.getMinute(); int second = localTime.getSecond(); System.out.println("hour: " + hour); System.out.println("minute: " + minute); System.out.println("second: " + second);
输出结果:
能够看出,LocalTime只有时间没有日期。
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime:" + localDateTime);
输出结果:
localDateTime: 2020-06-11T11:03:21.376
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); System.out.println("year: " + localDateTime.getYear()); System.out.println("month: " + localDateTime.getMonthValue()); System.out.println("day: " + localDateTime.getDayOfMonth()); System.out.println("hour: " + localDateTime.getHour()); System.out.println("minute: " + localDateTime.getMinute()); System.out.println("second: " + localDateTime.getSecond());
输出结果:
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); LocalDateTime tomorrow = localDateTime.plusDays(1); System.out.println("tomorrow: " + tomorrow); LocalDateTime nextHour = localDateTime.plusHours(1); System.out.println("nextHour: " + nextHour);
输出结果:
localDateTime: 2020-06-11T11:13:44.979
tomorrow: 2020-06-12T11:13:44.979
nextHour: 2020-06-11T12:13:44.979
LocalDateTime
还提供了添加年、周、分钟、秒这些方法,这里就不一一列举了:
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); LocalDateTime yesterday = localDateTime.minusDays(1); System.out.println("yesterday: " + yesterday); LocalDateTime lastHour = localDateTime.minusHours(1); System.out.println("lastHour: " + lastHour);
输出结果:
localDateTime: 2020-06-11T11:20:38.896
yesterday: 2020-06-10T11:20:38.896
lastHour: 2020-06-11T10:20:38.896
相似的,LocalDateTime
还提供了减小年、周、分钟、秒这些方法,这里就不一一列举了:
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); System.out.println("DayOfWeek: " + localDateTime.getDayOfWeek().getValue()); System.out.println("DayOfYear: " + localDateTime.getDayOfYear());
输出结果:
localDateTime: 2020-06-11T11:32:31.731
DayOfWeek: 4
DayOfYear: 163
JDK8中推出了java.time.format.DateTimeFormatter
来处理日期格式化问题,《阿里巴巴Java开发手册》中也是建议使用DateTimeFormatter
代替SimpleDateFormat
。
LocalDate localDate = LocalDate.now(); System.out.println("ISO_DATE: " + localDate.format(DateTimeFormatter.ISO_DATE)); System.out.println("BASIC_ISO_DATE: " + localDate.format(DateTimeFormatter.BASIC_ISO_DATE)); System.out.println("ISO_WEEK_DATE: " + localDate.format(DateTimeFormatter.ISO_WEEK_DATE)); System.out.println("ISO_ORDINAL_DATE: " + localDate.format(DateTimeFormatter.ISO_ORDINAL_DATE));
输出结果:
若是提供的格式没法知足你的需求,你还能够像之前同样自定义格式:
LocalDate localDate = LocalDate.now(); System.out.println("yyyy/MM/dd: " + localDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));
输出结果:
yyyy/MM/dd: 2020/06/11
LocalTime localTime = LocalTime.now(); System.out.println(localTime); System.out.println("ISO_TIME: " + localTime.format(DateTimeFormatter.ISO_TIME)); System.out.println("HH:mm:ss: " + localTime.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
输出结果:
14:28:35.230
ISO_TIME: 14:28:35.23
HH:mm:ss: 14:28:35
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDateTime); System.out.println("ISO_DATE_TIME: " + localDateTime.format(DateTimeFormatter.ISO_DATE_TIME)); System.out.println("ISO_DATE: " + localDateTime.format(DateTimeFormatter.ISO_DATE));
输出结果:
2020-06-11T14:33:18.303
ISO_DATE_TIME: 2020-06-11T14:33:18.303
ISO_DATE: 2020-06-11
JDK8中,Date
新增了from()
方法,将Instant
转换为Date
,代码以下所示:
Instant instant = Instant.now(); System.out.println(instant); Date dateFromInstant = Date.from(instant); System.out.println(dateFromInstant);
输出结果:
2020-06-11T06:39:34.979Z
Thu Jun 11 14:39:34 CST 2020
JDK8中,Date
新增了toInstant
方法,将Date
转换为Instant
,代码以下所示:
Date date = new Date(); Instant dateToInstant = date.toInstant(); System.out.println(date); System.out.println(dateToInstant);
输出结果:
Thu Jun 11 14:46:12 CST 2020
2020-06-11T06:46:12.112Z
Date date = new Date(); Instant instant = date.toInstant(); LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); System.out.println(date); System.out.println(localDateTimeOfInstant);
输出结果:
Thu Jun 11 14:51:07 CST 2020
2020-06-11T14:51:07.904
Date date = new Date(); Instant instant = date.toInstant(); LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); LocalDate localDate = localDateTimeOfInstant.toLocalDate(); System.out.println(date); System.out.println(localDate);
输出结果:
Thu Jun 11 14:59:38 CST 2020
2020-06-11
能够看出,Date
是先转换为Instant
,再转换为LocalDateTime
,而后经过LocalDateTime
获取LocalDate
。
Date date = new Date(); Instant instant = date.toInstant(); LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); LocalTime toLocalTime = localDateTimeOfInstant.toLocalTime(); System.out.println(date); System.out.println(toLocalTime);
输出结果:
Thu Jun 11 15:06:14 CST 2020
15:06:14.531
能够看出,Date
是先转换为Instant
,再转换为LocalDateTime
,而后经过LocalDateTime
获取LocalTime
。
LocalDateTime localDateTime = LocalDateTime.now(); Instant toInstant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date dateFromInstant = Date.from(toInstant); System.out.println(localDateTime); System.out.println(dateFromInstant);
输出结果:
2020-06-11T15:12:11.600
Thu Jun 11 15:12:11 CST 2020
LocalDate today = LocalDate.now(); LocalDateTime localDateTime = localDate.atStartOfDay(); Instant toInstant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date dateFromLocalDate = Date.from(toInstant); System.out.println(dateFromLocalDate);
输出结果:
Thu Jun 11 00:00:00 CST 2020
LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime); Instant instantFromLocalTime = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date dateFromLocalTime = Date.from(instantFromLocalTime); System.out.println(dateFromLocalTime);
输出结果:
Thu Jun 11 15:24:18 CST 2020
JDK8推出了全新的日期时间类,如Instant
、LocaleDate
、LocalTime
、LocalDateTime
、DateTimeFormatter
,设计比以前更合理,也是线程安全的。
《阿里巴巴Java开发规范》中也推荐使用Instant
代替Date
,LocalDateTime
代替 Calendar
,DateTimeFormatter
代替 SimpleDateFormat
。
所以,若是条件容许,建议在项目中使用,没有使用的,能够考虑升级下。
注:若是以为本篇博客有任何错误或者更好的建议,欢迎留言,我会及时跟进并更正博客内容!
文章持续更新,欢迎关注微信公众号「申城异乡人」第一时间阅读!