【深度思考】JDK8中日期类型该如何使用?
在JDK8之前,处理日期时间,我们主要使用3个类,Date
、SimpleDateFormat
和Calendar
。
这3个类在使用时都或多或少的存在一些问题,比如SimpleDateFormat
不是线程安全的,
比如Date
和Calendar
获取到的月份是0到11,而不是现实生活中的1到12,关于这一点,《阿里巴巴Java开发手册》中也有提及,因为很容易犯错:
不过,JDK8推出了全新的日期时间处理类解决了这些问题,比如Instant
、LocalDate
、LocalTime
、LocalDateTime
、DateTimeFormatter
,在《阿里巴巴Java开发手册》中也推荐使用Instant
、
LocalDateTime
、DateTimeFormatter
:
但我发现好多项目中其实并没有使用这些类,使用的还是之前的Date
、SimpleDateFormat
和Calendar
,所以本篇博客就讲解下JDK8新推出的日期时间类,主要是下面几个:
- Instant
- LocalDate
- LocalTime
- LocalDateTime
- DateTimeFormatter
1. Instant
1.1 获取当前时间
既然Instant
可以代替Date
类,那它肯定可以获取当前时间:
Instant instant = Instant.now();
System.out.println(instant);
输出结果:
2020-06-10T08:22:13.759Z
细心的你会发现,这个时间比北京时间少了8个小时,如果要输出北京时间,可以加上默认时区:
System.out.println(instant.atZone(ZoneId.systemDefault()));
输出结果:
2020-06-10T16:22:13.759+08:00[Asia/Shanghai]
1.2 获取时间戳
Instant instant = Instant.now();
// 当前时间戳:单位为秒
System.out.println(instant.getEpochSecond());
// 当前时间戳:单位为毫秒
System.out.println(instant.toEpochMilli());
输出结果:
1591777752
1591777752613
当然,也可以通过System.currentTimeMillis()
获取当前毫秒数。
1.3 将long转换为Instant
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
1.4 将String转换为Instant
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
异常,如下图所示:
2. LocalDate
2.1 获取当前日期
使用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年了,当时好几个博主写过文章解析原因,我这里就不做过多解释了。
划重点:都说到这了,给大家安利下我新注册的公众号「申城异乡人」,欢迎大家关注,更多原创文章等着你哦,哈哈。
2.2 获取年月日
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。
2.3 指定日期
LocalDate specifiedDate = LocalDate.of(2020, 6, 1);
System.out.println("specifiedDate: " + specifiedDate);
输出结果:
specifiedDate: 2020-06-01
如果确定月份,推荐使用另一个重载方法,使用枚举指定月份:
LocalDate specifiedDate = LocalDate.of(2020, Month.JUNE, 1);
2.4 比较日期是否相等
LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2020, 6, 10);
if (localDate1.equals(localDate2)) {
System.out.println("localDate1 equals localDate2");
}
输出结果:
localDate1 equals localDate2
2.5 获取日期是本周/本月/本年的第几天
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天
2.6 判断是否为闰年
LocalDate today = LocalDate.now();
System.out.println(today.getYear() + " is leap year:" + today.isLeapYear());
输出结果:
2020 is leap year:true
3. LocalTime
3.1 获取时分秒
如果使用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只有时间没有日期。
4. LocalDateTime
4.1 获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDateTime:" + localDateTime);
输出结果:
localDateTime: 2020-06-11T11:03:21.376
4.2 获取年月日时分秒
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());
输出结果:
4.3 增加天数/小时
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
还提供了添加年、周、分钟、秒这些方法,这里就不一一列举了:
4.4 减少天数/小时
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
还提供了减少年、周、分钟、秒这些方法,这里就不一一列举了:
4.5 获取时间是本周/本年的第几天
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
5. DateTimeFormatter
JDK8中推出了java.time.format.DateTimeFormatter
来处理日期格式化问题,《阿里巴巴Java开发手册》中也是建议使用DateTimeFormatter
代替SimpleDateFormat
。
5.1 格式化LocalDate
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
5.2 格式化LocalTime
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
5.3 格式化LocalDateTime
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
6. 类型相互转换
6.1 Instant转Date
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
6.2 Date转Instant
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
6.3 Date转LocalDateTime
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
6.4 Date转LocalDate
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
。
6.5 Date转LocalTime
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
。
6.6 LocalDateTime转Date
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
6.7 LocalDate转Date
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
6.8 LocalTime转Date
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
7. 总结
JDK8推出了全新的日期时间类,如Instant
、LocaleDate
、LocalTime
、LocalDateTime
、DateTimeFormatter
,设计比之前更合理,也是线程安全的。
《阿里巴巴Java开发规范》中也推荐使用Instant
代替Date
,LocalDateTime
代替 Calendar
,DateTimeFormatter
代替 SimpleDateFormat
。
因此,如果条件允许,建议在项目中使用,没有使用的,可以考虑升级下。
【深度思考】JDK8中日期类型该如何使用?的更多相关文章
- java和数据库中日期类型的常见用法
(1)java中日期类型:Date.Timestamp(2)数据库中:Date.Timestamp(3)字符串和Date之间的格式化转换: SimpleDateFormat类方法: format ...
- 【转载】 C#中日期类型DateTime的日期加减操作
在C#开发过程中,DateTime数据类型用于表示日期类型,可以通过DateTime.Now获取当前服务器时间,同时日期也可以像数字一样进行加减操作,如AddDay方法可以对日期进行加减几天的操作,A ...
- oracle中日期类型 to_date 和to_timestamp什么区别啊?
1.to_date() 和to_timestamp()区别 由于oracle中date类型只支持到秒,不支持到毫秒,所以to_date()不能取到毫秒.如果要取到毫秒,oracle 9i以上版本,可以 ...
- Java中日期类型和mysql中日期类型进行整合
1. java与mysql中日期.时间类型总结: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 mysql(版本:5.1.50)的时间日期类型如下: da ...
- 解决ASP.NET MVC返回的JsonResult 中 日期类型数据格式问题,和返回的属性名称转为“驼峰命名法”和循环引用问题
DateTime类型数据格式问题 问题 在使用ASP.NET MVC 在写项目的时候发现,返回给前端的JSON数据,日期类型是 Date(121454578784541) 的格式,需要前端来转换一下才 ...
- Mysql 中日期类型bigint和datetime互转
MySql数据库中字段类型bigint 长度是10位的 mysql> select (from_unixtime(1554047999))as datatime;+--------------- ...
- 解决mysql 数据库中日期类型00:00:00 的问题 设置xml数据类型:java.util.Date
解决方法是 设置xml里面字段的类型为:java.util.Date.加红部分. 1. beanl里面private Date ulLoginDate; 2.hibernate的xml里面是 < ...
- Node.js怎么处理数据库中日期类型
问题描述:在数据库里存储时间的时候明明显示的是类如2016-12-22的形式,读取出来后却变成了大概是这样的:Fri May 17 2016 14:12:33 GMT+0800 (中国标准时间) 处理 ...
- Java 基础【09】 日期类型
java api中日期类型的继承关系 java.lang.Object --java.util.Date --java.sql.Date --java.sql.Time --java.sql.Time ...
随机推荐
- 输入一个整数n,输出契波那契数列的第n项
package bianchengti; /* * 输入一个整数n,输出契波那契数列的第n项 * 斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89... */ p ...
- DRF版本组件
1.DRF版本组件配置类局部使用 局部配置: 方式一:直接配置versioning_class=QueryParameterVersioning 方式二:直接配置versioning_class=UR ...
- 《机器学习_07_02_svm_软间隔支持向量机》
一.简介 上一节介绍了硬间隔支持向量机,它可以在严格线性可分的数据集上工作的很好,但对于非严格线性可分的情况往往就表现很差了,比如: import numpy as np import matplot ...
- 苏浪浪 201771010120 第三周 Java基本程序设计总结
理论知识: Java有五种语句: (1)方法调用语句(2)表达式语句(3)复合语句(4)控制语句(5)package.import语句 3.8控制流程 3.9大数值 *如果基本的整型和浮点型数据无法达 ...
- charles 抓包iOS模拟器 HTTPS请求
参考: https://www.jianshu.com/p/3bfae9ede35e https://www.jianshu.com/p/171046d9f4f9 https://www.jiansh ...
- 贪心 BZOJ1034
1034: [ZJOI2008]泡泡堂BNB Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3164 Solved: 1623[Submit][St ...
- 【Java】Scanner类nextInt后使用nextLine无法读取输入
首先,我们先介绍一下,在学习Java语言,对于字符串的输入,由于Scanner.next()函数无法输入空格及回车,此时,我们就必须要用Scanner.nextLine()解决这类问题, 在使用过程中 ...
- centos的安装
直接给大家截图说明吧,简洁明了. 休闲吃瓜时光 选择语言 这边看个人 当然推荐英语 设置root密码 将自己要设置的信息填写进去即可 然后又是休闲吃瓜时光..... 下来登录即可 然后可以看到 这 ...
- Rocket - diplomacy - wirePrefix
https://mp.weixin.qq.com/s/DVcA2UixnB_6vgI3SjZGyQ 调试wirePrefix方法. 1. 实现 wirePrefix用于调整名称格式,其实现 ...
- 数组API汇总
数组API汇总 Javascript数组API: 1.将数组转化为字符串:2种: 1.var str=String(str); 将数组转化为字符串并分隔每个元素; var arr=[1,2,3]; ...