Java 8 新的时间处理API

一:时间日期API的演进,及存在的问题

JDK 1.0 时期:

  1. 对于日期和时间的支持只能依赖于java.util.Date类。它的最小精度是毫秒
  2. 起始年份为1900年,起始月份为0。20180822表示为new Date (118,7,22)
  3. 返回值使用JVM默认时区:CST。但是并不支持时区

JDK 1.1 时期:

  1. 废弃了java.util.Date的一些方法,转而用java.util.Calendar替代
  2. Calendar的起始月份依旧是0
  3. 格式化及解析时间使用DateFormat方法,非线程安全
  4. Date、Calendar类都是可变的

JDK 1.8 时期:
Java 8在java.time包中整合了很多Joda-Time的特性,使得API更加好用。API主要包含类:
LocalDate、LocalTime、Instant、Duration和Period

二:新的日期&时间API

LocalDate、LocalTime、Instant、Duration和Period

LocalDate:日期
该类的实例是一个不可变对象,它只提供简单的日期,不包含当天的时间,也不包含时区相关信息。可以使用静态工厂创建LocalDate实例。

LocalDate常见用法:

	LocalDate date = LocalDate.of(2019, 4, 10);System.out.println(date.getYear());//2019System.out.println(date.getMonthValue());//4System.out.println(date.getDayOfYear());//100System.out.println(date.getDayOfMonth());//10System.out.println(date.getDayOfWeek());//WEDNESDAYSystem.out.println(date.isLeapYear());//falseSystem.out.println(date.lengthOfMonth());//30System.out.println(date.lengthOfYear());//365System.out.println(LocalDate.now().atStartOfDay());//2019-04-10T00:00

LocalTime:时间

与LocalDate类似,LocalTime表示时间,同样可以使用of方法创建LocalTime实例。
另外,LocalDate、LocalTime都支持从字符串创建

//LocalDate、LocalTime都是final的
LocalDatelocalDate = LocalDate.parse("2019-04-10");
LocalTime localTime = LocalTime.parse("10:48:33");LocalTime localTime2 = LocalTime.of(10, 48, 33);
System.out.println(localTime2.getHour());//10
System.out.println(localTime2.getMinute());//48
System.out.println(localTime2.getSecond());//33
System.out.println(localTime2.getNano());//当前LocalTime的秒的纳秒数:0

LocalDateTime:日期和时间

		System.out.println(LocalDateTime.now());//2019-04-10T11:00:05.627System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.now()));//2019-04-10T11:00:05.628System.out.println(LocalDateTime.parse("2019-04-10T10:58:01"));//2019-04-10T10:58:01System.out.println(LocalDateTime.of(2019, 4, 10, 10, 58, 00, 19999));//2019-04-10T10:58:00.000019999//可以把LocalDateTime拆分为LocalDate和LocalTimeLocalDateTime l1 = LocalDateTime.now();System.out.println(l1.toLocalDate());//2019-04-10System.out.println(l1.toLocalTime());//11:02:34.827

Instant:机器的日期和时间
Instant设计初衷是便于机器使用,包含的是秒及纳秒所组成的数字。所以,一般编程不会用到此API。
java.time.Instant类对时间的建模方式是以Unix元年时间(UTC时区1970-01-01 00:00:00)开始进行计算

System.out.println(Instant.ofEpochMilli(763883333l));//1970-01-09T20:11:23.333Z//参数1:秒,参数2:纳秒,参数2对参数1进行调整System.out.println(Instant.ofEpochSecond(1, 8999999999999999999l));//2255-03-14T16:00:00.999999999Z

Duration、Period:时间段

由于LocalDateTime和Instant是为不同的目的而设计的,一个是为了人阅读的,一个是为了机器处理的,所以不能将二者混用。此外,由于Duration类主要用于以秒和纳秒衡量时间的长短,所以不能向between方法传递LocalDate

Duration和Period类都提供了很多非常方便的工厂类,直接创建对应的实例

//计算日期时间差使用这两个类
LocalDateTime l1 = LocalDateTime.parse("2019-04-01T15:10:10");
LocalDateTime l2 = LocalDateTime.now();//2019-04-10T11:40:10
System.out.println(Duration.between(l1, l2).toDays());//8
System.out.println(Period.between(l1.toLocalDate(), l2.toLocalDate()).getDays());//9Duration threeMinutes = Duration.ofMinutes(3);
Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES);Period tenDays = Period.ofDays(10);
Period threeWeeks  = Period.ofWeeks(3);
Period twoYearsSixMothsOneDay = Period.of(2,6,1);

