旧版jdk对时间和日期的设计非常差

1、设计不合理 在java.util和Java.sql 包中都有日期类,java.util.Data同时包含日期和时间 而Java.sql.Date仅仅包含日期 此外用于格式化和解析的类在java.text包下 new Date()年份从1900算起

2、非线程安全 所有的日期类都是可变的 这是Java日期类最大的问题之一 用SimpleFormatter在多线程格式化时会出现问题

3、时区处理麻烦 日期类并不提供国际化 没有时区支持

新的日期API

JDK 8中增加了一套全新的日期时间API,这套API设计合理,是线程安全的。新的日期及时间API位于java.time包中,下面是一些关键类。

LocalDate 表示日期,包含年月日,格式为2019-10-16
LocalTime 表示时间,包含时分秒,格式为16:38:54.158549300
LocalDateTime 表示日期时间,包含年月日,时分秒,格式为2018-09-06T15:33:56.750
DateTimeFormatter 日期时间格式化类。
lnstant 时间戳,表示一个特定的时间瞬间。
Duration 用于计算2个时间(LocalTime,时分秒)的距离
Period 用于计算2个日期(LocalDate,年月日)的距离
ZonedDateTime 包含时区的时间

Java中使用的历法是ISO8601日历系统,它是世界民用历法,也就是我们所说的公历。

平年有365天,闰年是366天。此外Java8还提供了4套其他历法,分别是:

ThaiBuddhistDate:泰国佛教历

MinguoDate:中华民国历

JapaneseDate:日本历

HijrahDate:伊斯兰历

正文将通过对这8个类的详细使用介绍来学习新日期时间API的用法

1、LocalDate:

初始化日期:

  • 创建指定日期 localDate.of(int,int,int)

LocalDate date = LocalDate.of(2022,12,5);
System.out.println("date = " + date);
//sout: date = 2022-12-05
  • 获取当前日期 LocalDate.now()

LocalDate now = LocalDate.now();
System.out.println("now = " + now);
//sout: now = 2022-06-18
  • 获取日期信息

LocalDate date = LocalDate.of(2022,12,5);
​
int year = date.getYear();
// 得到年份:year = 2022
Month month = date.getMonth();
// 得到月份 month = DECEMBER(Month是枚举类型 获取数值可通过getValue )
int monthGetValue = date.getMonth().getValue();
// 得到月份 monthGetValue = 12
int monthValue = date.getMonthValue();
// 得到月份 monthValue = 12 相当于date.getMonth().getValue();
int dayOfYear = date.getDayOfYear();
// 得到一天在该年中的第多少天 dayOfYear = 339
int dayOfMonth = date.getDayOfMonth();
// 得到一天在月中的第多少天 dayOfMonth = 5 也就是经常说的几号
DayOfWeek dayOfWeek = date.getDayOfWeek();
// 得到星期 dayOfWeek = MONDAY(DayOfWeek 是枚举类型 获取数值可通过getValue)
int dayOfWeekGetValue = date.getDayOfWeek().getValue();
// 得到一天在改星期的第多少天 dayOfWeekGetValue = 1 也就是常说的礼拜几

2、LocalTime

  • 获取指定时间

LocalTime localTime = LocalTime.of(10, 30, 59);
System.out.println("localTime = " + localTime);
//sout: localTime = 10:30:59
  • 获取当前时间

LocalTime now = LocalTime.now();
System.out.println("now = " + now);
//sout: now = 10:04:49.918
  • 获取时间信息

LocalTime localTime = LocalTime.of(10, 30, 59);
​
int hour = localTime.getHour();
// hour = 10
int minute = localTime.getMinute();
// minute = 30
int second = localTime.getSecond();
// second = 59
int nano = localTime.getNano();
// nano = 1120 返回纳秒级字段。此方法返回一个介于0到999,999,999之间的整数值,即一秒的纳秒数

3、LocalDateTime

  • 获取指定日期时间

LocalDateTime localDateTime = LocalDateTime.of(2022, 6, 18, 10, 16, 55);
System.out.println("localDateTime = " + localDateTime);
//sout: localDateTime = 2022-06-18T10:16:55
  • 获取当前日期时间

LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
//sout: now = 2022-06-18T10:19:43.398
  • 获取日期时间信息

