【Java8日期】一文搞定Java8日期新特性

2023-10-31

目录标题

前言

Java对日期、日历及时间的处理一直以来都饱受诟病,比如java.util.Date和java.util.Calendar类易用性差,不支持时区,非线程安全;还有用于格式化日期的类DateFormat也是非线程安全的等问题

Java8引入的新的一系列API,对时间日期的处理提供了更好的支持,清楚的定义了时间日期的一些概念,比如说,瞬时时间(Instant),持续时间(duration),日期(date),时间(time),时区(time-zone)以及时间段(Period)

Java8日期类型

简介

1、核心类

Java8常用的日期和时间类包含LocalDate、LocalTime、Instant、Duration、Period、LocalDateTime以及ZonedDateTime等。

LocalDate:不包含时间的日期,比如2019-10-14。可以用来存储生日,周年纪念日,入职日期等。
LocalTime:与LocalDate想对照,它是不包含日期的时间。
LocalDateTime:包含了日期及时间,没有偏移信息(时区)。
ZonedDateTime:包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。
Instant:时间戳,与System.currentTimeMillis()类似。
Duration:表示一个时间段。
Period:用来表示以年月日来衡量一个时间段。

另外,还有新的日期解析格式化类DateTimeFormatter

2、关键点

Java8中关于时间日期的API有以下关键点:

  1. 提供了javax.time.ZoneId用来处理时区。
  2. 提供了LocalDate与LocalTime类。
  3. 时间与日期API中的所有类都是线程安全的。
  4. 明确定义了基本的时间与日期概念。
  5. 核心API:Instant、LocalDate、LocalTime、LocalDateTime、ZonedDateTime。
  6. DateTimeFormatter类用于在Java中进行日期的格式化与解析。

LocalDate

LocalDate类内只包含日期,不包含具体时间。只需要表示日期而不包含时间,就可以使用它。

1、获取当前日期、年、月、日

// 只获取日期
LocalDate today = LocalDate.now();
System.out.println(today);

int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();

System.out.printf("Year : %d Month : %d day : %d \t %n", year, month, day);

2、获取月、周的第几天

同时,还可以通过LocalDate获取日期是月份的第几天、周的第几天,月份的天数,是否为闰年等。看下面的代码是不是非常方便。

LocalDate today = LocalDate.now();
// 月份中的第几天
int dayOfMonth = today.getDayOfMonth();
// 一周的第几天
DayOfWeek dayOfWeek = today.getDayOfWeek();
// 月份的天数
int length = today.lengthOfMonth();
// 是否为闰年
boolean leapYear = today.isLeapYear();

3、随意创建日期

上面通过now获取LocalDate对象,也可以通过静态方法of()或parse创建任意一个日期。再也不用像之前一样年只能从1900年开始,月必须从0开始等。

LocalDate oneDay = LocalDate.of(2019,10,1);
System.out.println(oneDay);

4、比较两个LocalDate是否相同

LocalDate重写了equals方法,让日期的比较也变得简单了。

// 定义任意日期
LocalDate oneDay = LocalDate.of(2019, 10, 1);
System.out.println(oneDay);

// 定义任意比较
LocalDate anyDay = LocalDate.of(2019, 10, 1);
System.out.println(oneDay.equals(anyDay));

同时,针对日期还可延伸出MonthDay或YearMonth类,顾名思义,只包含月天或年月。同样适用于equals方法来比较。

5、比较两个LocalDate的大小

boolean notBefore = LocalDate.parse("2019-10-01").isBefore(LocalDate.parse("2019-10-02"));
boolean isAfter = LocalDate.parse("2019-10-01").isAfter(LocalDate.parse("2019-10-02"));

6、对天、月进行加减

对日期进行前一天后一天或前一个月的加减也变得十分方便。

LocalDate tomorrowDay = LocalDate.now().plusDays(1);
LocalDate nextMonth =  LocalDate.now().plusMonths(1);

