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

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

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

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

LocalDateTimeDateTimeFormatter

但我发现好多项目中其实并没有使用这些类,使用的还是之前的DateSimpleDateFormatCalendar,所以本篇博客就讲解下JDK8新推出的日期时间类,主要是下面几个:

  1. Instant
  2. LocalDate
  3. LocalTime
  4. LocalDateTime
  5. DateTimeFormatter

1. Instant

1.1 获取当前时间

既然Instant可以代替Date类,那它肯定可以获取当前时间:

  1. Instant instant = Instant.now();
  2. System.out.println(instant);

输出结果:

2020-06-10T08:22:13.759Z

细心的你会发现,这个时间比北京时间少了8个小时,如果要输出北京时间,可以加上默认时区:

  1. System.out.println(instant.atZone(ZoneId.systemDefault()));

输出结果:

2020-06-10T16:22:13.759+08:00[Asia/Shanghai]

1.2 获取时间戳

  1. Instant instant = Instant.now();
  2. // 当前时间戳:单位为秒
  3. System.out.println(instant.getEpochSecond());
  4. // 当前时间戳:单位为毫秒
  5. System.out.println(instant.toEpochMilli());

输出结果:

1591777752

1591777752613

当然,也可以通过System.currentTimeMillis()获取当前毫秒数。

1.3 将long转换为Instant

1)根据秒数时间戳转换:

  1. Instant instant = Instant.now();
  2. System.out.println(instant);
  3. long epochSecond = instant.getEpochSecond();
  4. System.out.println(Instant.ofEpochSecond(epochSecond));
  5. 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)根据毫秒数时间戳转换:

  1. Instant instant = Instant.now();
  2. System.out.println(instant);
  3. long epochMilli = instant.toEpochMilli();
  4. System.out.println(Instant.ofEpochMilli(epochMilli));

输出结果:

2020-06-10T08:43:25.607Z

2020-06-10T08:43:25.607Z

1.4 将String转换为Instant

  1. String text = "2020-06-10T08:46:55.967Z";
  2. Instant parseInstant = Instant.parse(text);
  3. System.out.println("秒时间戳:" + parseInstant.getEpochSecond());
  4. System.out.println("豪秒时间戳:" + parseInstant.toEpochMilli());
  5. System.out.println("纳秒:" + parseInstant.getNano());

输出结果:

秒时间戳:1591778815

豪秒时间戳:1591778815967

纳秒:967000000

如果字符串格式不对,比如修改成2020-06-10T08:46:55.967,就会抛出java.time.format.DateTimeParseException异常,如下图所示:

2. LocalDate

2.1 获取当前日期

使用LocalDate获取当前日期非常简单,如下所示:

  1. LocalDate today = LocalDate.now();
  2. 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 获取年月日

  1. LocalDate today = LocalDate.now();
  2. int year = today.getYear();
  3. int month = today.getMonthValue();
  4. int day = today.getDayOfMonth();
  5. System.out.println("year: " + year);
  6. System.out.println("month: " + month);
  7. System.out.println("day: " + day);

输出结果:

year: 2020

month: 6

day: 10

获取月份终于返回1到12了,不像java.util.Calendar获取月份返回的是0到11,获取完还得加1。

2.3 指定日期

  1. LocalDate specifiedDate = LocalDate.of(2020, 6, 1);
  2. System.out.println("specifiedDate: " + specifiedDate);

输出结果:

specifiedDate: 2020-06-01

如果确定月份,推荐使用另一个重载方法,使用枚举指定月份:

  1. LocalDate specifiedDate = LocalDate.of(2020, Month.JUNE, 1);

2.4 比较日期是否相等

  1. LocalDate localDate1 = LocalDate.now();
  2. LocalDate localDate2 = LocalDate.of(2020, 6, 10);
  3. if (localDate1.equals(localDate2)) {
  4. System.out.println("localDate1 equals localDate2");
  5. }

输出结果:

localDate1 equals localDate2

2.5 获取日期是本周/本月/本年的第几天

  1. LocalDate today = LocalDate.now();
  2. System.out.println("Today:" + today);
  3. System.out.println("Today is:" + today.getDayOfWeek());
  4. System.out.println("今天是本周的第" + today.getDayOfWeek().getValue() + "天");
  5. System.out.println("今天是本月的第" + today.getDayOfMonth() + "天");
  6. System.out.println("今天是本年的第" + today.getDayOfYear() + "天");

