新的日期和时间( Java 8 )

2023-11-03

为什么我们需要新的Date和Time类!

  • Java8之前所有的日期类都是可变的,这就导致了线程不安全问题;
  • java的日期和时间类的定义不一致,在java.util和java.sql中都包含日期类;
  • java.util.Date同时包含日期和时间,但是java.sql中只包含日期,将其纳入java.sql中的是不合适的,而且更糟糕的是:这两个类中的日期类的名字都是一样的;
  • 对于时间、时间戳、格式化及解析,没有一些明确定义的类,而且对于格式化和解析的需求,Java中有java.text.DateFormat抽象类,但是通常我们用的是SimpleDateFormate类进行格式化和解析
  • 日期类不支持国际化,没有时区支持,即使Java引入了-java.util.Calendar和java.util.TimeZone类,但是问题依然存在。

Java8新的日期和时间API的设计原则

Java8中新的日期和时间是基于JSR-310实现的,参考了绝大多数的joda-timeApi。

  • 不变性:新的日期/时间API中,所有的类都是不可变的,实现了线程安全;
  • 关注点分离:新的API中将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date)、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类;
  • 清晰明了:新的API中,方法都被明确定义用以完成相同的行为,例如,想要拿到当前实例,可以用new()方法,在所有的类方法中都实现了formate()和parse()方法,不再是之前用单独一个类去解决,而且新的API中所有的类都使用了工厂模式和策略模式;
  • 实用性:所有新的日期和时间API类都实现了一系列方法用以完成通用的需求,例如:加、减、格式化、解析、从日期或时间中提取单独部分等等;
  • 可扩展性:新的日期/时间API是基于国际标准ISO 8601,其实我们也是可以将其用于非IOS的日历上

Java8中的日期和时间API包含以下包

  • java.time包:这是新的Java日期/时间API的基础包,所有的主要基础类都是该包的一部分,例如:LocalDate、LocalTime、LocalDateTime、Instant、Period、Duration等类。这些类都是线程安全的
  • java.time.chrono包:这个包为非ISO的日历标准定义了一些泛化的API,我们可以拓展AbstractChronology来创建自己的日历标准
  • java.time.formate包:这个包包含能够格式化和解析日期时间对象的类,在绝大数情况下,我们不应该直接使用它,因为java.time包中相应的类已经提供了格式化和解析的方法
  • java.time.temporal包:这个包包含一些时态对象,可以用其找出关于某个日期/时间对象的某个特定日期或时间,比如说找到某个月的第一天或最后一天,可以根据withXXX的格式进行区分
  • java.time.zone包:这个包支持不同的时区以及相关规则的类

Java8中引入的关于日期和时间的新类:Period和Duration类,两个类表示两个日期和时间之间的差,Period基于日期,Duration类基于时间

Period类

概述:该类表示一段时间的年、月、日

  1. 使用该类中between()方法获取两个日期之间的差作为Period对像返回;
// 代码示例
LocalDate startTime = LocalDate.of(2020,10,01);
LocalDate endTime = LocalDate.of(2021,11,20);
Period timeSub = Period.between(startTime,endTime);
System.out.println("year:"+timeSub.getYears());
System.out.println("month:"+timeSub.getMonths());
System.out.println("day:"+timeSub.getDays());
  1. 使用该类中的isNegative()方法判断起止日期的大小
    (false为endTime大于startTime,否则相反)原理是根据该该方法(不需要参数)会校验Period对象中的天、月、年是否为负,为负则返回true,为正则返回false
// 代码示例
LocalDate startTime = LocalDate.of(2020,10,01);
LocalDate endTime = LocalDate.of(2021,11,20);
Period timeSub = Period.between(startTime,endTime);
System.out.println(timeSub.isNegative());
  1. 使用该类的plusXXX()方法、minusXXX()方法可以进行日期的增加和减少
// 代码示例
Period periodTime = Period.of(2020,10,26);
//年
String plusYears = periodTime.plusYears(1).toString();
String minusYears = periodTime.minusYears(1).toString();
//月
String plusMonths = periodTime.plusMonths(1).toString();
String minusMonths = periodTime.minusMonths(1).toString();
//日
String plusDays = periodTime.plusDays(1).toString();
String minusDays = periodTime.minusDays(1).toString();

Duration类

概述:表示秒或纳秒的时间间隔,适合处理较短的时间,且需要更高的精确性

  1. 使用该类中between()方法比较两个瞬间的差值