7、获取两个日期相减间隔

between内的参数类型可以是:LocalDateTime、LocalDate、LocalTime。

LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration = Duration.between(from, to);
// 区间统计换算
// 总天数
long days = duration.toDays();
// 小时数
long hours = duration.toHours();
// 分钟数
long minutes = duration.toMinutes();
// 秒数
long seconds = duration.getSeconds();
// 毫秒数
long milliSeconds = duration.toMillis();
// 纳秒数
long nanoSeconds = duration.toNanos();

8、字符串转日期对象

LocalDate parseDay = LocalDate.parse("2019-10-01");
System.out.println(parseDay);

LocalTime

LocalTime和LocalDate类似,区别在于LocalDate不包含具体时间,而LocalTime包含具体时间。

  1. localtime可以表示的最大值是:23:59:59,24小时转换为秒值是86399,超过这个值报错;
  2. LocalTime获得的时间格式为:11:41:58.904。也就是,HH:mm:ss.nnn,这里nnn是纳秒*

1、获取当前时间&&随意创建时间对象

同样可以使用now或of方法来获得对象。

//获取当天时间  HH:mm:ss.nnn
LocalTime localTime = LocalTime.now();

// of方式创建时间对象
LocalTime oneTime = LocalTime.of(10,10,10);
// ofSecondOfDay方式创建时间对象
LocalTime localTime = LocalTime.ofSecondOfDay(seconds);

2、获取时分秒 && 比较时间大小 && 字符串转时间对象

LocalDate类似它也拥有parse(字符串转时间对象)、isBefore(比较两个时间大小)、获取时间单元(时分秒)等方法,就不再赘述。

3、获取最大时间和最小时间

还有一个在实战中查询日期区间时我们经常定义的“23:59:59.99”常量再也不用自己定义了。

// 23:59:59.999999999
LocalTime maxTime = LocalTime.MAX;
// 00:00
LocalTime minTime = LocalTime.MIN;

4、获取两个时间相差间隔

between内的参数类型可以是:LocalDateTime、LocalDate、LocalTime。

LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration = Duration.between(from, to);
// 区间统计换算
// 总天数
long days = duration.toDays();
// 小时数
long hours = duration.toHours();
// 分钟数
long minutes = duration.toMinutes();
// 秒数
long seconds = duration.getSeconds();
// 毫秒数
long milliSeconds = duration.toMillis();
// 纳秒数
long nanoSeconds = duration.toNanos();

LocalDateTime

LocalDateTime表示日期和时间组合。

1、获取当前日期时间 && 随意创建日期时间 && 拼接

可以通过of()方法直接创建,也可以调用LocalDate的atTime()方法或LocalTime的atDate()方法将LocalDate或LocalTime合并成一个LocalDateTime。

LocalDateTime now = LocalDateTime.now();

LocalDateTime oneTime = LocalDateTime.of(2019,10,14,10,12,12);

// 拼接日期
LocalTime.now().atDate(LocalDate.now());

2、日期时间增、减、比较大小

LocalDateTime与LocalDate和LocalTime之间可以相互转化。其他日期增减等操作与上面的类似。

3、获取两个日期时间相减间隔