输出结果:

Today:2020-06-11

Today is:THURSDAY

今天是本周的第4天

今天是本月的第11天

今天是本年的第163天

2.6 判断是否为闰年

  1. LocalDate today = LocalDate.now();
  2. System.out.println(today.getYear() + " is leap year:" + today.isLeapYear());

输出结果:

2020 is leap year:true

3. LocalTime

3.1 获取时分秒

如果使用java.util.Date,那代码是下面这样的:

  1. Date date = new Date();
  2. int hour = date.getHours();
  3. int minute = date.getMinutes();
  4. int second = date.getSeconds();
  5. System.out.println("hour: " + hour);
  6. System.out.println("minute: " + minute);
  7. System.out.println("second: " + second);

输出结果:

注意事项:这几个方法已经过期了,因此强烈不建议在项目中使用:

如果使用java.util.Calendar,那代码是下面这样的:

  1. Calendar calendar = Calendar.getInstance();
  2. // 12小时制
  3. int hourOf12 = calendar.get(Calendar.HOUR);
  4. // 24小时制
  5. int hourOf24 = calendar.get(Calendar.HOUR_OF_DAY);
  6. int minute = calendar.get(Calendar.MINUTE);
  7. int second = calendar.get(Calendar.SECOND);
  8. int milliSecond = calendar.get(Calendar.MILLISECOND);
  9. System.out.println("hourOf12: " + hourOf12);
  10. System.out.println("hourOf24: " + hourOf24);
  11. System.out.println("minute: " + minute);
  12. System.out.println("second: " + second);
  13. 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,那代码是下面这样的:

  1. LocalTime localTime = LocalTime.now();
  2. System.out.println("localTime:" + localTime);
  3. int hour = localTime.getHour();
  4. int minute = localTime.getMinute();
  5. int second = localTime.getSecond();
  6. System.out.println("hour: " + hour);
  7. System.out.println("minute: " + minute);
  8. System.out.println("second: " + second);

输出结果:

可以看出,LocalTime只有时间没有日期。

4. LocalDateTime

4.1 获取当前时间

  1. LocalDateTime localDateTime = LocalDateTime.now();
  2. System.out.println("localDateTime:" + localDateTime);

输出结果:

localDateTime: 2020-06-11T11:03:21.376

4.2 获取年月日时分秒

  1. LocalDateTime localDateTime = LocalDateTime.now();
  2. System.out.println("localDateTime: " + localDateTime);
  3. System.out.println("year: " + localDateTime.getYear());
  4. System.out.println("month: " + localDateTime.getMonthValue());
  5. System.out.println("day: " + localDateTime.getDayOfMonth());
  6. System.out.println("hour: " + localDateTime.getHour());
  7. System.out.println("minute: " + localDateTime.getMinute());
  8. System.out.println("second: " + localDateTime.getSecond());

输出结果:

4.3 增加天数/小时

  1. LocalDateTime localDateTime = LocalDateTime.now();
  2. System.out.println("localDateTime: " + localDateTime);
  3. LocalDateTime tomorrow = localDateTime.plusDays(1);
  4. System.out.println("tomorrow: " + tomorrow);
  5. LocalDateTime nextHour = localDateTime.plusHours(1);
  6. 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 减少天数/小时

  1. LocalDateTime localDateTime = LocalDateTime.now();
  2. System.out.println("localDateTime: " + localDateTime);
  3. LocalDateTime yesterday = localDateTime.minusDays(1);
  4. System.out.println("yesterday: " + yesterday);
  5. LocalDateTime lastHour = localDateTime.minusHours(1);
  6. 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 获取时间是本周/本年的第几天

  1. LocalDateTime localDateTime = LocalDateTime.now();
  2. System.out.println("localDateTime: " + localDateTime);
  3. System.out.println("DayOfWeek: " + localDateTime.getDayOfWeek().getValue());
  4. 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

  1. LocalDate localDate = LocalDate.now();
  2. System.out.println("ISO_DATE: " + localDate.format(DateTimeFormatter.ISO_DATE));
  3. System.out.println("BASIC_ISO_DATE: " + localDate.format(DateTimeFormatter.BASIC_ISO_DATE));
  4. System.out.println("ISO_WEEK_DATE: " + localDate.format(DateTimeFormatter.ISO_WEEK_DATE));
  5. System.out.println("ISO_ORDINAL_DATE: " + localDate.format(DateTimeFormatter.ISO_ORDINAL_DATE));