// 代码示例
Instant start = Instant.parse("2020-10-12T10:12:12.00Z");
Instant end = Instant.now();
System.out.println(end.toString());
Duration duration = Duration.between(start,end);
System.out.println(duration.isNegative());
  1. 使用该类中的isNegative()方法判断起止时间的大小
    (false为endTime大于startTime,否则相反)原理是根据该该方法(不需要参数)会校验Duration对象中的天、月、年是否为负,为负则返回true,为正则返回false
// 代码示例(使用LocalTime也可以获取Duration对象)
LocalTime startTime = LocalTime.of(1,10,30,234);
LocalTime endTime  = LocalTime.of(1,20,30,234);
Duration duration = Duration.between(startTime,endTime);
System.out.println(duration.isNegative());
  1. 使用该类的plusXXX()方法、minusXXX()方法可以进行日期的增加和减少
// 代码示例(使用该类中的ofDays方法也可以获取Duration对象)
Duration durationDays = Duration.ofDays(1);
String addDays = durationDays.plusDays(1).toString();
System.out.println(durationDays.getSeconds());

Duration durationHours = Duration.ofHours(3);
String minusHours = durationHours.minusHours(1).toString();
System.out.println(durationHours.getSeconds());

Duration durationMinutes = Duration.ofMinutes(1);
System.out.println(durationMinutes.getSeconds());

Duration durationMillis = Duration.ofMillis(1);
System.out.println(durationMillis.getSeconds());
System.out.println(durationMillis.getNano());

Instant类

概述:表示某个时间,不带时区的即时时间点,精确到纳秒

内部由两个Long字段组成,第一部分保存自标准Java时代到现在的秒数,第二部分保存的是纳秒数(不会超过999,999,999)。注意:通过这种方式获取的时间戳与北京时间相差8个时区,需要修正为北京时间,通过查看源代码发现Instant.now()使用等是UTC时间Clock.systemUTC().instant()。LocalDate、LocalDateTime 的now()方法使用的是系统默认时区 不存在Instant.now()的时间问题。

  1. Instant相当于Date,以下是相互转换
// 代码示例
//类方法java.time.Instant
Instant instant = Instant.now();
System.out.println(instant);
Instant beijingTime = Instant.now().plus(8, ChronoUnit.HOURS);
System.out.println(beijingTime);

//类方法java.util.Date
Date date = new Date();
System.out.println(date);

date = Date.from(instant);
System.out.println(date);

instant = date.toInstant();
System.out.println(instant);
  1. Instant类中通过固定时间转换为Instant对象的方法
//根据Date转换为instant(java.util.Instant中方法)
Date date = new Date();
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println(instant);
//根据毫秒转换为instant(java.util.Instant中方法)
instant = Instant.ofEpochMilli(1000 * 60 * 60 * 24);
System.out.println(instant);
//根据秒转换为instant(java.util.Instant中方法)
instant = Instant.ofEpochSecond(60 * 60 * 24 * 5);
System.out.println(instant);
//根据秒和纳秒转换为instant(java.util.Instant中方法),这样得到的instant会包含纳秒的数据 1000000000纳秒(9位)=1秒
instant = Instant.ofEpochSecond(60 * 60 * 24,1000000000*60);
System.out.println(instant);
  1. Instant类中的parse方法
// 代码示例
//该方法的入参仅支持UTC格式的字符串,而且date结果的字符串会报出DateTimeParseException异常
Instant instant = Instant.parse("2020-10-26T12:10:00Z");
System.out.println(instant);
  1. Instant类中的加减日期方法(加)plus()和(减)minus()方法
// 代码示例
//ChronoUnit位于java.time.temporal,Periodjava位于Java.time
//plus()方法会产生一个新的instant对象
//plus()方法给当前日期增加五天
Instant instant = Instant.now();
Instant instantAddDayOne = instant.plus(5, ChronoUnit.DAYS);
Instant instantAddDayTwo = instant.plus(Period.ofDays(5));
Instant instantAddDayTwo1 = instant.plus(Duration.ofDays(5));
System.out.println(instantAddDayOne.toString());
System.out.println(instantAddDayTwo.toString());
System.out.println(instantAddDayTwo1.toString());
System.out.println(instant == instantAddDayOne);
//minus()方法会产生一个新的instant对象
//minus()方法给当前日期减少五天
Instant instantSubDay = instant.minus(5, ChronoUnit.DAYS);
Instant instantSubDayTwo = instant.minus(Period.ofDays(5));
Instant instantSubDayTwo1 = instant.minus(Duration.ofDays(5));
System.out.println(instantSubDay);
System.out.println(instantSubDayTwo);
System.out.println(instantSubDayTwo1);
System.out.println(instant == instantSubDayTwo);
  1. Instant类中比较两个日期的大小