```java
LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration = Duration.between(from, to);
// 区间统计换算
// 总天数
long days = duration.toDays();
// 小时数
long hours = duration.toHours();
// 分钟数
long minutes = duration.toMinutes();
// 秒数
long seconds = duration.getSeconds();
// 毫秒数
long milliSeconds = duration.toMillis();
// 纳秒数
long nanoSeconds = duration.toNanos();

4、获取一天的开始、结束时间

//获取一天的开始时间,2017,7,22 00:00
  public static LocalDateTime getDayStart(LocalDateTime time) {
    return time.withHour(0)
        .withMinute(0)
        .withSecond(0)
        .withNano(0);
  }
 
  //获取一天的结束时间,2017,7,22 23:59:59.999999999
  public static LocalDateTime getDayEnd(LocalDateTime time) {
    return time.withHour(23)
        .withMinute(59)
        .withSecond(59)
        .withNano(999999999);
  }

Instant-获取时间戳

Instant用于一个时间戳,与System.currentTimeMillis()类似,但Instant可以精确到纳秒(Nano-Second)。

1、获取当前时间戳

Instant除了可以使用now()方法创建,还可以通过ofEpochSecond方法创建。

Instant now = Instant.now();
// 其中ofEpochSecond第一个参数表示秒,第二个参数表示纳秒。整体表示:从1970-01-01 00:00:00开始后的365天100纳秒的时间点
long tiemstamp = Instant.ofEpochSecond(365 * 24 * 60, 100);

Duration-获取时间段

Duration的内部实现与Instant类似,但Duration表示时间段。

1、创建Duration

通过between方法创建:

LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration = Duration.between(from, to);

Duration对象还可以通过of()方法创建,该方法参数为时间段长度和时间单位:

// 7天
Duration duration1 = Duration.of(7, ChronoUnit.DAYS);
// 60秒
Duration duration2 = Duration.of(60, ChronoUnit.SECONDS);

2、获取日期时间相差天、时、分、秒、毫秒

between内的参数类型可以是:LocalDateTime、LocalDate、LocalTime。

LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration = Duration.between(from, to);
// 区间统计换算
// 总天数
long days = duration.toDays();
// 小时数
long hours = duration.toHours();
// 分钟数
long minutes = duration.toMinutes();
// 秒数
long seconds = duration.getSeconds();
// 毫秒数
long milliSeconds = duration.toMillis();
// 纳秒数
long nanoSeconds = duration.toNanos();

Period-获取日期段

Period与Duration类似,获取一个时间段,只不过单位为年月日

1、创建Period时间段

也可以通过of方法和between方法创建,between方法接收的参数为LocalDate。

Period period = Period.of(1, 10, 25);
Period period1 = Period.between(LocalDate.now(), LocalDate.now().plusYears(1));

ZonedDateTime-创建时区时间

ZonedDateTime类,用于处理带时区的日期和时间。ZoneId表示不同的时区。大约有40不同的时区。

//获取所有时区集合:
Set allZoneIds = ZoneId.getAvailableZoneIds();

//创建时区:
ZoneId zoneId = ZoneId.of("Asia/Shanghai");

//把LocalDateTime转换成特定的时区:
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), zoneId);

另外和时区一起使用的类是OffsetDateTime类,OffsetDateTime是不变的,表示date-time偏移,存储所有日期和时间字段,精确至纳秒,从UTC/Greenwich计算偏移。

日期相关的类型转换

Java8日期与字符串转换

1、日期格式的两种定义方式

Java8对日期的格式化操作非常简单,首先看到上面的类大多都提供了parse方法,可以直接通过解析字符串得到对应的对象。

  1. 可以使用DateTimeFormatter预置的格式DateTimeFormatter.ISO_LOCAL_DATE_TIME;
  2. 可以通过DateTimeFormatter.ofPattern方法来指定格式。
LocalDateTime dateTime = LocalDateTime.now();
String str = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
System.out.println(str);
str = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(str);

2、字符串与日期、时间、日期时间互转

public class DateTimePatternConstant {

    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public static final String DATE_PATTERN = "yyyy-MM-dd";

    public static final String TIME_PATTERN = "HH:mm:ss";
}
public class DateTimeAndStringConvertTest {
    public static void main(String[] args) {
        String startDateStr = "2021-08-15 09:09:09";
        String endDateStr = "2021-08-15 10:10:10";

        String date = "2021-08-15";

        String time = "01:01:01";

        String dateTimePattern = DateTimePatternConstant.DATE_TIME_PATTERN;

        String datePattern = DateTimePatternConstant.DATE_PATTERN;

        String timePattern = DateTimePatternConstant.TIME_PATTERN;

        // 日期时间与字符串相互转换示例
       // dateTime_str_convert(startDateStr, dateTimePattern);

        // 日期与字符串相互转换示例
        date_string_convert(date, datePattern);

        // 时间与字符串相互转换示例同理

    }

    private static void date_string_convert(String date, String datePattern) {
        // 字符串-->日期对象
        LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern(datePattern));
        // 日期对象-->指定格式的字符串
        String format = localDate.format(DateTimeFormatter.ofPattern(datePattern));
        // 2021-08-15
        System.out.println(format);
    }

    private static void dateTime_str_convert(String startDateStr, String pattern) {

        // Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-08-15' could not be parsed at index 10
        //LocalDateTime localDate = LocalDateTime.parse(date);

         // 字符串-->日期时间对象
        LocalDateTime localDateTime = LocalDateTime.parse(startDateStr, DateTimeFormatter.ofPattern(pattern));

        // 日期时间对象-->指定格式的字符串
        String format = localDateTime.format(DateTimeFormatter.ofPattern(pattern)));
        // 2021-08-15 09:09:09
        System.out.println(format);
    }
}

LocalDateTime与Date互转

LocalDateTime 转 Date(亲测有效):

LocalDateTime localDateTime = LocalDateTime.now();
Date date = Date.from(localDateTime.atZone( ZoneId.systemDefault()).toInstant());

Date 转 LocalDateTime:

Date startDate=new Date();
LocalDateTime localDateTime = startDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime()

LocalDateTime与时间戳转换

13位的时间戳。

将timestamp转为LocalDateTime:

public LocalDateTime timestamToDatetime(long timestamp){
  Instant instant = Instant.ofEpochMilli(timestamp);
  return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
 }

将LocalDataTime转为timestamp:

public long datatimeToTimestamp(LocalDateTime ldt){
  long timestamp = ldt.toInstant(ZoneOffset.of("+8")).toEpochMilli();
  return timestamp;
 }

我在网上还找到了另一个将datetime转为时间戳的方法:

ZoneId zone = ZoneId.systemDefault();
long timestamp = ldt.atZone(zone).toInstant().toEpochMilli();

Java8的时间转为时间戳的大概的思路就是LocalDateTime先转为Instant,设置时区,然后转timestamp。

总结

略。

参考文章:

  • https://www.choupangxia.com/2019/10/14/java8%e6%96%b0%e7%89%b9%e6%80%a7%e6%97%b6%e9%97%b4%e6%97%a5%e6%9c%9f%e5%ba%93datetime-api%e5%8f%8a%e7%a4%ba%e4%be%8b/
  • https://www.jb51.net/article/206904.htm
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java8日期】一文搞定Java8日期新特性 的相关文章

  • 机器学习评估方法——P值校验

    目标 假设在 0 05的情况下 根据舆情监测项目需求 查看召回率和准确率的置信区间 均值 过程 1 输入数据 三列分别是precision recall f1 score 每一列分别计算 以此为例 一共四十行 即样本容量为40 2 计算标准
  • linux下登陆mysql失败

    一 提示由于没有密码 拒绝登陆 ERROR 1045 28000 Access denied for user root localhost using password NO 1 关闭mysql service mysqld stop2
  • mysql索引之B+树

    1 概述 提到B 树就不得不提及二叉树 平衡二叉树和B树这三种数据结构了 B 树就是从他们三个演化来的 众所周知B 树是一种常见的数据结构 被广泛应用于数据库和文件系统等领域 B 树的设计目标是保持树的平衡性 以提供稳定的性能 并且适用于大
  • 链表插入详解

    单链表速成 增与删 众所周知 链表是数据结构的重中之重 但有许多朋友对此并不感冒 甚至想骂 本文主要介绍小编对于链表的喜与悲 乐于忧 先上图 添加结点 单链表结点类型声明 typedef int ElemType 假设ElemType为自定
  • python捕获异常时,打印异常的类型、报错文件、与报错所在的行

    捕获异常 异常的完整代码是 try raise Exception wa except print 报错 else print 没有报错 finally print 程序关闭 得到结果 报错 程序关闭 一般程序里的 try与except是一
  • 如何优化一个肽预测模型

    要优化一个肽预测模型 首先需要考虑的是输入数据的质量 确保输入的数据是完整的 正确的 而不是噪声数据 此外 还需要考虑模型的训练方式 比如是否使用正则化和提前停止来确保不会过拟合训练数据 最后 应该尝试在模型中使用不同的参数来改善模型的性能
  • 02 Java基本数据结构之队列实现

    系列文章目录 01 Java基本数据结构之栈实现 02 Java基本数据结构之队列实现 03 Java基本数据结构之优先级队列 04 Java基本数据结构之链表 如有错误 还请指出 文章目录 系列文章目录 前言 一 队列 简述 二 栈 数组
  • 【Hyperledger Fabric】学习笔记1—— 区块链介绍

    目录 1 区块链介绍 1 1 区块链技术起源 1 1 1 区块链技术 1 1 2 区块链技术发展 1 2 区块链核心技术 1 2 1 定义 1 2 2 区块链技术原理 1 2 3 区块链工作过程 1 3 区块链开发平台 1 3 1 公有链平
  • GIT使用教程(十五步吃透,全网最详细)

    一 安装GIT 到官网下载GIT https git scm com downloads 二 创建仓库 在要创建仓库的文件夹空白地方点击右键 在弹出的菜单中点击 GIT Bash Here 然后初始化仓库 git init 成功后该文件夹中
  • MySQL配置和设置问题小结

    问题1 root Tony ts tian bin mysqladmin uroot password kaka123 mysqladmin connect to server at localhost failed ERROR 1045
  • [4G+5G专题-144]: 测试-频谱分析仪工作原理与测试结果分析

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 123222945 目录 前言 第1章

随机推荐

  • RSA/数字证书/签名原理详解

    文中首先解释了加密解密的一些基础知识和概念 然后通过一个加密通信过程的例子说明了加密算法的作用 以及数字证书的出现所起的作用 接着对数字证书做一个详细的解释 并讨论一下windows中数字证书的管理 最后演示使用makecert生成数字证书
  • 优惠卷测试案例

    提示 过期优惠卷 不同等级的用户 叠加使用 退款 支付失败 取消支付 退款中 订单信息 网络问题 退货 兼容性 优惠券是否可以正常使用 外观是否与UI保持一致 部分商品是否能正常使用 购买商品的时候会不会提示使用优惠券 优惠券是否能分享 分
  • git锁住如何解决GitLab: Your account has been blocked.

    今天用gitpush和pull的时候出现了一个问题 报了一个错误 GitLab Your account has been blocked 然后我怀疑是账号错误 然后发现账号密码对 后来发现是两个git账号同时占用了一个目录 强制删除目录下
  • 数据结构【堆】的认识及建立

    目录 一 堆 1 什么是堆 2 堆的存储方式 二 堆的建立与存储 三 堆的应用 1 堆排序 2 对顶堆 一 堆 1 什么是堆 堆 Heap 是一种特殊的完全二叉树结构 其中最大堆 Max Heap 或最小堆 Min Heap 的每个节点的键
  • Maven-Failed to parse POMs

    Maven Failed to parse POMs 错误描述信息 产生错误的原因 解决办法 依赖关系 错误描述信息 ERROR Failed to parse POMs hudson remoting ProxyException hud
  • mmdetection学习&训练测试自己的数据集

    一 本机使用环境 商汤科技和香港中文大学联合开源的深度学习目标检测工具箱mmdetection源码地址 Ubuntu16 04 Cuda9 0 cudnn7 5 Python3 6 GCC 7 2 Anaconda3 二 环境配置 官方配置
  • 无法连接 SQL Server 不可用或不存在 无法连接, SQL Server 不存在或拒绝网络访问..请问这是怎么回事?...

    远程连接sql server 2000服务器的解决方案 一 看ping 服务器IP能否ping通 这个实际上是看和远程sql server 2000服务器的物理连接是否存在 如果不行 请检查网络 查看配置 当然得确保远程sql server
  • CUDA 6.0在 VS 2010下的安装和配置

    CUDA 6 0在 VS 2010下的安装和配置 安装前准备 CUDA 6 0 安装包 下载地址 https developer nvidia com cuda downloads VS 2010 安装 这个直接下个免费的就行 Visual
  • 信息打点-公众号服务&Github监控&供应链&网盘泄漏&证书图标邮箱资产

    文章目录 微信公众号 获取 三方服务 Github监控 开发 配置 源码 网盘资源搜索 全局文件机密 敏感目录文件 目录扫描 爬虫 网络空间进阶 证书 图标 邮箱 实战案例四则 技术分享打击方位 微信公众号 获取 三方服务 1 获取微信公众
  • Linux C利用Socket套接字进行服务器与多个客户端进行通讯

    http blog csdn net returningprodigal article details 51916754 服务器端 html view plain copy print include
  • C++/Python机器学习—感知机(二分类)

    一 Python import numpy as np import matplotlib pyplot as plt 定义预测函数 def predict x w b 计算特征向量和权重向量的点积 dot product np dot x
  • chrome浏览器 docker_使用docker安装elasticsearch

    1 使用docker安装 拉取镜像docker pull elasticsearch 6 5 4 创建容器docker create name elasticsearch net host e discovery type single n
  • 通过这些case,我把项目LCP时间减少了1.5s

    您好 如果喜欢我的文章 可以关注我的公众号 量子前端 将不定期关注推送前端好文 前言 最近在做公司几个项目性能优化 整理出一些比较有用且常见的case来分享一下 A项目优化 白屏相关 DNS预连接 资源预解析 对于公共域名g alicdn
  • Python 大数据分析教程_1_大数据分析概述

    本章内容 理解数据 认识数据分析 数据分析工具Python 集成开发环境和文本编辑器 使用Jupter Notebook 理解数据 需要分析的数据一般是结构化的 半结构化的 非结构化的数据集合 大部分数据集都能够被转化为更加适合分析和建模的
  • openwrt路由器samba拒绝访问

    openwrt路由器samba拒绝访问 第一步 第一步 检查软件包 进入路由器web后台页面 系统 软件包 按ctrl f键查找samba软件包安装情况 例如 我的系统就有 autosamba luci app samba luci i18
  • Postfix+Cyrus-IMAP + Cyrus-SASL + MySQL + IMP 配置指南

    CNGNU Postfix邮件系统系列指南之一 Postfix Cyrus IMAP Cyrus SASL MySQL IMP完全指南 作者 王兴宇
  • iphonex苹果手机Exchange邮箱设置同步的邮件天数

    苹果手机Exchange邮件设置 同步的邮件天数 步骤 1 找到手机 设置 2 找到 账户与密码 3 找到 Exchage 4 找到 要同步的邮件天数 5 选择要保留的天数
  • leetcode shell 4道题

    最近在学习shell 发现leetcode上shell的4道题还是比较不错的 整理了一下 193 Valid Phone Numbers 电话号码匹配 easy grep 0 9 0 9 0 9 0 9 0 9 0 9 0 9 0 9 0
  • IOU

    IOU 即交并比 应用 NMS 过滤重叠框 mAP import numpt as np def get IOU pred bbox gt bbox ixmin max pred bbox 0 gt bbox 0 iymin max pre
  • 【Java8日期】一文搞定Java8日期新特性

    目录标题 前言 Java8日期类型 简介 1 核心类 2 关键点 LocalDate 1 获取当前日期 年 月 日 2 获取月 周的第几天 3 随意创建日期 4 比较两个LocalDate是否相同 5 比较两个LocalDate的大小 6