操作、解析和格式化日期

LocalDate l1 = LocalDate.of(2019, 4, 10);
LocalDate l2 = l1.withYear(2020);
LocalDate l3 = l2.withMonth(5);
LocalDate l4 = l3.withDayOfMonth(20);
System.out.println(l1);//2019-04-10,with方法会创建对象的副本,原对象不变
System.out.println(l4);//2020-05-20

像LocalDate、LocalTime、LocalDateTime以及Instant这些表示日期和时间的类提供了大量的通用方法:
1、from 静态方法 依据传入的Temporal对象创建是实例

2、now 静态方法 依据系统时钟创建Temporal对象

3、of 静态方法 由Temporal对象的某个部分创建对象的实例

4、 parse 静态方法 由字符串创建Temporal对象的实例

5、atOffset 将Temporal对象和某个时区偏移相结合

6、atZone 将Temporal 对象和某个时区相结合

7、format 使用某个指定的格式将Temporal对象转换为字符串(Instant类不提供此方法)

8、get 读取Temporal对象的某一部分的值

9、minus 创建对象的一个副本,然后将当前的Temporal对象的值减去一定的时长创建该副本

10、plus 创建对象的一个副本,然后将当前Temporal对象的值加上一定的时长创建该副本

11、with 以该对象为模板,对某些状态进行修改创建该对象的副本。

TemporalAdjuster:精细化操作

操纵更复杂的日期,比如将日期调整到下个周日、下个工作日,或者是本月的最后一天。这时可以使用with的重载版本,向其传递一个提供了更多定制化选择的TemporalAdjuster对象,更加灵活的处理日期。

import static java.time.temporal.TemporalAdjusters.*;LocalDate dd = LocalDate.of(2018,8,23);LocalDate dd1 = dd.with(dayOfWeekInMonth(2,DayOfWeek.FRIDAY)); //同一个月中,第二个星期五 2018-08-10LocalDate dd2 = dd.with(firstDayOfMonth()); //当月的第一天 2018-08-01
LocalDate dd3 = dd.with(firstDayOfNextMonth()); //下月的第一天 2018-09-01
LocalDate dd4 = dd.with(firstDayOfNextYear()); //明年的第一天 2019-01-01
LocalDate dd5 = dd.with(firstDayOfYear()); //当年的第一天 2018-01-01
LocalDate dd6 = dd.with(firstInMonth(DayOfWeek.MONDAY)); //当月第一个星期一 2018-08-06LocalDate dd7 = dd.with(lastDayOfMonth()); //当月的最后一天 2018-08-31
LocalDate dd8 = dd.with(lastDayOfYear()); //当年的最后一天 2018-12-31
LocalDate dd9 = dd.with(lastInMonth(DayOfWeek.SUNDAY)); //当月最后一个星期日 2018-08-26LocalDate dd10 = dd.with(previous(DayOfWeek.MONDAY)); //将日期向前调整到第一个符合星期一 2018-08-20
LocalDate dd11 = dd.with(next(DayOfWeek.MONDAY)); //将日期向后调整到第一个符合星期一 2018-08-27LocalDate dd12 = dd.with(previousOrSame(DayOfWeek.FRIDAY)); //将日期向前调整第一个符合星期五,如果该日期已经符合,直接返回该对象 2018-08-17
LocalDate dd13 = dd.with(nextOrSame(DayOfWeek.FRIDAY)); //将日期向后调整第一个符合星期五,如果该日期已经符合,直接返回该对象 2018-08-24

打印输出及解析日期

处理日期和时间对象时,格式化以及解析日期-时间对象是另一个非常重要的功能。新的java.time.format包就是为了这个目的而设计的。这个包中最重要的类是DateTimeFormatter,创建格式器最简单的方式是通过他的静态工厂方法及常量。

String s1 = next.format(DateTimeFormatter.BASIC_ISO_DATE); //20180824
String s2 = next.format(DateTimeFormatter.ISO_LOCAL_DATE); //2018-08-24

除了解析为字符串外,还可以通过解析代表日期或时间的字符串重新创建该日期对象。