// 代码示例
Instant instantNow = Instant.now();
Instant instantAddDay = instantNow.plus(Duration.ofDays(5));
//isAfter()方法判断instantAddDay是否在instantNow之后
boolean flgAfter = instantAddDay.isAfter(instantNow);
System.out.println(flgAfter);
//isBefore()方法判断instantAddDay是否在instantNow之前
boolean flgBefore = instantAddDay.isBefore(instantNow);
System.out.println(flgBefore);
//compareTo()方法比较,前者时间纳秒值大于后者返回1,小于返回-1,等于返回0
int result1 = instantAddDay.compareTo(instantNow);
System.out.println(result1);
int result2 = instantNow.compareTo(instantAddDay);
System.out.println(result2);
int result3 = instantNow.compareTo(instantNow);
System.out.println(result3);
  1. Instant类计算两个日期的差值
// 代码示例
Instant instantNow = Instant.now();
Instant instantAddDay = instantNow.plus(Duration.ofDays(5));
//between()方法后者比前者大,返回正数,比前者小返回负数,相等返回0(ChronoUnit.DAYS位于java.time.temporal)
long result1 = ChronoUnit.DAYS.between(instantNow, instantAddDay);
System.out.println(result1);
long result2 = ChronoUnit.DAYS.between(instantAddDay, instantNow);
System.out.println(result2);
long result3 = ChronoUnit.DAYS.between(instantNow, instantNow);
System.out.println(result3);

LocalDateTime类

概述:表示不带时区的日期及时间,替换之前的Calendar

**注意:**看上去,LocalDateTime和Instant很象,但记得的是“Instant中是不带时区的即时时间点。可能有人说,即时的时间点 不就是日期+时间么?看上去是这样的,但还是有所区别,比如LocalDateTime对于用户来说,可能就只是一个简单的日期和时间的概念,考虑如下的 例子:两个人都在2013年7月2日11点出生,第一个人是在英国出生,而第二个是在加尼福利亚,如果我们问他们是在什么时候出生的话,则他们看上去都是 在同样的时间出生(就是LocalDateTime所表达的),但如果我们根据时间线(如格林威治时间线)去仔细考察,则会发现在出生的人会比在英国出生的人稍微晚几个小时(这就是Instant所表达的概念,并且要将其转换为UTC格式的时间)。

  1. LocalDateTime获取当前时间(系统自带默认时间)
// 代码示例
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
  1. LoclaDateTime类中时间加减计算(加)plusXXX()和(减)minusXXX()方法
// 代码示例
// plus()和minus()方法与Instant类中相同
LocalDateTime localDateTime1 = localDateTime.plusHours(5);
System.out.println(localDateTime1);
System.out.println(localDateTime1 == localDateTime);
LocalDateTime localDateTime2 = localDateTime.minusHours(5);
System.out.println(localDateTime2);
System.out.println(localDateTime2 == localDateTime);
  1. LocalDateTime显示年月日,不显示时间;显示时间,不显示年月
// 代码示例
LocalDateTime localDateTime = LocalDateTime.now();
//显示年月日,且增加两个月
LocalDate localDate = localDateTime.toLocalDate().plusMonths(2);
System.out.println(localDate);
//显示时分秒毫秒,且减少两个小时
LocalTime localTime = localDateTime.toLocalTime().minusHours(2);
System.out.println(localTime);
  1. LocalDateTime类中格式化日期的两种方式
// 代码示例
//通过Instant类获取当前系统时间,ZoneId.systemDefault设置为系统默认时区
//ZoneId位于java.time
LocalDateTime localDateTime1 = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
System.out.println(localDateTime1);
//通过DateTimeFormatter类中的ofPattern方法获取自定义格式的系统时间,位于java.time.format
String localDateTimeStr = localDateTime1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(localDateTimeStr);

文章借鉴处

  • https://blog.csdn.net/fragrant_no1/article/details/83988042
  • https://blog.csdn.net/neweastsun/article/details/88770592
  • https://blog.csdn.net/liubenlong007/article/details/62039628
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

新的日期和时间( Java 8 ) 的相关文章