和LocalDate获取日期 LocalTime获取时间用法一致,可想像成两个的结合体

LocalDateTime now = LocalDateTime.now();
System.out.println("年:" + now.getYear());
System.out.println("月:" + now.getMonthValue());
System.out.println("日:" + now.getDayOfMonth());
System.out.println("时:" + now.getHour());
System.out.println("分:" + now.getMinute());
System.out.println("秒:" + now.getSecond());
/*
年:2022
月:6
日:18
时:10
分:41
秒:46
  • 修改日期时间

    对日期时间的修改,对已存在的LocalDateTime对象 按照原来的模板创建新的对象 并不会修改原来的日期对象

    with-- 对某个值进行修改(替换)

    withYear(int year);

    withMonth(int month);

    withDayOfMonth(int dayOfMonth);

    withDayOfYear(int dayOfYear);

    withHour(int hour);

    withMinute(int minute);

    withSecond(int second);

    withNano(int nanoOfSecond)

    LocalDateTime now = LocalDateTime.now();
    System.out.println("年:" + now.getYear());  // 年:2022
    System.out.println("now = " + now);         // now = 2022-06-18T11:06:20.318
    LocalDateTime localDateTime1 = now.withYear(1998);
    System.out.println("localDateTime1 = " + localDateTime1);
    //localDateTime1 = 1998-06-18T11:04:56.474
    System.out.println("年:" + localDateTime1.getYear());  // 年:1998

    plus-- 对某个值进行增加

    plusYears(long years);

    plusMonths(long months);

    plusWeeks(long weeks);

    plusDays(long days);

    plusHours(long hours);

    plusMinutes(long minutes);

    plusSeconds(long seconds);

    plusNanos(long nanos);

    LocalDateTime now = LocalDateTime.now();
    System.out.println("年:" + now.getYear());
    LocalDateTime localDateTime = now.plusYears(1);
    System.out.println("年:" + localDateTime.getYear());/*
    年:2022
    年:2023

    minus-- 对某个值进行减少

    方法和用法跟plus如出一辙

  • 日期时间的比较

    boolean isAfter(ChronoLocalDateTime<?> other) 是否在参数日期时间之后

    boolean isBefore(ChronoLocalDateTime<?> other) 是否在参数日期时间之前

    boolean isEqual(ChronoLocalDateTime<?> other) 是否等于参数日期时间

    LocalDateTime now = LocalDateTime.now();
    LocalDateTime plusDays = now.plusDays(1);
    LocalDateTime minusDays = now.minusDays(1);
    ​
    boolean after = plusDays.isAfter(now);
    System.out.println("after = " + after);
    // after = true
    boolean before = minusDays.isBefore(now);
    System.out.println("before = " + before);
    // before = true
    boolean equal = plusDays.isEqual(minusDays);
    System.out.println("equal = " + equal);
    // equal = false

4、格式化和解析操作

在jdk8中我们可以通过java.time.format.DateTimeFormatter 类可以进行日期的解析和格式化操作

格式化输出 String format(DateTimeFormatter formatter)

LocalDateTime now = LocalDateTime.now();
// 指定格式
DateTimeFormatter isoLocalDateTime = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String format = now.format(isoLocalDateTime);
System.out.println("format = " + format);
//sout: format = 2022-06-18T14:04:43.506
// 自定义格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String s = now.format(dateTimeFormatter);
System.out.println("s = " + s);
//sout: s = 2022-06-18 14:04:43

字符串解析成日期对象

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parse = LocalDateTime.parse("2022-05-20 22:20:20", dateTimeFormatter);
System.out.println("parse = " + parse);
// sout:parse = 2022-05-20T22:20:20

5、Instant类

在jdk8中新增一个Instant类 (时间戳) 1970-1-1 00:00:00 以来和秒数或者纳秒数

Instant now = Instant.now();
System.out.println("now = " + now);
// sout:now = 2022-06-18T06:19:50.220Z
​
// 获取从1970-1-1 00:00:00到现在的秒
long epochSecond = now.getEpochSecond();
System.out.println("epochSecond = " + epochSecond);
// sout:epochSecond = 1655533190
Thread.sleep(5000);
Instant after = Instant.now();
System.out.println("间隔时间 = " + (after.getEpochSecond() - now.getEpochSecond()));
// sout: 间隔时间 = 5

6、计算日期时间差

JDK8中提供两个工具类Duration、Period 来计算时间差

  1. Duration 用来计算两个时间差 (LocalTime)Duration between(Temporal startInclusive, Temporal endExclusive)

  2. Period 用来计算两个日期差(LocalDate) Period between(LocalDate startDateInclusive, LocalDate endDateExclusive)

// 通过Duration来计算时间差
LocalTime now = LocalTime.now();
LocalTime plusHours = now.plusHours(1).plusMinutes(12).plusSeconds(33);
Duration duration = Duration.between(now, plusHours);
System.out.println("duration = " + duration.toHours()+"小时"+duration.toMinutes()+"分钟"+duration.toMillis()+"秒");
// sout: duration = 1小时72分钟4353000秒
​
// 通过Period来计算日期差
LocalDate nowDate = LocalDate.now();
LocalDate date = LocalDate.of(2022, 10, 12);
Period between = Period.between(nowDate, date);
System.out.println("period = " + between.getYears()+"年"+between.getMonths()+"月"+between.getDays()+"日");
// sout:period = 0年3月24日

7、时间矫正器

TemporalAdjuster类是一个函数式接口,提供了一个抽象方法adjustInto 该方法被多个类实现 每个实现类下也有不同的操作 本文就不作详细展开了

LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
// sout: now = 2022-06-18T15:17:13.481
TemporalAdjuster adjuster = t -> t.plus(Period.ofDays(1)); // 加一天
LocalDateTime with1 = now.with(adjuster);
System.out.println("with1 = " + with1);
// sout: with1 = 2022-06-19T15:17:13.481
​
TemporalAdjuster adjuster1 = (temporal)->{
LocalDateTime dateTime = (LocalDateTime) temporal;
LocalDateTime localDateTime = dateTime.plusMonths(1).withDayOfMonth(1); //下个月第一天
return localDateTime;
};
LocalDateTime with = now.with(adjuster1);
System.out.println("with = " + with);
// sout: with = 2022-07-01T15:17:13.481

TemporalAdjusters类中预定义实现

TemporalAdjusters类有很多预定义的static方法返回TemporalAdjuster对象,使用不同方式调节Temporal对象而与Temporal实现无关。

dayOfWeekInMonth(2,DayOfWeek.TUESDAY)  一周中的某一天,例如,三月中第二个星期二
firstDayOfMonth()  当前月的第一天
firstDayOfNextMonth() 下一个月的第一天
firstDayOfNextYear()  下一年的第一天
firstDayOfYear()  当年的第一天
lastDayOfMonth()  当月的最后一天
lastDayOfYear()  当年的最后一天
​
previous(DayOfWeek.MONDAY) 上周周一
previousOrSame(DayOfWeek.MONDAY) 上周或当天发生的一周中的周一
next(DayOfWeek.MONDAY) 下周周一
nextOrSame(DayOfWeek.MONDAY)  下周或当天发生的一周中的周一

8、日期时间的时区

JDK8中加入了对时区的支持,LocalDate、LocalTime、LocalDateTime 是不带时区的,带时区的日期时间类型分别是 ZoneDate、ZoneTime、ZoneDateTime。

其中每个时区都对应着不同的ID ID的格式为“区域、城市” 例如 Asia/ShangHai等

ZoneId : 该类中包含了所有的时区信息

// 获取所有的时区id
ZoneId.getAvailableZoneIds().forEach(s->{if (s.contains("Shang")){System.out.println("s = " + s);}
});
​
// 获取当前时间 中国使用的 东八区的时区 比标准时间早8小时
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
​
// 获取标准时间
ZonedDateTime zonedDateTime = ZonedDateTime.now(Clock.systemUTC());
System.out.println("标准时区时间 = " + zonedDateTime);
​
// 使用计算机默认的时区 创建日期时间
ZonedDateTime zonedDateTime1 = ZonedDateTime.now();
System.out.println("默认时区时间 = " + zonedDateTime1);
​
// 使用指定的时区创建日期时间
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("America/Marigot"));
System.out.println("自定义时区时间 = " + zonedDateTime2);
s = Asia/Shanghai
now = 2022-06-18T16:24:34.836
标准时区时间 = 2022-06-18T08:24:34.836Z
默认时区时间 = 2022-06-18T16:24:34.836+08:00[Asia/Shanghai]
自定义时区时间 = 2022-06-18T04:24:34.836-04:00[America/Marigot]

JDK8新特性:新日期时间API全面学习相关推荐

  1. 重学Java8新特性(四) : 日期时间API、LocalDateTime、DateTimeFormatter、开发中时间工具类(常用)

    文章目录 一.JDK8中日期时间API的介绍 1.1.LocalDate.LocalTime.LocalDateTime的使用 2.2.Instant类的使用 2.3.DateTimeFormatte ...

  2. java 8 新特性之日期-时间 API

    Date-Time API简介 在Java8之前的版本中,我们处理时间类型常常使用的是java.util包下的Date类.但使用Date类却有诸多的弊端,如: java.util.Date 是非线程安 ...

  3. java8 日期api_我们多么想要新的Java日期/时间API?

    java8 日期api 当前的Java.net 民意测验问题是:" 对于用Java 8实现的JSR-310(新的日期和时间API)有多重要? "在我撰写本文时,将近150位受访者投 ...

  4. 我们多么想要新的Java日期/时间API?

    当前的Java.net 民意测验问题是:" 对于用Java 8实现的JSR-310(新的日期和时间API)有多重要? "在我撰写本文时,将近150位受访者投了赞成票,绝大多数人回答 ...

  5. 6 日期字符串转日期_Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类...

    因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API.Stephen向JCP提交了 ...

  6. java 包结构 枚举类_Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类...

    因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API.Stephen向JCP提交了 ...

  7. JDK8新特性(十四)之日期时间API

    旧版日期时间API存在的问题: 1. 设计很差: 在java.util和java.sql的包中都有日期类,java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期.此外用 ...

  8. 详解Java8特性之新的日期时间 API

    #吐槽 Java 8 提供了一套新的日期时间 API,为什么要这么干呢.因在旧版的 Java 中,日期时间 API 存在很多问题,比如说线程安全问题了, java.util.Date 是非线程安全的, ...

  9. 高级JAVA开发必备技能:java8 新日期时间API((一)JSR-310:ZoneId 时区和偏移量)(JAVA 小虚竹)

    技术活,该赏 点赞再看,养成习惯 大家好,我是小虚竹.之前有粉丝私聊我,问能不能把JAVA8 新的日期时间API(JSR-310)知识点梳理出来.答案是肯定的,谁让我宠粉呢.由于内容偏多(超十万字了) ...

最新文章

  1. MySQL创建相同表和数据命令
  2. java jdk1.5 对for循环遍历的优化
  3. ubuntu 开启关闭mysql 服务
  4. 堆排序(如何手写堆)
  5. 最实用的logback讲解(2)—appender
  6. element-ui中table表头错位问题
  7. 分布式是写出来的(三)
  8. linux下的多线程
  9. html行分割,如何确定一个html标签是否分割成多行
  10. 邮箱服务器端口以及各大型邮箱smtp服务器及端口收集
  11. '转载'Tableau试用过后破解失败解决方法,清除注册表工具
  12. ESP32 WS2812B灯带 代码
  13. APICloud前端框架
  14. HTML简单动画制作
  15. RSH-810微机智能母线电弧光保护装置
  16. Vue3+ Vue-cli (2) 组件篇
  17. js json操作,qk-json
  18. “沙盘” 系统
  19. 【香港科技大学(广州)】博士后/博士/硕士/研究助理招聘
  20. 通告(公告),消息(站内短信),提醒的设计:通告

热门文章

  1. Cortex-M55 AI-NPU集成
  2. springboot毕设项目java学习平台m55rv(java+VUE+Mybatis+Maven+Mysql)
  3. Rocket Smart Grid mit LTE Routern Internet shoots for €1.5 billion IPO
  4. 阿里巴巴中国站获取1688app上原数据 API 返回值说明
  5. .NET性能优化-推荐使用Collections.Pooled
  6. mybatis 连接池POOLED分析
  7. mtk平台usb序列号与手机序列号
  8. IE浏览器过期,自动跳转至Edge解决办法
  9. img图像标签-HTML入门基础(017)
  10. 网易云音乐热评详细源码-Python