LocalDate date1 = LocalDate.parse("20180901",DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2018-09-02",DateTimeFormatter.ISO_LOCAL_DATE);

与老的java.util.DateFormat想比较,所有的DateTimeFormatter实例都是线程安全的。DateTimeFormatter类还支持一个静态工厂方法,它按照某个特定的模式创建格式器。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate now = LocalDate.now();
String formatterDate = now.format(formatter);
LocalDate nowparse = LocalDate.parse(formatterDate,formatter);

ofPattern可以按照指定的格式进行解析成字符串,然后又调用了parse方法的重载 将该格式的字符串转换成了 LocalDate对象。
ofPattern也提供了重载版本,使用它可以创建某个Locale的格式器:

DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MMMMd号", Locale.CHINA);
LocalDate chinaDate = LocalDate.parse("2018-08-21");
String formatterDate2 = chinaDate.format(formatter2); //2018年八月21号
LocalDate chinaDate2 = LocalDate.parse(formatterDate2,formatter2);

DateFormatterBuilder类还提供了更复杂的格式器和更强大的解析功能:

DateTimeFormatter chinaFormatter = new DateTimeFormatterBuilder().appendText(ChronoField.YEAR).appendLiteral("年").appendText(ChronoField.MONTH_OF_YEAR).appendText(ChronoField.DAY_OF_MONTH).appendLiteral("号").parseCaseInsensitive().toFormatter(Locale.CHINA);

处理不同的时区和历法
之前所看到的日期和时间种类都不包含时区信息。时区的处理是新版日期和时间API新增加的重要功能,新的 java.time.ZoneId 类是老版 java.util.TimeZone 的替代品。

时区是按照一定的规则将区域划分成的标准时间相同的区间。在ZoneRules这个类中包含了40个这样的实例。你可以使用ZoneId的getRules()得到指定时区的规则。每个特定的ZoneId对象都由一个地区标识:

ZoneId romeZone = ZoneId.of("Europe/Rome"); //格式 欧洲/罗马

地区ID都为 “{区域}/{城市}”的格式,这些地区集合的设定都由英特网编号分配机构(IANA)的时区数据库提供。你可以通过java 8的新方法toZoneId将一个老的时区对象转换为ZoneId

ZoneId zoneId = TimeZone.getDefault().toZoneId();

一旦得到一个ZoneId对象,就可以将它与LocalDate、LocalDateTIme或者是Instant对象整合起来,构造为一个ZonedDateTime实例,它代表了相对于指定时区的时间点,

LocalDate date = LocalDate.of(2018,8,22);
ZonedDateTime zdt1 = date.atStartOfDay(romeZone);LocalDateTime dateTime = LocalDateTime.of(2018,8,23,13,48,00);
ZonedDateTime zdt2 = dateTime.atZone(romeZone);Instant instant = Instant.now();
ZonedDateTime zdt3 = instant.atZone(romeZone);

ZonedDateTime = LocalDateTime(LocalDate + LocalTime) + ZoneId

通过ZoneId,你还可以将LocalDateTime转换为Instant

LocalDateTime dateTime = LocalDateTime.of(2018,8,23,13,48,00);
Instant instantFromDateTime = dateTime.toInstant(romeZone);Instant instant1 = Instant.now();
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(romeZone);

利用和 UTC/格林尼治时间的固定偏差计算时区

另一种比较常用的表达时区的方式就是利用当前时区和 UTC/格林尼治 的固定偏差,比如,纽约落后伦敦5小时。这种情况下,你可以使用ZoneOffset类,它是ZoneId的一个子类,表示的是当前时间和伦敦格林尼治子午时间的差异:

ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");

这种方式不推荐使用,因为 -05:00 的偏差实际上是对应的美国东部标准时间,并未考虑任何日光时的影响。

LocalDateTime dateTime1 = LocalDateTime.now();
OffsetDateTime dateTimeInNewYork1 = OffsetDateTime.of(dateTime1,newYorkOffset);

它使用ISO-8601的历法系统,以相对于UTC时间的偏差方式表示日期时间。

使用别的日历系统

ISO-8601日历系统是世界文明日历系统的事实标准。但是,java 8 中另外提供了4种其他的日历系统。这些日历系统中的每一个都有一个对应的日志类,分别是ThaiBuddhistDate、MinguoDate、JapaneseDate以及HijrahDate。所有这些类以及LocalDate都实现了ChronoLocalDate接口,能够对公历的日期进行建模。利用LocalDate对象,可以创建这些类的实例。

小结:

  1. Java 8之前的java.util.Date类以及其他用于建模日期时间的雷有很多不一致及设计上的缺陷,包括易变性以及糟糕的偏移值、默认值和命名
  2. 新版的日期和时间API中,日期-时间对象是不可变的
  3. 操纵的日期不会影响老值,而是新生成一个实例
  4. 新的API提供了两种不同的时间表示方式,有效地区分了运行时人和机器的不同需求
  5. TemporalAdjuster可以更精确的操纵日期,还可以自定义日期转换器
  6. 他们都是线程安全的

参考:
新API的用法:
https://www.cnblogs.com/baidawei/p/9519747.html
https://blog.csdn.net/zsx157326/article/details/80887673
https://blog.csdn.net/w592376568/article/details/80408742

旧API:
https://blog.csdn.net/quxing10086/article/details/80032713
https://www.cnblogs.com/CSU-PL/p/4430787.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core结合Nacos来完成配置管理和服务发现

前言今年4月份的时候,和平台组的同事一起调研了一下Nacos,也就在那个时候写了.net core版本的非官方版的SDK。虽然公司内部由于某些原因最后没有真正的用起来,但很多人还是挺看好的。在和镇汐大大沟通后,决定写一篇博客简单介绍一…

2020 ICPC 济南 F. Gcd Product

Gcd Product Cm∑i1mAgcd⁡(i,m)Bgcd⁡(k1−i,m)∑d1∣mAd1∑d2∣mBd2∑i1m([gcd⁡(id1,md1)1][d1∣i])([gcd⁡(m1−id2,md2)1][d2∣m1−i])∑d1∣mAd1∑d2∣mBd2∑k1∣md1μ(k1)∑k2∣md2μ(k2)∑i1m([d1∣i][k1∣id1])([d2∣m1−i][k2∣m1−id2])T1d1k1,T2d2k2∑T1∣m∑d1∣T…

Java 时间处理

时区、冬令时和夏令时、时间戳 时间戳 距离一个标准参照时间经过的秒数(毫秒数) 有两个常用参照时间: 1970-01-01 00:00:00 应用最广泛的时间戳参照点2001-01-01 00:00:00 常被苹果系统使用 注意:以上时间节点皆采用UTC的标准时…

试试这个Excel知识测验,得分超过80分算你赢

大家可能都知道,全世界使用Excel的用户超过了10亿。Excel的知识真所谓是博大精深,并且还很有趣味。我最近编写了一个Excel小工具,可以让大家可以在Excel里面进行各种知识小测验,并且与全世界的高手一比高低。这个小工具&#xff0…

SimpleDateFormat与线程安全

SimpleDateFormat不是线程安全的。 SimpleDateFormat(下面简称sdf)类内部有一个Calendar对象引用,它用来储存和这个sdf相关的日期信息,例如sdf.parse(dateStr),sdf.format(date) 诸如此类的方法参数传入的日期相关String, Date等等&#xff…

几道偏序问题(数据结构)

P3157 [CQOI2011]动态逆序对 #include <bits/stdc.h>using namespace std;typedef long long ll;const int N 1e5 10;int root[N], ls[N << 8], rs[N << 8], sum[N << 8], cnt;int n, m, pos[N];inline int lowbit(int x) {return x & (-x); }v…

自学架构设计?帮你总结了 4 个方法

从编程思维到架构思维的升级&#xff0c;是工作 3、5 年的程序员遇到的第一个槛&#xff0c;特别是当你准备晋升考核时。我有个哥们&#xff0c;技术和业务都很不错&#xff0c;腾讯 T2.3 升 T3.1&#xff0c;就卡在了架构设计这部分。架构这个事儿&#xff0c;不像算法和代码&…

如何在东八区的计算机上获取美国时间

既可以用旧API&#xff08;JDK8之前&#xff09;&#xff0c;也可以使用新API。以下用旧API为例&#xff1a; 在Java语言中&#xff0c;可以通过java.util.Calendar类取得一个本地时间或者指定时区的时间实例&#xff0c;如下&#xff1a; // 取得本地时间&#xff1a; Calen…

Wannafly挑战赛24 无限手套(生成函数)

无限手套 每种宝石的生成函数为∑n≥0xn(ain2bin1)对其进行化简∑n≥0xn∑n≥0binxn∑n≥0ain2xn11−xbix(1−x)2aix(1x)(1−x)3最后答案∏i1m((ai−bi1)x2(aibi−2)x1)(1−x)3m每种宝石的生成函数为\sum_{n \geq 0} x ^ n(a_i n ^ 2 b_i n 1)\\ 对其进行化简\sum_{n \geq 0}…

.NET Core 3.0及ASP.NET Core 3.0 前瞻

前几天微软发布了 .NET Core 3.0 Preview 9 &#xff0c;这是.NET Core 3.0 最后一个预览版。[翻译] .NET Core 3.0 Preview 9 发布.NET Core 3.0 正式发布将在.NET Conf 上发布&#xff0c;.NET Conf 时间是9月23日至25日。Visual Studio 2019 16.3预览版3和Visual Studio for…

有了Unicode为啥还需要UTF-8

有了Unicode为啥还需要UTF-8 要回答这个问题&#xff0c;需要吃透“编码”的概念&#xff0c;刚好看到大神阮一峰写的文章&#xff1a;字符编码笔记&#xff1a;ASCII&#xff0c;Unicode 和 UTF-8 抄录如下&#xff0c;便于查找&#xff1a; 一、ASCII 码 我们知道&#xf…

2019ICPC西安邀请赛 E. Tree(树剖 + 线段树)

Tree 给定一棵树&#xff0c;节点有点权&#xff0c;然后有三种操作&#xff1a; 一、修改1−>s1->s1−>s的路径上的点权与ttt进行按位或。 二、修改1−>s1->s1−>s的路径上的点权与ttt进行按位与。 三、查询1−>s1->s1−>s的路径上的点权异或和…

升职却不加薪,为什么我还觉得老板说的挺有道理

前几天晚上&#xff0c;DevOps交流群里&#xff0c;有人抛出这样一个观点&#xff1a;如果有人来找我加薪&#xff0c;我一定告诉他我要给他升职&#xff0c;因为升职是免费的&#xff0c;加薪可是真的要花钱。但是我也会许诺他&#xff0c;如果他能把那个团队搞好&#xff0c;…

GBK、GB2312、GB18030

GBK、GB2312都是编码方式&#xff0c;都是双字节字符集&#xff0c;GB18030编码是一二四字节变长编码 GB&#xff1a;国标&#xff0c;国家标准 BIG5&#xff1a; 支持繁体中文 GB2312&#xff1a; 支持简体中文&#xff08;GBK的子集&#xff09; 共收录 6763 个汉字 GBK&…

2019 ICPC 南京 F. Paper Grading(字典树dfs序上树套树)

Paper Grading 题意&#xff1a;给定nnn个字符串&#xff0c;有两种操作&#xff1a; 一、给定i,ji, ji,j&#xff0c;交换第iii个跟第jjj个字符串。 二、给定 str &#xff0c;k,l,rk, l, rk,l,r&#xff0c;问你在区间[l,r][l, r][l,r]中的字符&#xff0c;与 str 至少有k…

细节之中自有天地,整洁成就卓越代码

溪源 | 长沙.NET技术社区开篇我们总是很容易就能写出满足某个特定功能的代码&#xff0c;却很难写出优雅代码。又最欣赏那些优雅的代码&#xff0c;因为优雅代码更能体现一个开发者的积累。就像写一篇散文&#xff0c;有的就像初学者不得其门而入&#xff0c;遣词造句都非常困难…

#2693. jzptab

jzptab ∑i1n∑j1mlcm(i,j)∑i1n∑j1mijgcd⁡(i,j)∑d1nd∑i1nd∑j1mdij[gcd⁡(i,j)1]∑d1nd∑k1ndk2μ(k)∑i1nkdi∑j1mkdjTkd,f(n)∑i1ni∑T1nf(nT)f(mT)(T∑k∣Tμ(k)k)设g(n)n∑d∣nμ(d)d先令g(n)g(n)ng(1)1,g(p)μ(1)μ(p)p1−p,g(pk,k≥2)1−p同时是积性函数&#xff0c…

UTF8、UTF16、UTF32区别

UTF8、UTF16、UTF32都是unicode字符集的字符编码。 UTF意思是unicode转换格式&#xff08;Unicode transform format&#xff09;&#xff0c;出现UTF8、UTF16、UTF32是出于要在内存中存储字符的目的而对unicode字符编号进行编码。 UTF8、UTF16、UTF32区别&#xff1a;&#…

URL编解码、Big Endian和Little Endian

一、Endian的起源 在各种计算机体系结构中&#xff0c;对于字节、字等的存储机制有所不同&#xff0c;因而引发了计算机通信领域中一个很重要的问题&#xff0c;即通信双方交流的信息单元&#xff08;比特、字节、字、双字等等&#xff09;应该以什么样的顺序进行传送。如果不达…

一次业务网关用ASP.NET Core 2.1重构的小结

前言对于API网关&#xff0c;业界貌似对它进行下划分&#xff0c;有下面几个分类/场景。面向Web App面向Mobile App面向Partner OpenAPI面向Partner ExternalAPI其他。。。在18年8月份的时候&#xff0c;有幸用.NET Core 2.1重构了一个对外的业务网关项目&#xff0c;这个项目的…