随机推荐

  • 深入理解AMBA总线——AXI原子访问机制和AXI响应

    本篇文章给大家讲解AXI协议的原子访问机制 1 Atomic访问机制 1 1 Atomic信号 众所周知 操作系统的很多机制需要底层硬件的支持 如并发 虚拟化等 随着多处理器的流行 arm也自然而然的要做其总线上加入和并发相关的信号 以满足
  • 【kubernetes系列】k8s ingress配置websocket支持

    背景 公司的后端同事在代码调试过程中需要上传一个文件 调用的websocket接口 了解同事需求和现象 浏览器上传文件一直卡主 通过浏览器调试模式发现无法正常获取websocket的连接 websocket的接口访问可以通过wscat命令
  • CTFHUB-Cookie注入

    Cookie Cookie 浏览器向服务器发送请求时发送cookie 或者服务器向浏览器附加cookie 就是将cookie附近在这里的 例如 Cookie user admin HackBar Load一下 BurpSuite等工具也可以
  • vuex固化插件的使用

    数据持久化 刷新页面 vuex里面数据丢失 清空 有时候我们需要把一些数据固话到本地 即使刷新也不能清空 第一步 需要先下载插件 npm install vuex persistedstate save 第二步 在 store index
  • linux配置SVN,添加用户,配置用户组的各个权限教程

    前言 今天组长要我给新员工添加svn 的权限 以及赋予他们权限访问指定的目录 于是就顺手写个教程吧 毕竟好记性不如烂笔头 一 xshell登陆服务器 用xshell登陆服务器 cd切换到服务器中svn的项目仓库目录中 然后切换到conf文件
  • java利用freemark和itext出pdf文件

    第一步导包
  • Navicat Premium

    一 简介 Navicat Premium 是一套数据库开发工具 让你从单一应用程序中同时连接 MySQL MariaDB SQL Server Oracle PostgreSQL 和 SQLite 数据库 它与 Amazon RDS Ama
  • 计算机基础汇总

    计算机基础汇总 时间复杂度 https blog csdn net qq 41523096 article details 82142747 数组与链表 https blog csdn net qq 25806863 article det
  • normalize.css在vue中使用

    css样式初始化 normalize在vue中使用 1 Normalize css只是一个很小的css文件 但它在磨人的HTML元素样式上提供了跨浏览器的高度一致性 相比于传统的CSS reset Normalize css是一种现代的 为
  • CUDA - 在CUDA C/C++中使用共享内存

    原文链接 Using Shared Memory in CUDA C C 文章目录 共享内存 线程同步 共享内存示例 静态共享内存 动态共享内存 共享内存bank冲突 配置共享内存数量 总结 在上一篇文章中 我研究了如何将一组线程的全局内存
  • F12复制返回的json

    第一步 打印返回的数据 然后打开控制台 第二步 在打印的res右键出现会出现Store as global variable 然后点击 出现temp 第三步 在控制台输入copy temp 第四步 这个时候已经复制好json了 直接粘贴到t
  • 计算除法java实现

    class Solution public double calcEquation List
  • ROS报错[joint_state_publisher_gui-1] process has died [pid 70747, exit code 1, cmd...

    1 报错 终端里运行 roslaunch mbot description display mbot launch 出现报错如下 joint state publisher gui 1 process has died pid 70747
  • 凹下去的白色按钮

    先看效果 再看代码
  • 关于分页的参数说明

    使用分页 如果Pageable是不是为null 此代码说明如果不为null PageHelper startPage currentPage pageSize true 第一个参数表示从第几页开始 第二个参数表示一页多少条记录 第三个参数表
  • Unity鼠标事件详解

    鼠标事件详解 1 3D物体 OnMouseDown 鼠标按下 OnMouseDrag 鼠标在按下时拖动 OnMouseUp 鼠标抬起 OnMouseEnter 鼠标进入 OnMouseExit 鼠标离开 OnMouseOver 鼠标经过 O
  • bert第三篇:tokenizer

    文章目录 tokenizer基本含义 bert里涉及的tokenizer BasicTokenzer wordpiecetokenizer FullTokenzier PretrainTokenizer 关系图 实操 如何训练 训练自己中文
  • Google Play的QUERY_ALL_PACKAGES或REQUEST_INSTALL_PACKAGES权限问题

    情况1 你的应用需要使用QUERY ALL PACKAGES权限 就按照Google Play政策要求上传这块功能视频了 情况2 应用不需权限 就把自己AndroidManifest xm中两个权限删除
  • 【华为面试题】动态规划

    题目 题目描述 一个充电站有n个不同功率的充电设备 您的任务是从中选取若干个设备 使得他们的总功率最接近但不超过充电站的最大输出功率P max 输入 第一行 一个整数n 代表充电设备的数量 第二行 n个整数 分别代表每个设备的功率 第三行
  • 新的日期和时间( Java 8 )

    为什么我们需要新的Date和Time类 Java8之前所有的日期类都是可变的 这就导致了线程不安全问题 java的日期和时间类的定义不一致 在java util和java sql中都包含日期类 java util Date同时包含日期和时间