输出结果:

如果提供的格式无法满足你的需求,你还可以像以前一样自定义格式:

  1. LocalDate localDate = LocalDate.now();
  2. System.out.println("yyyy/MM/dd: " + localDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));

输出结果:

yyyy/MM/dd: 2020/06/11

5.2 格式化LocalTime

  1. LocalTime localTime = LocalTime.now();
  2. System.out.println(localTime);
  3. System.out.println("ISO_TIME: " + localTime.format(DateTimeFormatter.ISO_TIME));
  4. 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

  1. LocalDateTime localDateTime = LocalDateTime.now();
  2. System.out.println(localDateTime);
  3. System.out.println("ISO_DATE_TIME: " + localDateTime.format(DateTimeFormatter.ISO_DATE_TIME));
  4. 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,代码如下所示:

  1. Instant instant = Instant.now();
  2. System.out.println(instant);
  3. Date dateFromInstant = Date.from(instant);
  4. 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,代码如下所示:

  1. Date date = new Date();
  2. Instant dateToInstant = date.toInstant();
  3. System.out.println(date);
  4. System.out.println(dateToInstant);

输出结果:

Thu Jun 11 14:46:12 CST 2020

2020-06-11T06:46:12.112Z

6.3 Date转LocalDateTime

  1. Date date = new Date();
  2. Instant instant = date.toInstant();
  3. LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
  4. System.out.println(date);
  5. System.out.println(localDateTimeOfInstant);

输出结果:

Thu Jun 11 14:51:07 CST 2020

2020-06-11T14:51:07.904

6.4 Date转LocalDate

  1. Date date = new Date();
  2. Instant instant = date.toInstant();
  3. LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
  4. LocalDate localDate = localDateTimeOfInstant.toLocalDate();
  5. System.out.println(date);
  6. System.out.println(localDate);

输出结果:

Thu Jun 11 14:59:38 CST 2020

2020-06-11

可以看出,Date是先转换为Instant,再转换为LocalDateTime,然后通过LocalDateTime获取LocalDate

6.5 Date转LocalTime

  1. Date date = new Date();
  2. Instant instant = date.toInstant();
  3. LocalDateTime localDateTimeOfInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
  4. LocalTime toLocalTime = localDateTimeOfInstant.toLocalTime();
  5. System.out.println(date);
  6. 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

  1. LocalDateTime localDateTime = LocalDateTime.now();
  2. Instant toInstant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
  3. Date dateFromInstant = Date.from(toInstant);
  4. System.out.println(localDateTime);
  5. System.out.println(dateFromInstant);

输出结果:

2020-06-11T15:12:11.600

Thu Jun 11 15:12:11 CST 2020

6.7 LocalDate转Date

  1. LocalDate today = LocalDate.now();
  2. LocalDateTime localDateTime = localDate.atStartOfDay();
  3. Instant toInstant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
  4. Date dateFromLocalDate = Date.from(toInstant);
  5. System.out.println(dateFromLocalDate);

输出结果:

Thu Jun 11 00:00:00 CST 2020

6.8 LocalTime转Date

  1. LocalDate localDate = LocalDate.now();
  2. LocalTime localTime = LocalTime.now();
  3. LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
  4. Instant instantFromLocalTime = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
  5. Date dateFromLocalTime = Date.from(instantFromLocalTime);
  6. System.out.println(dateFromLocalTime);

输出结果:

Thu Jun 11 15:24:18 CST 2020

7. 总结

JDK8推出了全新的日期时间类,如InstantLocaleDateLocalTimeLocalDateTimeDateTimeFormatter,设计比之前更合理,也是线程安全的。

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

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


