深度思考JDK8中日期类型该如何使用详解

在JDK8之前,处理日期时间,我们主要使用3个类, DateSimpleDateFormatCalendar

这3个类在使用时都或多或少的存在一些问题,比如 SimpleDateFormat 不是线程安全的,

比如 DateCalendar 获取到的月份是0到11,而不是现实生活中的1到12,关于这一点,《阿里巴巴Java开发手册》中也有提及,因为很容易犯错:

不过,JDK8推出了全新的日期时间处理类解决了这些问题,比如 InstantLocalDateLocalTimeLocalDateTimeDateTimeFormatter ,在《阿里巴巴Java开发手册》中也推荐使用 Instant

LocalDateTimeDateTimeFormatter

但我发现好多项目中其实并没有使用这些类,使用的还是之前的 DateSimpleDateFormatCalendar ,所以本篇博客就讲解下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推出了全新的日期时间类,如 InstantLocaleDateLocalTimeLocalDateTimeDateTimeFormatter ,设计比之前更合理,也是线程安全的。

《阿里巴巴Java开发规范》中也推荐使用 Instant 代替 DateLocalDateTime 代替 CalendarDateTimeFormatter 代替 SimpleDateFormat

因此,如果条件允许,建议在项目中使用,没有使用的,可以考虑升级下。

到此这篇关于JDK8中日期类型该如何使用详解的文章就介绍到这了,更多相关JDK8 日期类型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java将日期类型Date时间戳转换为MongoDB的时间类型数据

    存了一个时间类型(Date)的数据到mongo数据库中,但是前台显示的是一串数字.继而引发了如下问题: Java里面如何把 时间戳 1477387464495 转换为 2016-10-25 17:24:24 期望格式的日期字符串. 因为业务需要,在model里面有个Date类型的字段,然后需要按这个时间类型排序.但是在后台处理完之后,返回到前台,发现时间变成了13位数字,学名叫时间戳.不是我想要的具体时间,不适合展示啊.具体有如下 mongo数据库中存储时间类型的数据具体如下: 然后debug的

  • java字符串与日期类型转换的工具类

    常用的字符串转date,和日期转字符串的方法,具体内容如下 package com.cq2022.zago.base.util; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import javax.xml.datatype.Dat

  • java实现字符串和日期类型相互转换的方法

    本文实例讲述了java实现字符串和日期类型相互转换的方法.分享给大家供大家参考,具体如下: Date inDate = new Date(); //获取当前日期 //建立一个一定格式的 SimpleDateFormat SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String date = f.format(inDate); //将Date转化为字符串 System.out.println(date

  • 深度思考JDK8中日期类型该如何使用详解

    在JDK8之前,处理日期时间,我们主要使用3个类, Date . SimpleDateFormat 和 Calendar . 这3个类在使用时都或多或少的存在一些问题,比如 SimpleDateFormat 不是线程安全的, 比如 Date 和 Calendar 获取到的月份是0到11,而不是现实生活中的1到12,关于这一点,<阿里巴巴Java开发手册>中也有提及,因为很容易犯错: 不过,JDK8推出了全新的日期时间处理类解决了这些问题,比如 Instant . LocalDate . Loc

  • c#中String类型的存储原理详解

    在我们正式了解c#中的String类型前,先来判断一下下面代码的结果吧~ String str1 = "123"; String str2 = str1; str2 = "321"; Console.WriteLine(str1); 上面代码的最终输出结果是123,如果有浅学过引用类型的同学一定会问:str2不是在存储的是str1的引用么?那么str2不是和str1指向堆中同一块内存空间么?为什么在引用了str2使其改变数据后再打印出str1最终还是打印出来123?

  • MySQL中日期型单行函数代码详解

    MySQL中日期型单行函数: CURDATE()或CURRENT_DATE() 返回当前日期(精确到日) 参考代码如下: SELECT CURDATE() FROM DUAL; SELECT CURRENT_DATE() FROM DUAL; -----------------------------------(分割线)------------------------------------ CURTIME() 或CURRENT_TIME() 返回当前时间(精确到秒) 参考代码如下: SELE

  • SQL Server中日期时间函数的用法详解

    1.getdate():获取当前日期 返回当前SQLServer服务器所在计算机的日期和时间.返回值舍入到最近的秒小数部分,精度为.333秒数据库十七偏移量不包含在内. select getdate() --输出 2013-03-09 15:16:00.570 2.getutcdate():获取UTC时间值 select GETUTCDATE() -- 2013-06-18 08:02:53.253 3.year():获取年度信息 year函数以int数据类型的格式返回特定日期的年度信息.其中的

  • Java 中DateUtils日期工具类的实例详解

    Java 中DateUtils日期工具类的实例详解 介绍 在java中队日期类型的处理并不方便,通常都需要借助java.text.SimpleDateFormat类来实现日期类型 和字符串类型之间的转换,但是在jdk1.8之后有所改善,jdk1.7以及之前的版本处理日期类型并不方便, 可以借助Joda Time组件来处理,尤其是日期类型的一些数学操作就更是不方便. java代码 /** * * 日期工具类 java对日期的操作一直都很不理想,直到jdk1.8之后才有了本质的改变. * 如果使用的

  • Java日期时间类及计算详解

    目录 1. Java中与日期相关的类 1.1 java.util包 ① Date类 ② Calendar 日历类 roll 设置Calendar的容错性 set 1.2 java.time包 ① LocalDate 本地日期类 ② LocalTime 本地时间类 ③ LocalDateTime 本地日期时间类 ④ Instant 类 ⑤ Period 类 ⑥ Duration 类 2. 时间间隔计算 2.1 Period与Duration类 2.1.1 Duration 2.1.2 Period

  • Struts中使用validate()输入校验方法详解

    1.在ActionSupport中有一个validate()方法,这个方法是验证方法,它会在execute()方法执行之前执行,所以能够起到很好的验证的作用. @Override //重写Action中的validate()方法 public void validate() { if(null==this.username||this.username.length()<4||this.username.length()>6){ this.addActionError("userna

  • java时间日期使用与查询代码详解

    只要格式正确,直接比较字符串就可以了呀,精确到秒的也一样 String s1 = "2003-12-12 11:30:24"; String s2 = "2004-04-01 13:31:40"; int res = s1.compareTo(s2); 求日期差 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date begin=df.parse("

  • Java的静态类型检查示例代码详解

    关于静态类型检查和动态类型检查的解释: 静态类型检查:基于程序的源代码来验证类型安全的过程: 动态类型检查:在程序运行期间验证类型安全的过程: Java使用静态类型检查在编译期间分析程序,确保没有类型错误.基本的思想是不要让类型错误在运行期间发生. 在各色各样的编程语言中,总共存在着两个类型检查机制:静态类型检查和动态类型检查. 静态类型检查是指通过对应用程序的源码进行分析,在编译期间就保证程序的类型安全. 动态类型检查是在程序的运行过程中,验证程序的类型安全.在Java中,编译期间使用静态类型

  • 对python xlrd读取datetime类型数据的方法详解

    使用xlrd读取出来的时间字段是类似41410.5083333的浮点数,在使用时需要转换成对应的datetime类型,下面代码是转换的方法: 首先需要引入xldate_as_tuple函数 from xlrd import xldate_as_tuple 使用方法如下: #d是从excel中读取出来的浮点数 xldate_as_tuple(d,0) xldate_as_tuple第二个参数有两种取值,0或者1,0是以1900-01-01为基准的日期,而1是1904-01-01为基准的日期.该函数

随机推荐