【深度思考】JDK8中日期类型该如何使用?的更多相关文章

  1. java和数据库中日期类型的常见用法

    (1)java中日期类型:Date.Timestamp(2)数据库中:Date.Timestamp(3)字符串和Date之间的格式化转换:    SimpleDateFormat类方法: format ...

  2. 【转载】 C#中日期类型DateTime的日期加减操作

    在C#开发过程中,DateTime数据类型用于表示日期类型,可以通过DateTime.Now获取当前服务器时间,同时日期也可以像数字一样进行加减操作,如AddDay方法可以对日期进行加减几天的操作,A ...

  3. oracle中日期类型 to_date 和to_timestamp什么区别啊?

    1.to_date() 和to_timestamp()区别 由于oracle中date类型只支持到秒,不支持到毫秒,所以to_date()不能取到毫秒.如果要取到毫秒,oracle 9i以上版本,可以 ...

  4. 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 ...

  5. 解决ASP.NET MVC返回的JsonResult 中 日期类型数据格式问题,和返回的属性名称转为“驼峰命名法”和循环引用问题

    DateTime类型数据格式问题 问题 在使用ASP.NET MVC 在写项目的时候发现,返回给前端的JSON数据,日期类型是 Date(121454578784541) 的格式,需要前端来转换一下才 ...

  6. Mysql 中日期类型bigint和datetime互转

    MySql数据库中字段类型bigint 长度是10位的 mysql> select (from_unixtime(1554047999))as datatime;+--------------- ...

  7. 解决mysql 数据库中日期类型00:00:00 的问题 设置xml数据类型:java.util.Date

    解决方法是 设置xml里面字段的类型为:java.util.Date.加红部分. 1. beanl里面private Date ulLoginDate; 2.hibernate的xml里面是 < ...

  8. Node.js怎么处理数据库中日期类型

    问题描述:在数据库里存储时间的时候明明显示的是类如2016-12-22的形式,读取出来后却变成了大概是这样的:Fri May 17 2016 14:12:33 GMT+0800 (中国标准时间) 处理 ...

  9. Java 基础【09】 日期类型

    java api中日期类型的继承关系 java.lang.Object --java.util.Date --java.sql.Date --java.sql.Time --java.sql.Time ...

随机推荐

  1. dockerfile文档的相关参数

    以上是用dockerfile来构建的nginx镜像示例. 一.构建stress压力测试软件镜像 ##(1) 以下是Dockerfile内容(ENTRYPOINT是运行的环境): FROM centos ...

  2. .Net基础之3——运算符

    (3)Convert类型转换 1.类型如果相兼容的两个变量,可以使用自动类型转换或者显示类型转换. 但是如果两个类型的变量不兼容,这个时候可以使用一个叫做Convert的转换工厂进行转换. 注意:使用 ...

  3. vue触发事件的五个关键字

    v-on    vue中提供了v-on事件绑定    v-on:click='函数';    v-on可以使用@代替 vue  五个触发事件关键字    .stop 用于阻止冒泡    例如 div1 ...

  4. Meta标签基本使用

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><t ...

  5. 【JAVA习题七】输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。

    package erase; import java.util.Scanner; public class 字符串分类 { public static void main(String[] args) ...

  6. [设计模式](转)Java中的24种设计模式与7大原则

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  7. matlab单目相机标定——标定步骤以及参数含义

    参考博客园的一篇文章: https://www.cnblogs.com/flyinggod/p/8470407.html#commentform

  8. 深度学习玩LOL-游戏助手-概述

    目标 用深度学习技术实现常规英雄联盟游戏助手的主要功能,功能主要包括:英雄推荐,装备推荐,地图预警等. 基本思路 首先使用图像分类算法模型对游戏客户端内的英雄头像进行截取和识别. 使用线性回归模型对可 ...

  9. lua string方法拓展

    --[[-- 用指定字符或字符串分割输入字符串,返回包含分割结果的数组 local input = "Hello,World" local res = string.split(i ...

  10. Python机器学习笔记:SVM(1)——SVM概述

    前言 整理SVM(support vector machine)的笔记是一个非常麻烦的事情,一方面这个东西本来就不好理解,要深入学习需要花费大量的时间和精力,另一方面我本身也是个初学者,整理起来难免思 ...