相关链接
目录
- 1. 旧API问题
- 2. 新API概览⭐️
- 3. 新API实例 - 时间点类
- a. 日期向上转型
- a1.Instant -> LocalDateTime
- a2.Instant -> OffsetDateTime
- a3.Instant -> ZonedDateTime
- a4.LocalDate -> LocalDateTime
- a5.LocalDate + LocalTime -> LocalDateTime
- a6.LocalDate -> ZonedDateTime
- a7.LocalDate + LocalTime -> LocalDateTime
- a8.LocalDateTime -> OffsetDateTime
- a9.LocalDateTime -> ZonedDateTime
- a10.LocalDateTime -> ZonedDateTime(区域偏移)
- a11.LocalDate + LocalTime -> OffsetDateTime
- a12.LocalDate + LocalTime -> ZonedDateTime
- b.日期向下转型
- b1. LocalDateTime -> Instant
- b2. LocalDateTime -> LocalTime
- b3. LocalDateTime -> LocalDate
- b4. OffsetDateTime -> Instant
- b5. OffsetDateTime -> LocalTime
- b6. OffsetDateTime -> LocalDate
- b7. OffsetDateTime -> LocalDateTime
- b8. ZonedDateTime -> Instant
- b9. ZonedDateTime -> LocalTime
- b10. ZonedDateTime -> LocalDate
- b11. ZonedDateTime -> LocalDateTime
- b12. ZonedDateTime -> OffsetDateTime
- b13. get方法向下转型
- c. 实例化对象 from
- d. 获取当前时间 now
- e. 日期加法 plus(减法 minus )
- f. 日期判断 isAfter(isBefore)
- g. 日期调节器 with
- h. 日期查询 query
- i. 日期解析 format(日期 -> String)⭐️
- j. 日期解析 parse 方法(String -> 日期)
- 4. 新API实例 - 时间段类
- k. 实例化对象 of
- k1. Duration.of(数量,单位)
- k2. Duration.ofNanos(纳秒)
- k3. Duration.ofMillils(毫秒)
- k4. Duration.ofSeconds(秒)
- k5. Duration.ofSeconds(秒,纳秒)
- k6. Duration.ofMinutes(分钟)
- k7. Duration.ofHours(小时)
- k8. Duration.ofDays(天)
- k9. Period.of(年,月,日)
- k10. Period.ofDays(日)
- k11. Period.ofWeeks(周)
- k12. Period.ofMonths(月)
- k13. Period.ofYears(年)
- l. 时间间隔 between
- 5. 新API详解
- 6.旧API转换
- 7. 注意事项
1. 旧API问题
Java自带的 java.util.Date,自Java1.0开始使用
从Java1.1开始,Date类中的所有方法就已被弃用,标记为@Deprecated
原因: 1. 线程不安全的风险,在并发编程中可能会出现bug
2. 日期计算困难
3. API使用不规范
Java1.1推荐采用 java.util.Calendar 类处理日期和时间,但是这个类同样存在不少问题
a.计算困难
需求: 计算2021年1月1日到现在(2022年1月17日)相差几天
java.util.Calendar 的set方法,month:规定0代表1月,不符合常理
案例代码一 老版本API存在问题 a.计算困难
package com.groupies.jdk8.day04;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
/**
* @author GroupiesM
* @date 2022/01/17
* @introduction 老版本API存在问题 a.计算困难
* 需求:计算2021年1月1日到现在相差几天
*/
public class Demo1DateTimeCalculate {
public static void main(String[] args) {
//获取2022年1月1日 Date
Calendar c = Calendar.getInstance();
c.set(2022, 0, 1);
Date d1 = c.getTime();
long s1 = d1.getTime();
//获取2022年1月17日 Date
Date d2 = new Date();
long s2 = d2.getTime();
//计算相差天数 (毫秒->天)
long intervalDay1 = (s2 - s1) / 1000 / 60 / 60 / 24;
System.out.println("2022年1月1日距离现在已经过了" + intervalDay1 + "天");
//Java8新版本的API完成需求
long intervalDay2 = ChronoUnit.DAYS.between(LocalDate.of(2022, 1, 1), LocalDate.now());
System.out.println("2022年1月1日距离现在已经过了" + intervalDay2 + "天");
}
}
b.线程不安全
需求: 创建十个线程,将字符串 2022-01-01 01:01:01 转换为Date对象后打印到控制台上
案例代码二 老版本API存在问题 b.线程不安全
package com.groupies.jdk8.day04;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author GroupiesM
* @date 2022/01/17
* @introduction
*/
public class Demo2DateFormatUnSafe {
final static SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
//循环10次,创建10个线程对象并启动
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
Date date = SIMPLE_DATE_FORMAT.parse("2022-01-01 01:01:01");
System.out.println(date);
} catch (ParseException e) {e.printStackTrace();}
}).start();
}
}
}
执行结果:
Exception in thread "Thread-3" Exception in thread "Thread-7" Exception in thread "Thread-6" java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Long.parseLong(Long.java:601) at java.lang.Long.parseLong(Long.java:631) at java.text.DigitList.getLong(DigitList.java:195) at java.text.DecimalFormat.parse(DecimalFormat.java:2084) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) at java.text.DateFormat.parse(DateFormat.java:364) at com.groupies.jdk8.day04.Demo2DateFormatUnSafe.lambda$main$0(Demo2DateFormatUnSafe.java:20) at java.lang.Thread.run(Thread.java:748) Exception in thread "Thread-8" java.lang.NumberFormatException: empty String at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842) at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.lang.Double.parseDouble(Double.java:538) at java.text.DigitList.getDouble(DigitList.java:169) at java.text.DecimalFormat.parse(DecimalFormat.java:2089) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) at java.text.DateFormat.parse(DateFormat.java:364) at com.groupies.jdk8.day04.Demo2DateFormatUnSafe.lambda$main$0(Demo2DateFormatUnSafe.java:20) at java.lang.Thread.run(Thread.java:748) java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Long.parseLong(Long.java:601) at java.lang.Long.parseLong(Long.java:631) at java.text.DigitList.getLong(DigitList.java:195) at java.text.DecimalFormat.parse(DecimalFormat.java:2084) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) at java.text.DateFormat.parse(DateFormat.java:364) at com.groupies.jdk8.day04.Demo2DateFormatUnSafe.lambda$main$0(Demo2DateFormatUnSafe.java:20) at java.lang.Thread.run(Thread.java:748) java.lang.ArrayIndexOutOfBoundsException: -1 at java.text.DigitList.fitsIntoLong(DigitList.java:230) at java.text.DecimalFormat.parse(DecimalFormat.java:2082) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) at java.text.DateFormat.parse(DateFormat.java:364) at com.groupies.jdk8.day04.Demo2DateFormatUnSafe.lambda$main$0(Demo2DateFormatUnSafe.java:20) at java.lang.Thread.run(Thread.java:748) Sat Jan 01 01:01:01 CST 2022 Sat Jan 01 01:01:01 CST 2022 Sat Jan 01 01:01:01 CST 2022 Fri Jun 11 11:01:01 CST 2190 Sat Jan 01 01:01:01 CST 2022 Sat Jan 01 01:01:01 CST 2022
异常原因: 全局使用同一个calendar对象,如果没有线程同步措施,可能会造成线程安全问题
解决方案: 同步代码块,或升级为Java8新版本日期API
//循环10次,创建10个线程对象并启动
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
synchronized (SIMPLE_DATE_FORMAT){
Date date = SIMPLE_DATE_FORMAT.parse("2022-01-01 01:01:01");
System.out.println(date);
}
} catch (ParseException e) {e.printStackTrace();}
}).start();
}
}
c.API使用不规范
月份从0开始计算,这里的8表示是9月;即month比实际月份少1,而year和date和实际日期是相同的;
JavaSE8 引入的 java.time 包解决了这些问题。java.time 包基于Joda-Time库构件,是一种免费的开源解决方案,在Java8没有出现之前,公司中已经广泛使用Joda-Time来解决Java中的日期与时间问题,Joda-Time的设计团队也参与了 java.time 包的开发。
2. 新API概览⭐️
Date-Time API中的所有类均生成不可变实例,它们是线程安全的,并且这些类不提供公共构造函数,也就是说没办法通过new的方式直接创建,需要采用工厂方法加以实例化。(通过now方法根据当前日期或时间创建实例)
2.1 时间点类【按API功能类型分】
id | 类名 | 作用 |
---|---|---|
1 | Instant | 格林威治时间戳,表示0时区的当前系统时间,可以使用Instant类作为中间类完成 旧版本日期API -> 新版本日期API 的转换。 默认格式: 年-月-日T时:分:秒.纳秒Z 实例: 2022-01-17T09:59:21.814Z -------------------------------------------------------------------------------------- 通以下形式可以完成旧版本API的升级 Date date = new java.util.Date(); Instant instant = date.toInstant(); -------------------------------------------------------------------------------------- Z 表示zulu time,即祖鲁时间,又被称为 格林威治标准时间(GMT)、世界时(UT),是在英格兰格林威治零度经线的时间。 祖鲁时间比美国中部标准时间晚6个小时,比美国中部夏季时(Daylight-Savings Time)晚5个小时。 祖鲁时间在世界范围内是相同的,因此通讯网络的交换也是按照祖鲁时间为标准来协调的。 |
2 | Enum DayOfWeek | 一个不可变的日期时间对象,表示星期几。 默认格式: 英文大写 实例: MONDAY |
3 | MonthDay | 一个不可变的日期时间对象,表示月日 默认格式: –月-日 实例: --01-17 |
4 | Enum Month | 一个不可变的日期时间对象,表示月。 默认格式: 英文大写 实例: JANUARY |
5 | YearMonth | 一个不可变的日期时间对象,表示年月。 默认格式: 年-月 实例: 2022-01 |
6 | Year | 一个不可变的日期时间对象,表示年。 默认格式: 年 实例: 2022 |
7 | LocalTime | 一个不可变的日期时间对象,表示本地时间。 默认格式: 时:分:秒.纳秒 实例: 17:59:21.988 |
8 | LocalDate | 一个不可变的日期时间对象,表示本地日期。 默认格式: 年-月-日 实例: 2022-01-17 |
9 | LocalDateTime | 一个不可变的日期时间对象,表示本地日期时间。 还可以访问其他日期和时间字段,例如:DayOfWeek,Month等。 默认格式: 年-月-日T时:分:秒.纳秒 实例: 2022-01-17T17:59:21.988 ![]() -------------------------------------------------------------------------------------- LocalDateTime 表示 ISO-8601日历系统中不带时区的日期时间。 说明: ISO-8601日系统是现今世界上绝大部分国家/地区使用的,这就是我们国人所说的公历,有闰年的特性。 |
10 | OffsetDateTime | 一个不可变的日期时间对象,表示偏移的日期时间。 还可以访问其他日期和时间字段,例如:DayOfWeek,Month等。 默认格式: 年-月-日T时:分:秒.纳秒±偏移时间 实例: 2022-01-17T17:59:21.989+08:00 |
11 | ZonedDateTime | 一个不可变的日期时间对象,表示具有时区的日期时间,此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。 还可以访问其他日期和时间字段,例如:DayOfWeek,Month等 默认格式: 年-月-日T时:分:秒.纳秒±偏移时间[时区] 实例: 2022-01-17T17:59:21.989+08:00[Asia/Shanghai] ![]() |
2.2 时间段类【按API功能类型分】
id | 类名 | 作用 |
---|---|---|
12 | Duration | TemporalAmount 接口的实现类,表示秒或纳秒时间间隔,适合处理需要时间高精确性的场景(秒杀)。(常用 l. 时间间隔 between:作为Duration.between静态方法的参数。) |
13 | Period | TemporalAmount 接口的实现类,表示一段时间(年、月、日)。(常用 l. 时间间隔 between:作为Duration.between静态方法的参数。e.日期加减:作为plus,minus方法的参数,指定计算的最小单位) 实例: 获取距离今天1年2个月零3天以后的本地日期时间 LocalDateTime result = LocalDateTime.now().plus(Period.of(1, 2, 3)); -------------------------------------------------------------------------------------- TemporalUnit是个接口,一般直接使用该接口在Java8自带的实现类即可(Duration、Period) idea查看uml图方式=> IDEA使用常见问题记录 的2.1.3 uml图 ![]() |
14 | Enum ChronoUnit | TemporalAmount 接口的实现类,采用枚举类的方式表示一些 计算常用时间单位。(常用 e.日期加减:作为plus,minus方法的参数,指定计算的最小单位) 例如: 一纳秒(ChronoUnit.NANOS) 一微秒(ChronoUnit.MICROS) 一毫秒(ChronoUnit.MILLIS) 一秒(ChronoUnit.SECONDS) 一分钟(ChronoUnit.MINUTES) 一小时(ChronoUnit.HOURS) 半天(ChronoUnit.HALF_DAYS) 一天(ChronoUnit.DAYS) 一周(ChronoUnit.WEEKS) 一个月(ChronoUnit.MONTHS) 一年(ChronoUnit.YEARS) 十年(ChronoUnit.DECADES) 百年(一个世纪)(ChronoUnit.CENTURIES) 千年(ChronoUnit.MILLENNIA) 十亿年(一个纪元)(ChronoUnit.ERAS) 2.92277266×1011年(永恒)(ChronoUnit.FOREVER) 实例: 获取举例今天100年以后的本地日期时间 LocalDate DecadesFromNow = LocalDate.now().plus(1,ChronoUnit.DECADES); -------------------------------------------------------------------------------------- TemporalUnit是个接口,一般直接使用该接口在Java8自带的实现类即可(ChronoUnit) idea查看uml图方式=> IDEA使用常见问题记录 的2.1.3 uml图 ![]() |
2.3 时间其他类【按API功能类型分】
id | 类名 | 作用 |
---|---|---|
15 | ZoneOffset | 表示与格林威治/ UTC的时区偏移量,如+02:00。时区偏移是时区与格林威治/ UTC不同的时间段。 这通常是固定的几小时和几分钟。(常用 a.日期向上转型:构建OffsetDateTime对象时,指定偏移) 世界不同的地区有不同的时区偏移。 在ZoneId课程中会捕获偏移量随地点和年份变化的规则。 例如,巴黎在冬季比格林威治/ UTC提前了一个小时,夏天还有两个小时。 该ZoneId实例巴黎将两个参考ZoneOffset实例-一个+01:00冬季实例,以及+02:00夏季实例。 |
16 | ZoneId | 表示时区信息,通过 ZoneId.getAvailableZoneIds() 可以获取所有时区(常用 a.日期向上转型:构建ZonedDateTime对象时,指定时区) 按字典序: Africa/Abidjan Africa/Accra Africa/Addis_Ababa …【部分省略】… America/New_York America/Nipigon America/Nome America/Noronha America/North_Dakota/Beulah …【部分省略】… Asia/Shanghai Asia/Singapore Asia/Srednekolymsk Asia/Taipei Asia/Tashkent Asia/Tbilisi Asia/Tehran Asia/Tel_Aviv Asia/Thimbu Asia/Thimphu Asia/Tokyo Asia/Tomsk Asia/Ujung_Pandang Asia/Ulaanbaatar Asia/Ulan_Bator Asia/Urumqi …【部分省略】… WET Zulu |
17 | Enum TextStyle | 采用枚举类的方式表示 文本格式和解析的风格。(常用 k. 枚举类 DayOfWeek:作为DayOfWeek.getDisplayName方法的参数,指定星期几的文本格式-长短) 三种尺寸: (文本格式) “满”(TextStyle.FULL) “短”(TextStyle.SHORT) “窄”(TextStyle.NARROW) 两种变体:(每种尺寸都有两种变体) “标准”(TextStyle.FULL) “独立”(TextStyle.FULL_STANDALONE) 在大多数语言中,三种尺寸之间的差异是显而易见的。 例如,在英语中,“满月”为“一月”,“短”月为“一月”,“窄”月为“J”。 请注意,狭窄的大小通常不是唯一的。 例如,‘1月’,‘6月’和’7’都有’窄’文本’J’。 “标准”和“独立”形式之间的区别是形容词难度很大,英文没有差别。 然而,在其他语言中,单独使用文本时使用的单词有所不同,而不是完整的日期。 例如,一个月在单独使用日期选择器中使用的单词与用于与日期中的日期和年份相关联的月份的单词不同。 |
18 | Locale | Locale对象代表具体的地理,政治或文化地区。(常用 k. 枚举类 DayOfWeek:作为DayOfWeek.getDisplayName方法的参数,指定星期几的文本格式-地区) 例如: 中国地区(Locale.CHINESE) |
19 | TemporalAdjusters 调节器 | 类中所有方法都会返回一个 TemporalAdjuster 对象。 表示一些 常用时间节点,供时间计算(g1. with + 调节器)。 例如: 上一个星期几(TemporalAdjusters.previous(DayOfWeek dayOfWeek)) 上一个星期几或当天(TemporalAdjusters.previousOrSame(DayOfWeek dayOfWeek)) 下一个星期几(TemporalAdjusters.next(DayOfWeek dayOfWeek)) 下一个星期几或当天(TemporalAdjusters.nextOrSame(DayOfWeek dayOfWeek)) 当月第1天(TemporalAdjusters.firstDayOfMonth()) 当月最后1天(TemporalAdjusters.lastDayOfMonth()()) 当月第1个星期几(TemporalAdjusters.firstInMonth(DayOfWeek dayOfWeek)) 当月第n个星期几(TemporalAdjusters.dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)) 当月最后一个星期几(TemporalAdjusters.lastInMonth(DayOfWeek dayOfWeek)) 当年最后1天(TemporalAdjusters.lastDayOfYear()) 明年的第1天(TemporalAdjusters.firstDayOfNextYear()) 下月第1天(TemporalAdjusters.firstDayOfNextMonth()) lambda表达式自定义指定日期(TemporalAdjusters. ofDateAdjuster(UnaryOperator<LocalDate> dateBasedAdjuster)) 实例: 获取举例今天100年以后的日期 LocalDate DecadesFromNow = LocalDate.now().plus(1,ChronoUnit.DECADES); -------------------------------------------------------------------------------------- Class TemporalAdjusters 并不是 interface TemporalAdjuster 的实现类,只不过 Class TemporalAdjusters 的静态方法实现了 interface TemporalAdjuster,并返回 interface TemporalAdjuster 对象的实例 |
20 | Interface TemporalQuery | 这是一个功能界面,因此可以用作lambda表达式或方法引用的赋值对象。 -------------------------------------------------------------------------------------- 在 c. 实例化对象 from 有使用的案例 |
21 | DateTimeFormatter | 日期格式化器,用于打印和解析日期时间对象。(常用 i. 日期解析 format(日期->String):作为*.with的参数,按照一些特殊规则计算时间) 常用方法: DateTimeFormatter.ofLocalizedDate 静态方法,自动识别时区的方式解析,需要传入一个FormatStyle的枚举值 DateTimeFormatter.ofPattern 静态方法,指定日期格式的解析,需要传入一个字符串日期格式 实例: String format1 = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE); String format2 = LocalDateTime.now().format(DateTimeFormatter.ofPattern(“yyyy-MM-dd’T’HH:mm:ss.SSS”)); -------------------------------------------------------------------------------------- DateTimeFormatter预制的格式化器,最常用的两个: 1. yyyy-MM-dd DateTimeFormatter.ISO_DATE => 2022-01-18 2. yyyy-MM-dd’T’HH:mm:ss.SSS DateTimeFormatter.ISO_DATE_TIME =>2022-01-18T18:12:51.639 -------------------------------------------------------------------------------------- 带不带 LOCAL 的对比: 仅对 OffsetDateTime、ZonedDateTime 有区别 1. LocalDateTime + ISO_DATE_TIME LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); => 2022-01-18T18:12:51.639 2. LocalDateTime + ISO_LOCAL_DATE_TIME LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); => 2022-01-18T18:12:51.639 3. OffsetDateTime + ISO_DATE_TIME OffsetDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); => 2022-01-18T18:12:51.639+08:00 4. OffsetDateTime + ISO_LOCAL_DATE_TIME OffsetDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); => 2022-01-18T11:12:51.639 5. ZonedDateTime + ISO_DATE_TIME ZonedDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); => 2022-01-18T18:12:51.639+08:00[Asia/Shanghai] 6. ZonedDateTime + ISO_LOCAL_DATE_TIME ZonedDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); => 2022-01-18T18:12:51.639 |
22 | Enum FormatStyle | 枚举本地化日期,时间或日期时间格式化的风格。(常用 i. 日期解析 format(日期->String):作为 DateTimeFormatter.ofLocalizedDate(FormatStyle dateStyle) 静态方法的参数使用,并返回一个 DateTimeFormatter 对象) 例如: 全文格式(FormatStyle.FULL)=> 2022年1月18日 星期二 长文本格式(FormatStyle.LONG)=> 2022年1月18日 中等格式(FormatStyle.MEDIUM)=> 2022-1-18 短文格式(FormatStyle.SHORT)=> 22-1-18 实例: 全文格式解析本地日期时间 String format = LocalDateTime.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)); -------------------------------------------------------------------------------------- 需要注意 这种方式在不同时区的显示内容不一样,在其他时区不会显示中文 |
23 | Interface TemporalField 时间结界 | 日期时间的字段,如月份或小时。日期和时间使用将时间线划分成对人有意义的东西的字段来表示。 此接口的实现表示这些字段。最常用的单位在 ChronoField 中定义。(常用 i. g2. with + ChronoField) 血缘关系: ![]() |
24 | Enum ChronoField 时间结界 | “先(按不同规则)获取一个新的时间,再这个时间的基础上再调整时间”。 表示一些 常用时间计算方式,供时间计算(g2. with + 时间结界)、时间获取(b13. get方法向下转型)。 例如:纳秒(在秒中)(ChronoField.NANO_OF_SECOND)取值范围[0, 999999999] 纳秒(在天中)(ChronoField.NANO_OF_DAY)取值范围[0, 86399999999999],需要使用getLong方法 微秒(在秒中)(ChronoField.MICRO_OF_SECOND)取值范围[0, 999999] 微秒(在天中)(ChronoField.MICRO_OF_DAY)取值范围[0, 86399999999],需要使用getLong方法 毫秒(在秒中) (ChronoField.MILLI_OF_SECOND)取值范围[0, 999] 毫秒(在天中) (ChronoField.MILLI_OF_DAY)取值范围[0, 86399999] 秒(在分中)(ChronoField.SECOND_OF_MINUTE)取值范围[0, 59] 秒(在天中)(ChronoField.SECOND_OF_DAY)取值范围[0, 86399] 秒(从UTC/格林威治的偏移秒数)(ChronoField.OFFSET_SECONDS)取值范围[-64800, 64800] 注意:对象必须是包含时区信息的(OffsetDateTime、ZonedDateTime) 举例:long offsetSecond = ZonedDateTime.of(ldt, ZoneId.of(“Asia/Shanghai”)).getLong(ChronoField.OFFSET_SECONDS); => 获取中国时区偏移秒数"29143"≈ 8.059小时,即东八区 秒(Unix 时间戳1)(ChronoField.INSTANT_SECONDS)取值范围[ Long.MIN_VALUE, Long.MAX_VALUE ],需要使用getLong方法,其中: LONG.MIN_VALUE = 0x8000000000000000L = - 264 LONG.MAX_VALUE = 0x7fffffffffffffffL = 264 - 1 注意:对象必须是包含时区信息的(OffsetDateTime、ZonedDateTime) 分钟(在天中)(ChronoField.MINUTE_OF_DAY)取值范围[0, 1439] 分钟(在小时中)(ChronoField.MINUTE_OF_HOUR)取值范围[0, 59] 12小时制(用0代表当天0:00AM或0:00PM)(ChronoField.HOUR_OF_AMPM)取值范围[0, 11] 12小时制(用12代表当天0:00AM或0:00PM)(ChronoField.CLOCK_HOUR_OF_AMPM)取值范围[1, 12] 2022-02-01T01:00.with(ChronoField.CLOCK_HOUR_OF_AMPM, 5) => 2022-02-01T05:00(当天AM5:00,因为01:00属于上午) 2022-02-01T14:00.with(ChronoField.CLOCK_HOUR_OF_AMPM, 5) => 2022-02-01T17:00(当天PM5:00,因为14:00属于下午) 24小时制(用0代表当天0点) (ChronoField.HOUR_OF_DAY)取值范围[0, 23] 24小时制(用24代表当天0点)(ChronoField.CLOCK_HOUR_OF_DAY)取值范围[1, 24] 半天(AM=0,PM=1)(ChronoField.AMPM_OF_DAY)取值范围[0,1] 日(在周中)(ChronoField.DAY_OF_WEEK)取值范围[1,7] 日(在月中)(ChronoField.DAY_OF_MONTH)取值范围[1,x],其中x∈[28,31] ,取决于当月有几天 日(在年中)(ChronoField.DAY_OF_YEAR)取值范围[1,x],其中x∈[365,366] ,取决于当年有几天 日(自纪元时间2起)(ChronoField.EPOCH_DAY)取值范围[(Year.MIN_VALUE * 365.25), (Year.MAX_VALUE * 365.25)],需要使用getLong方法,其中: Year.MIN_VALUE = -999999999; => 最小值 Year.MIN_VALUE * 365.25 = -365249999634 Year.MAX_VALUE = 999999999; => 最大值 Year.MAX_VALUE * 365.25 = 365249999634 周几(月对齐3)(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH)取值范围[1, 7] 周几(年对齐4)(ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR)取值范围[1, 7] 第几周(月对齐)(ChronoField.ALIGNED_WEEK_OF_MONTH)取值范围[1, 5],其中x∈[4,5] ,取决于当月有几周(实际测试平年2月x=5也可以) 第几周(年对齐)(ChronoField.ALIGNED_WEEK_OF_YEAR)取值范围[1, 53] 月(在年中)(ChronoField.MONTH_OF_YEAR)取值范围[1, 12] 月(自公元5“0000年1月"起)(ChronoField.PROLEPTIC_MONTH)取值范围[Year.MIN_VALUE * 12L, Year.MAX_VALUE * 12L + 11],需要使用getLong方法,其中: Year.MIN_VALUE = -999999999; => 最小值 Year.MIN_VALUE * 12L = 11999999988 Year.MAX_VALUE = 999999999; => 最大值 Year.MAX_VALUE * 12L + 11 = 11999999999 年(ChronoField.YEAR)取值范围[ Year.MIN_VALUE, Year.MAX_VALUE],需要使用getLong方法,其中: Year.MIN_VALUE = -999999999; => 最小值 Year.MAX_VALUE = 999999999; => 最大值 年(自公元1年起)(ChronoField.YEAR_OF_ERA)取值范围需要分类讨论,需要使用getLong方法,其中: ① 0001-01-01T00:00之前的时间(包含此刻), 属于公元前,取值范围[ 1, Year.MAX_VALUE + 1 ] => [ 1, 1000000000 ] ② 0001-01-01T00:00之后的时间(不包含此刻),属于公元前,取值范围[ 1, Year.MAX_VALUE ] => [ 1, 999999999 ] 其原因是:公元后开始于1年1月1日0点,所以 年份∈ [ -999999999 ,0 ] 时,是公元前。年份∈ [ 1, 999999999 ] 时,是公元后。就时间范围来说,公元前比公元后要多1年。 时代(公元前=0,公元后=1)(ChronoField.ERA)取值范围[0, 1],举例(伪代码): 2022-02-01T00:00.with(ChronoField.EPOCH_DAY, 0) => -2022-02-01T00:00(变为负值) 2022-02-01T00:00.with(ChronoField.EPOCH_DAY, 1) => 2022-02-01T00:00(不变) 举例(伪代码): 2022-01-01T02:03:04 在这一天内过了几分钟? “2022-01-01T02:03:04”.get(ChronoField.MINUTE_OF_DAY); => 123 -------------------------------------------------------------------------------------- 19.TemporalAdjusters 调节器 和 24.ChronoField 时间结界 都可以作为with参数修改时间(当然这2个的中文名字都是我自己编的,网上资料实在太少),区别在于: TemporalAdjusters 的修改日期是 基于当前时间 的,规则较为简单(例如上个星期一、当月第1个星期五、明年第5天等)。 ChronoField 的修改时间是 基于一个新的时间 ,规则较为复杂的(例如 ChronoField.SECOND_OF_DAY :先根据当前时间获取所在天,舍弃小时、分的信息,再基于这个时间设置一个新的秒数) => 秒(在天中)(ChronoField.SECOND_OF_DAY)取值范围[0, 86399],下面是一行伪代码,便于理解什么是"基于一个新的时间” => 2022-01-01T02:03:04.000056789.with(ChronoField.SECOND_OF_DAY, 8) => 2022-01-01T00:00:08.000056789 2022-01-01T02:03:04.000056789 => 先获取所在天的信息 => 2022-01-01T00:00:00.000056789 (小于秒的信息还保留着) 2022-01-01T00:00:00.000056789 => 对其赋值 SECOND=8 => 2022-01-01T00:00:08.000056789 |
14. ZoneOffset 的使用案例
//获取当前时区偏移+5小时时间
ZonedDateTime zdt = ZonedDateTime.ofInstant(LocalDateTime.now(),
ZoneOffset.of("+05:00"),
ZoneId.systemDefault());
15. ZoneId 的使用案例
//获取所有的时区信息
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
//availableZoneIds.forEach(System.out::println);//...
//获取当前系统默认的时区信息 -> 中国
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);//Asia/Shanghai
17. TextStyle & 18. Locale 的使用案例
String monday = DayOfWeek.of(1).getDisplayName(TextStyle.FULL, Locale.CHINESE);
System.out.println(monday);//星期一
19. TemporalAdjusters 的使用案例
更多详情查看 g1. with + 调节器 。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
//可以作为 -> with 方法的参数调节日期,例如:获取"下个星期五"的日期
TemporalAdjuster previous = TemporalAdjusters.next(DayOfWeek.of(5));
LocalDateTime nextFriday = ldt.with(previous);
//2022-01-01T00:00是星期六,他的下一个周五日期是2022-01-07T00:00
System.out.println(ldt + "是" + ldt.getDayOfWeek().
getDisplayName(TextStyle.FULL, Locale.CHINESE) +
",他的下一个周五日期是" + nextFriday);
}
20. TemporalQuery 的使用案例
更多详情查看 h. 日期查询 query 。
public static void main(String[] args) {
//创建日期对象2022年5月31日,模拟计算
LocalDate today = LocalDate.of(2022, 5, 31);
HashMap<String, Long> queryResult = today.query(new TemporalQuery<HashMap<String, Long>>() {
@Override
public HashMap<String, Long> queryFrom(TemporalAccessor temporalAccessor) {
//1.将 temporalAccessor 转为LocalDate对象
LocalDate ld = LocalDate.from(temporalAccessor);
//2.创建容器
HashMap<String, LocalDate> ldMap = new HashMap<>();
HashMap<String, Long> resultMap = new HashMap<>();
//3.封装当年的圣诞节/儿童节/劳动节的时间对象
ldMap.put("圣诞节", LocalDate.of(ld.getYear(), Month.DECEMBER, 2));
ldMap.put("儿童节", LocalDate.of(ld.getYear(), Month.JUNE, 1));
ldMap.put("劳动节", LocalDate.of(ld.getYear(), Month.MAY, 1));
//4.判断date是否已经超过了d1/d2/d3三个节日,如果超过了,则计算下一年的日期
for (String key : ldMap.keySet()) {
LocalDate holidayDate = ldMap.get(key);
//如果当前时间>当年节日,则节日日期+1年
if (ld.isAfter(holidayDate)) holidayDate = holidayDate.plusYears(1);
//计算:距离该节日还差几天
resultMap.put(key, ChronoUnit.DAYS.between(ld, holidayDate));
}
//5.返回结果
return resultMap;
}
});
//打印结果
for (String holidayName : queryResult.keySet()) {
//距离下一个儿童节还剩1天
//距离下一个劳动节还剩335天
//距离下一个圣诞节还剩185天
System.out.println("距离下一个" + holidayName + "还剩" + queryResult.get(holidayName) + "天");
}
}
21. DateTimeFormatter 的使用案例
更多详情查看 i. 日期解析 format 。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
String format1 = ldt.format(DateTimeFormatter.ISO_DATE);
String format2 = ldt.format(DateTimeFormatter.ISO_DATE_TIME);
System.out.println(format1);//2022-01-18
System.out.println(format2);//2022-01-18T18:12:51.639
}
22. FormatStyle 的使用案例
更多详情查看 i2. 自动识别时区 。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
String fullTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL));
String longTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));
String mediumTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
String shortTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));
System.out.println(fullTime);//2022年1月18日 星期二
System.out.println(longTime);//2022年1月18日
System.out.println(mediumTime);//2022-1-18
System.out.println(shortTime);//22-1-18
}
23. TemporalField 的使用案例
一般使用其实现类 24. ChronoField 。
24. ChronoField 的使用案例
更多详情查看 5. 新API详解,id=24 ChronoField 时间结界 。
3. 新API实例 - 时间点类
a. 日期向上转型
a1.Instant -> LocalDateTime
为 Instant(格林威治时间戳) 添加 ZoneId(时区信息)即可得到 LocalDateTime (本地日期时间)。
LocalDateTime.ofInstant(Instant instant, ZoneId zone) 静态方法
public static void main(String[] args) {
//LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneId.of("Asia/Shanghai"));
LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
System.out.println(ldt);//2022-01-18T18:12:51.639
}
a2.Instant -> OffsetDateTime
为 Instant(格林威治时间戳) 添加 ZoneId(时区信息)即可得到 OffsetDateTime (偏移的日期时间)。
OffsetDateTime.ofInstant(Instant instant, ZoneId zone) 静态方法
Instant.atOffset(ZoneOffset offset) 方法
public static void main(String[] args) {
Instant now = Instant.now();
//OffsetDateTime.ofInstant 静态方法
OffsetDateTime odt1 = OffsetDateTime.ofInstant(now, ZoneId.systemDefault());
System.out.println(odt1);//2022-01-18T18:12:51.639+08:00
//Instant.atOffset 方法
OffsetDateTime odt2 = now.atOffset(ZoneOffset.of("+01:00"));
System.out.println(odt2);//2022-01-18T11:12:51.639+00:00
OffsetDateTime odt3 = now.atOffset(ZoneOffset.of("+00:00"));
System.out.println(odt3);//2022-01-18T10:12:51Z
}
a3.Instant -> ZonedDateTime
为 Instant(格林威治时间戳) 添加 ZoneId(时区信息)即可得到 ZonedDateTime (具有时区的日期时间)。
ZonedDateTime.ofInstant(Instant instant, ZoneId zone) 静态方法
Instant.atZone(ZoneId zone) 方法
public static void main(String[] args) {
Instant now = Instant.now();
ZonedDateTime zdt1 = ZonedDateTime.ofInstant(now, ZoneId.systemDefault());
System.out.println(zdt1);//2022-01-18T12:51.639+08:00[Asia/Shanghai]
ZonedDateTime zdt2 = now.atZone(ZoneId.systemDefault());
System.out.println(zdt2);//2022-01-18T12:51.639+08:00[Asia/Shanghai]
}
a4.LocalDate -> LocalDateTime
为 LocalDate(本地日期)指定默认时间 LocalTime.MIDNIGHT(本地时间的00:00)即可得到 LocalDateTime (本地日期时间)。
LocalDate.atStartOfDay() 方法 会丢失小时级时间精度
public static void main(String[] args) {
LocalDate ld = LocalDate.now();
LocalDateTime ldt = ld.atStartOfDay();
System.out.println(ldt);//2022-01-18T00:00
}
a5.LocalDate + LocalTime -> LocalDateTime
为 LocalDate(本地日期)添加 LocalTime(本地时间)即可得到 LocalDateTime (本地日期时间)。
LocalDateTime.of(LocalDate date, LocalTime time) 静态方法
LocalTime.atDate(LocalDate date) 方法
LocalDate.atTime(LocalTime time) 方法
public static void main(String[] args) {
LocalDate ld = LocalDate.now();
LocalTime lt = LocalTime.now();
//LocalDateTime.of(LocalDate date, LocalTime time) 静态方法
LocalDateTime ldt1 = LocalDateTime.of(ld, lt);
System.out.println(ldt1);//2022-01-18T16:37
//LocalTime.atDate(LocalDate date) 方法
LocalDateTime ldt2 = lt.atDate(ld);
System.out.println(ldt2);//2022-01-18T16:37
//LocalDate.atTime(LocalTime time) 方法
LocalDateTime ldt3 = ld.atTime(lt);
System.out.println(ldt3);//2022-01-18T16:37
}
a6.LocalDate -> ZonedDateTime
为 LocalDate(本地日期)添加 ZoneId(时区信息)即可得到 ZonedDateTime (具有时区的时间日期)。
LocalDate.atStartOfDay(ZoneId zone) 静态方法 会丢失小时级时间精度
public static void main(String[] args) {
LocalDate ld = LocalDate.now();
ZonedDateTime zdt = ld.atStartOfDay(ZoneId.systemDefault());
System.out.println(zdt);//2022-01-18T00:00+08:00[Asia/Shanghai]
}
a7.LocalDate + LocalTime -> LocalDateTime
为 LocalDate(本地日期)添加 LocalTime(本地时间)即可得到 LocalDateTime (本地日期时间)。
LocalDateTime.of(LocalDate date, LocalTime time) 静态方法
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(LocalDate.now(), LocalTime.now());
System.out.println(ldt);//2022-01-18T16:37
}
a8.LocalDateTime -> OffsetDateTime
为 LocalDateTime(本地日期时间) 添加 ZoneOffset(时区偏移量)即可得到 OffsetDateTime (偏移的日期时间)。
OffsetDateTime.of(LocalDateTime dateTime, ZoneOffset offset) 静态方法
LocalDateTime.atOffset(ZoneOffset offset) 方法
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
//OffsetDateTime.of 静态方法
OffsetDateTime odt1 = OffsetDateTime.of(now, ZoneOffset.of("+08:00"));
System.out.println(odt1);//2022-01-18T18:12:51.639+08:00
//LocalDateTime.atOffset 方法
OffsetDateTime odt2 = now.atOffset(ZoneOffset.of("+08:00"));
System.out.println(odt2);//2022-01-18T18:12:51.639+08:00
}
a9.LocalDateTime -> ZonedDateTime
为 LocalDateTime(本地日期时间) 添加 ZoneId(时区信息)即可得到 ZonedDateTime (具有时区的日期时间)。
ZonedDateTime.of(LocalDateTime localDateTime, ZoneId zone) 静态方法
LocalDateTime.atZone(ZoneId zone) 方法
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
//ZonedDateTime.of 静态方法
ZonedDateTime zdt1 = ZonedDateTime.of(now, ZoneId.systemDefault());
System.out.println(zdt1);//2022-01-18T18:12:51.639+08:00[Asia/Shanghai]
//LocalDateTime.atZone 方法
ZonedDateTime zdt2 = now.atZone(ZoneId.systemDefault());
System.out.println(zdt2);//2022-01-18T18:12:51.639+08:00[Asia/Shanghai]
}
a10.LocalDateTime -> ZonedDateTime(区域偏移)
为 LocalDateTime(本地日期时间)添加 ZoneId(时区信息)和 ZoneOffset(区域偏移)即可得到 ZonedDateTime (具有时区的日期时间)。共有三种方法实现,三种方法的具体区别不详
ZonedDateTime.ofInstant(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone) 静态方法
ZonedDateTime.ofStrict(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone) 静态方法
ZonedDateTime.ofLocal(LocalDateTime localDateTime, ZoneId zone, ZoneOffset preferredOffset) 静态方法
//实例
public static void main(String[] args) {
ZonedDateTime zdt1 = ZonedDateTime.ofInstant(LocalDateTime.of(2022,1,18,18,12,51),
ZoneOffset.of("+06:00"),
ZoneId.systemDefault());
System.out.println(zdt1);//2022-01-18T20:12:51+08:00[Asia/Shanghai]
ZonedDateTime zdt2 = ZonedDateTime.ofInstant(LocalDateTime.of(2022,1,18,18,12,51),
ZoneOffset.of("+06:00"),
ZoneId.systemDefault());
System.out.println(zdt2);//2022-01-18T20:12:51+08:00[Asia/Shanghai]
ZonedDateTime zdt3 = ZonedDateTime.ofLocal(LocalDateTime.of(2022,1,18,18,12,51),
ZoneId.systemDefault(),
ZoneOffset.of("+06:00"));
System.out.println(zdt3);//2022-01-18T18:12:51+08:00[Asia/Shanghai]
}
a11.LocalDate + LocalTime -> OffsetDateTime
a7(LocalDate + LocalTime -> LocalDateTime) 和 a8 (LocalDateTime -> OffsetDateTime)方法的变体。
OffsetDateTime.of(LocalDate date, LocalTime time, ZoneId zone) 静态方法
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.systemDefault());
System.out.println(zdt);//2022-01-18T18:12:51.639+08:00[Asia/Shanghai]
}
a12.LocalDate + LocalTime -> ZonedDateTime
a7(LocalDate + LocalTime -> LocalDateTime) 和 a9 (LocalDateTime -> ZonedDateTime)方法的变体。
ZonedDateTime.of(LocalDate date, LocalTime time, ZoneId zone) 静态方法
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.systemDefault());
System.out.println(zdt);//2022-01-18T18:12:51.639+08:00[Asia/Shanghai]
}
b.日期向下转型
b1. LocalDateTime -> Instant
LocalDateTime (本地日期时间)通过 LocalDateTime.toInstant()方法 获取 Instant(格林威治时间戳)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
Instant instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println(instant);//2022-01-18T18:12:51.639Z
}
b2. LocalDateTime -> LocalTime
LocalDateTime (本地日期时间)通过 LocalDateTime.toLocalTime()方法 获取 LocalTime(本地时间)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
LocalTime lt = ldt.toLocalTime();
System.out.println(lt);//18:12:51.639
}
b3. LocalDateTime -> LocalDate
LocalDateTime (本地日期时间)通过 LocalDateTime.toLocalDate()方法 获取 LocalDate(本地日期)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
LocalDate ld = ldt.toLocalDate();
System.out.println(ld);//2022-01-18
}
b4. OffsetDateTime -> Instant
OffsetDateTime (偏移的日期时间)通过 OffsetDateTime.toInstant()方法 获取 Instant(格林威治时间戳)
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.now();
Instant instant = odt.toInstant();
System.out.println(instant);//2022-01-18T10:12:51Z
}
b5. OffsetDateTime -> LocalTime
OffsetDateTime (偏移的日期时间)通过 OffsetDateTime.toLocalTime()方法 获取 LocalTime(本地时间)
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.now();
LocalTime lt = odt.toLocalTime();
System.out.println(lt);//18:12:51.639
}
b6. OffsetDateTime -> LocalDate
OffsetDateTime (偏移的日期时间)通过 OffsetDateTime.toLocalDate()方法 获取 LocalDate(本地日期)
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.now();
LocalDate ld = odt.toLocalDate();
System.out.println(ld);//2022-01-18
}
b7. OffsetDateTime -> LocalDateTime
OffsetDateTime (偏移的日期时间)通过 OffsetDateTime.toLocalDateTime()方法 获取 LocalDateTime(本地日期时间)
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.now();
LocalDateTime ldt = odt.toLocalDateTime();
System.out.println(ldt);//2022-01-18T18:12:51.639
}
b8. ZonedDateTime -> Instant
ZonedDateTime (具有时区的日期时间)通过 ZonedDateTime.toInstant()方法 获取 Instant(格林威治时间戳)
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now();
Instant instant = zdt.toInstant();
System.out.println(instant);//2022-01-18T10:12:51Z
}
b9. ZonedDateTime -> LocalTime
ZonedDateTime (具有时区的日期时间)通过 ZonedDateTime.toLocalTime()方法 获取 LocalTime(本地时间)
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now();
LocalTime lt = zdt.toLocalTime();
System.out.println(lt);//18:12:51.639
}
b10. ZonedDateTime -> LocalDate
ZonedDateTime (具有时区的日期时间)通过 ZonedDateTime.toLocalDate()方法 获取 LocalDate(本地日期)
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now();
LocalDate ld = zdt.toLocalDate();
System.out.println(ld);//2022-01-18
}
b11. ZonedDateTime -> LocalDateTime
ZonedDateTime (具有时区的日期时间)通过 ZonedDateTime.toLocalDateTime()方法 获取 LocalDate(本地日期时间)
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now();
LocalDateTime ldt = zdt.toLocalDateTime();
System.out.println(ldt);//2022-01-18T18:12:51.639
}
b12. ZonedDateTime -> OffsetDateTime
ZonedDateTime (具有时区的日期时间)通过 ZonedDateTime.toOffsetDateTime()方法 获取 OffsetDateTime(偏移的日期时间)
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.now();
OffsetDateTime odt = zdt.toOffsetDateTime();
System.out.println(odt);//2022-01-18T18:12:51.639+08:00
}
b13. get方法向下转型
见 => 5. 新API详解 ,id=24 ChronoField 时间结界
c. 实例化对象 from
在使用 h.日期查询 query 方法时,需要实现 Temporaquery 接口的 queryFrom 方法,这个方法入参是一个 TemporalAccessor 对象。通过静态方法 from() 可以将其转为对应的时间对象。
public static void main(String[] args) {
LocalDateTime.now().query(new TemporalQuery<Object>() {
@Override
public Object queryFrom(TemporalAccessor ta) {
Instant i = Instant.from(ta);
LocalDate ld = LocalDate.from(ta);
LocalTime lt = LocalTime.from(ta);
LocalDateTime ldt = LocalDateTime.from(ta);
OffsetDateTime odt = OffsetDateTime.from(ta);
ZonedDateTime zdt = ZonedDateTime.from(ta);
return 0;
}
});
}
d. 获取当前时间 now
d1. Instant.now(2种)
d1. Instant
Instant.now( ):从 系统时间 获取 Instant(格林威治时间戳) 。
public static void main(String[] args) {
//instant无参构造:2022-01-18T10:12:51.639Z
Instant i = Instant.now();
System.out.println("instant无参构造:" + i);
}
d2. LocalTime.now(2种)
d2. LocalTime
Instant.now( ) :从 默认时区 的 系统时间 获取 LocalTime(本地时间)。
Instant.now(ZoneId zone) :从 指定时区 的 系统时间 获取 LocalTime(本地时间)。
public static void main(String[] args) {
//LocalTime默认时区:18:12:51.639
//LocalTime指定时区:18:12:51.639
LocalTime lt1 = LocalTime.now();
LocalTime lt2 = LocalTime.now(ZoneId.systemDefault());
System.out.println("LocalTime默认时区:" + lt1);
System.out.println("LocalTime指定时区:" + lt2);
}
d3. LocalDate.now(2种)
d3. LocalDate
LocalDate.now( ) :从 默认时区 的 系统时间 获取 LocalDate(本地日期)。
LocalDate.now(ZoneId zone) :从 指定时区 的 系统时间 获取 LocalDate(本地日期)。
public static void main(String[] args) {
//LocalDate默认时区:2022-01-18
//LocalDate指定时区:2022-01-18
LocalDate ld1 = LocalDate.now();
LocalDate ld2 = LocalDate.now(ZoneId.systemDefault());
System.out.println("LocalDate默认时区:" + ld1);
System.out.println("LocalDate指定时区:" + ld2);
}
d4. LocalDateTime.now(2种)
d4. LocalDateTime.now()
LocalDateTime.now( ) :从 默认时区 的 系统时间 获取 LocalDateTime(本地日期时间)。
LocalDateTime.now(ZoneId zone) :从 指定时区 的 系统时间 获取 LocalDateTime(本地日期时间)。
public static void main(String[] args) {
//LocalDateTime默认时区:2022-01-18T18:12:51.639
//LocalDateTime指定时区:2022-01-18T18:12:51.639
LocalDateTime ldt1 = LocalDateTime.now();
LocalDateTime ldt2 = LocalDateTime.now(ZoneId.systemDefault());
System.out.println("LocalDateTime默认时区:" + ldt1);
System.out.println("LocalDateTime指定时区:" + ldt2);
}
d5. OffsetDateTime.now(2种)
d5. OffsetDateTime
OffsetDateTime.now( ) :从 默认时区 的 系统时间 获取 OffsetDateTime(偏移的日期时间)。
OffsetDateTime.now(ZoneId zone) :从 指定时区 的 系统时间 获取 OffsetDateTime(偏移的日期时间)。
public static void main(String[] args) {
//OffsetDateTime默认时区::2022-01-18T18:12:51.639
//OffsetDateTime指定时区:2022-01-18T18:12:51.639
OffsetDateTime odt1 = OffsetDateTime. now();
OffsetDateTime odt2 = OffsetDateTime.now(ZoneId.systemDefault());
System.out.println("OffsetDateTime:" + odt1);
System.out.println("OffsetDateTime:" + odt2);
}
d6. ZonedDateTime.now(2种)
d6. ZonedDateTime
ZonedDateTime.now( ) :从 默认时区 的 系统时间 获取 OffsetDateTime(偏移的日期时间)。
ZonedDateTime.now(ZoneId zone) :从 指定时区 的 系统时间 获取 OffsetDateTime(偏移的日期时间)。
public static void main(String[] args) {
//ZonedDateTime默认时区::2022-01-18T18:12:51.639+08:00[Asia/Shanghai]
//ZonedDateTime指定时区:2022-01-18T18:12:51.639+08:00[Asia/Shanghai]
ZonedDateTime zdt1 = ZonedDateTime.now();
ZonedDateTime zdt2 = ZonedDateTime.now(ZoneId.systemDefault());
System.out.println("ZonedDateTime:" + zdt1);
System.out.println("ZonedDateTime:" + zdt2);
}
e. 日期加法 plus(减法 minus )
e1.时间戳增减
e1.时间戳增减: Instant中可使用。
1. plusNanos(long nanos) :增加 纳秒 (对应减少纳秒minusNanos,后面省略不写)
2. plusMillis(long seconds) :增加 毫秒
3. Seconds(long minutes) :增加 秒
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 18, 18, 12, 51, 639000000);
//原始时间:2022-01-18T10:12:51.639Z
Instant i = ldt.atZone(ZoneId.systemDefault()).toInstant();//Instant i = ldt.toInstant(ZoneOffset.of("+08:00"));
System.out.println("原始时间:" + i);
//1纳秒后时间:2022-01-18T10:12:51.639000001Z
Instant i1 = i.plusNanos(1);
System.out.println("1纳秒后时间:" + i1);
//2毫秒后时间:2022-01-18T10:12:51.641Z
Instant i2 = i.plusMillis(2);
System.out.println("2毫秒后时间:" + i2);
//3秒后时间:2022-01-18T10:12:54.639Z
Instant i3 = i.plusSeconds(3);
System.out.println("3秒后时间:" + i3);
}
e2.时间增减
e2.时间增减: LocalTime、LocalDateTime、OffSetDateTime、ZonedDateTime中均可使用。
1. plusNanos(long nanos) :增加 纳秒 (减少纳秒minusNanos,后面涉及到各plus方法均有对应minus方法)
2. plusSeconds(long seconds) :增加 秒
3. plusMinutes(long minutes) :增加 分钟
4. plusHours(long hours) :增加 小时
public static void main(String[] args) {
//原始时间:2022-01-18T18:12:51.639
LocalDateTime ldt = LocalDateTime.of(2022, 1, 18, 18, 12, 51, 639000000);
//原始时间:18:12:51.639
LocalTime lt = ldt.toLocalTime();
System.out.println("原始时间:" + lt);
//1纳秒后时间:18:12:51.639000001
LocalTime lt1 = lt.plusNanos(1);
System.out.println("1纳秒后时间:" + lt1);
//2秒后时间:18:12:53.639
LocalTime lt2 = lt.plusSeconds(2);
System.out.println("2秒后时间:" + lt2);
//3分钟后时间:18:15:51.639
LocalTime lt3 = lt.plusMinutes(3);
System.out.println("3分钟后时间:" + lt3);
//4小时后时间:22:12:51.639
LocalTime lt4 = lt.plusHours(4);
System.out.println("4小时后时间:" + lt4);
}
e3.日期增减
e3.日期增减: LocalDate、LocalDateTime、OffSetDateTime、ZonedDateTime中均可使用。
1. plusDays(long days) :增加 天数 (减少天数minusDays,后面涉及到各plus方法均有对应minus方法)
2. plusWeeks(long weeks) :增加 周
3. plusMonths(long months) :增加 月
4. plusYears(long years) :增加 年
public static void main(String[] args) {
//原始时间:2022-01-18T18:12:51.639
LocalDateTime ldt = LocalDateTime.of(2022, 1, 18, 18, 12, 51, 639000000);
System.out.println("原始时间:" + ldt);
//1天后时间:2022-01-19T18:12:51.639
LocalDateTime ldt1 = ldt.plusDays(1);
System.out.println("1天后时间:" + ldt1);
//2周后时间:2022-02-01T18:12:51.639
LocalDateTime ldt2 = ldt.plusWeeks(2);
System.out.println("2周后时间:" + ldt2);
//3月后时间:2022-04-18T18:12:51.639
LocalDateTime ldt3 = ldt.plusMonths(3);
System.out.println("3月后时间:" + ldt3);
//4年后时间:2026-01-18T18:12:51.639
LocalDateTime ldt4 = ldt.plusYears(4);
System.out.println("4年后时间:" + ldt4);
}
e4.范围增减(Duration or Period)
e4.范围增减: plus(TemporalAmount amount) 增加一个 时间范围,例如2年3个月4小时,参数(TemporalAmount amount) 是个接口,一般直接使用其实现类 Duration 和 Period,特殊规则可以自定义一个实现类
id | 类名 | 作用 |
---|---|---|
12 | Duration | TemporalAmount 接口的实现类,表示秒或纳秒时间间隔,适合处理需要时间高精确性的场景(秒杀)。(常用 l. 时间间隔 between:作为Duration.between静态方法的参数。) |
13 | Period | TemporalAmount 接口的实现类,表示一段时间(年、月、日)。(常用 l. 时间间隔 between:作为Duration.between静态方法的参数。e.日期加减:作为plus,minus方法的参数,指定计算的最小单位) 实例: 获取距离今天1年2个月零3天以后的本地日期时间 LocalDateTime result = LocalDateTime.now().plus(Period.of(1, 2, 3)); -------------------------------------------------------------------------------------- TemporalUnit是个接口,一般直接使用该接口在Java8自带的实现类即可(Duration、Period) idea查看uml图方式=> IDEA使用常见问题记录 的2.1.3 uml图 ![]() |
k1. Duration.of(数量,单位)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration1 = Duration.of(1, ChronoUnit.NANOS);//一纳秒
/*
Duration duration2 = Duration.of(1, ChronoUnit.MICROS);//一微秒
Duration duration3 = Duration.of(1, ChronoUnit.MILLIS);//一毫秒
Duration duration4 = Duration.of(1, ChronoUnit.SECONDS);//一秒
Duration duration5 = Duration.of(1, ChronoUnit.MINUTES);//一分钟
Duration duration6 = Duration.of(1, ChronoUnit.HOURS);//一小时
Duration duration7 = Duration.of(1, ChronoUnit.HALF_DAYS);//半天
Duration duration8 = Duration.of(1, ChronoUnit.DAYS);//一天
*/
try {
Duration duration9 = Duration.of(1, ChronoUnit.WEEKS);//一周
/*
Duration duration10 = Duration.of(1, ChronoUnit.MONTHS);//一月
Duration duration11 = Duration.of(1, ChronoUnit.YEARS);//一年
Duration duration12 = Duration.of(1, ChronoUnit.DECADES);//十年
Duration duration13 = Duration.of(1, ChronoUnit.CENTURIES);//百年(一个世纪)
Duration duration14 = Duration.of(1, ChronoUnit.MILLENNIA);//千年
Duration duration15 = Duration.of(1, ChronoUnit.ERAS);//十亿年(一个纪元)
Duration duration16 = Duration.of(1, ChronoUnit.FOREVER);//2.92277266×1011年(永恒)
*/
} catch (Exception e) {
e.printStackTrace();
}
LocalDateTime plus = ldt.plus(duration1);
System.out.println(ldt + " =>" + plus);
}
k2. Duration.ofNanos(纳秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofNanos(1);
//2022-01-01T00:00 => 2022-01-01T00:00:00.000000001
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k3. Duration.ofMillils(毫秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofMillis(2);
//2022-01-01T00:00 => 2022-01-01T00:00:00.002
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k4. Duration.ofSeconds(秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofSeconds(3);
//2022-01-01T00:00 => 2022-01-01T00:00:03
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k5. Duration.ofSeconds(秒,纳秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofSeconds(4,5);
//2022-01-01T00:00 => 2022-01-01T00:00:04.000000005
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k6. Duration.ofMinutes(分钟)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofMinutes(6);
//2022-01-01T00:00 => 2022-01-01T00:06
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k7. Duration.ofHours(小时)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofHours(7);
//2022-01-01T00:00 => 2022-01-01T07:00
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k8. Duration.ofDays(天)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofDays(8);
//2022-01-01T00:00 => 2022-01-09T00:00
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k9. Period.of(年,月,日)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.of(1, 2, 3);
//2022-01-01T00:00 => 2023-03-04T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k10. Period.ofDays(日)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofDays(4);
//2022-01-01T00:00 => 2022-01-05T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k11. Period.ofWeeks(周)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofWeeks(5);
//2022-01-01T00:00 => 2022-02-05T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k12. Period.ofMonths(月)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofWeeks(5);
//2022-01-01T00:00 => 2022-07-01T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k13. Period.ofYears(年)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofYears(7);
//2022-01-01T00:00 => 2029-01-01T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
e5.时间单位增减(ChronoUnit )
e5. 时间单位增减: plus(long amountToAdd, TemporalUnit unit) 指定最小单位、最小单位个数;
例如: 增加5个世纪 => plus(5,ChronoUnit.CENTURIES)
id | 类名 | 作用 |
---|---|---|
14 | Enum ChronoUnit | TemporalAmount 接口的实现类,采用枚举类的方式表示一些 计算常用时间单位。(常用 e.日期加减:作为plus,minus方法的参数,指定计算的最小单位) 例如: 一纳秒(ChronoUnit.NANOS) 一微秒(ChronoUnit.MICROS) 一毫秒(ChronoUnit.MILLIS) 一秒(ChronoUnit.SECONDS) 一分钟(ChronoUnit.MINUTES) 一小时(ChronoUnit.HOURS) 半天(ChronoUnit.HALF_DAYS) 一天(ChronoUnit.DAYS) 一周(ChronoUnit.WEEKS) 一个月(ChronoUnit.MONTHS) 一年(ChronoUnit.YEARS) 十年(ChronoUnit.DECADES) 百年(一个世纪)(ChronoUnit.CENTURIES) 千年(ChronoUnit.MILLENNIA) 十亿年(一个纪元)(ChronoUnit.ERAS) 2.92277266×1011年(永恒)(ChronoUnit.FOREVER) 实例: 获取举例今天100年以后的本地日期时间 LocalDate DecadesFromNow = LocalDate.now().plus(1,ChronoUnit.DECADES); -------------------------------------------------------------------------------------- TemporalUnit是个接口,一般直接使用该接口在Java8自带的实现类即可(ChronoUnit) idea查看uml图方式=> IDEA使用常见问题记录 的2.1.3 uml图 ![]() |
f. 日期判断 isAfter(isBefore)
两个比较的对象类型需要一致
isAfter(ChronoLocalDateTime<?> other)** :检查这个日期时间是否在指定的日期之后。 **isBefore(ChronoLocalDateTime<?> other) :检查这个日期时间是否在指定的日期之前。
public static void main(String[] args) {
boolean after1 = Instant.now().isAfter(Instant.now());
boolean after2 = LocalDateTime.now().isAfter(LocalDateTime.now());
boolean after3 = LocalDate.now().isAfter(LocalDate.now());
boolean after4 = LocalTime.now().isAfter(LocalTime.now());
boolean after5 = OffsetDateTime.now().isAfter(OffsetDateTime.now());
boolean after6 = ZonedDateTime.now().isAfter(ZonedDateTime.now());
}
g. 日期调节器 with
按照一定规则(例如:“下个星期一”,“当月的15号”,“当年的第1个周一”)对日期对象修改,并返回一个符合条件的新日期对象。
g1. with + 调节器
日期调节器 with(TemporalAdjuster adjuster) 的参数 TemporalAdjuster 一般通过 Java8自带的调节器 TemporalAdjusters 返回值
id | 类名 | 作用 |
---|---|---|
19 | TemporalAdjusters 调节器 | 类中所有方法都会返回一个 TemporalAdjuster 对象。 表示一些 常用时间节点,供时间计算。(常用 g. 日期调节器 with:作为*.with的参数,按照一些特殊规则计算时间) 例如: 上一个星期几(TemporalAdjusters.previous(DayOfWeek dayOfWeek)) 上一个星期几或当天(TemporalAdjusters.previousOrSame(DayOfWeek dayOfWeek)) 下一个星期几(TemporalAdjusters.next(DayOfWeek dayOfWeek)) 下一个星期几或当天(TemporalAdjusters.nextOrSame(DayOfWeek dayOfWeek)) 当月第1天(TemporalAdjusters.firstDayOfMonth()) 当月最后1天(TemporalAdjusters.lastDayOfMonth()()) 当月第1个星期几(TemporalAdjusters.firstInMonth(DayOfWeek dayOfWeek)) 当月第n个星期几(TemporalAdjusters.dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)) 当月最后一个星期几(TemporalAdjusters.lastInMonth(DayOfWeek dayOfWeek)) 当年最后1天(TemporalAdjusters.lastDayOfYear()) 明年的第1天(TemporalAdjusters.firstDayOfNextYear()) 下月第1天(TemporalAdjusters.firstDayOfNextMonth()) lambda表达式自定义指定日期(TemporalAdjusters. ofDateAdjuster(UnaryOperator<LocalDate> dateBasedAdjuster)) 实例: 获取举例今天100年以后的日期 LocalDate DecadesFromNow = LocalDate.now().plus(1,ChronoUnit.DECADES); -------------------------------------------------------------------------------------- Class TemporalAdjusters 并不是 interface TemporalAdjuster 的实现类,只不过 Class TemporalAdjusters 的静态方法实现了 interface TemporalAdjuster,并返回 interface TemporalAdjuster 对象的实例 |
这里以 DayOFWeek 举例,详细内容查看 5.新API详解 id=2 DayOfWeek星期枚举
DayOfWeek 可以作为 -> with 方法的参数调节日期,例如:获取"下个星期五"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
//可以作为 -> with 方法的参数调节日期,例如:获取"下个星期五"的日期
TemporalAdjuster previous = TemporalAdjusters.next(DayOfWeek.of(5));
LocalDateTime nextFriday = ldt.with(previous);
//2022-01-01T00:00是星期六,他的下一个周五日期是2022-01-07T00:00
System.out.println(ldt + "是" + ldt.getDayOfWeek().
getDisplayName(TextStyle.FULL, Locale.CHINESE) +
",他的下一个周五日期是" + nextFriday);
}
DayOfWeek 可以作为判断条件 -> with 方法中自定义接口,实现同样功能:获取"下个星期五"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
//可以作为判断条件 -> with 方法中自定义接口,实现同样功能:获取"下个星期五"的日期。
LocalDateTime nextFriday = ldt.with(new TemporalAdjuster() {
@Override
public Temporal adjustInto(Temporal temporal) {
//获取当前日期是星期几
int i = temporal.get(ChronoField.DAY_OF_WEEK);
DayOfWeek dayOfWeekNow = DayOfWeek.of(i);
if (dayOfWeekNow == DayOfWeek.MONDAY) return temporal.plus(4, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.TUESDAY) return temporal.plus(3, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.WEDNESDAY) return temporal.plus(2, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.THURSDAY) return temporal.plus(1, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.FRIDAY) return temporal;
else if (dayOfWeekNow == DayOfWeek.SATURDAY) return temporal.plus(6, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.SUNDAY) return temporal.plus(5, ChronoUnit.DAYS);
return null;
}
});
//2022-01-01T00:00是星期六,他的下一个周五日期是2022-01-07T00:00
System.out.println(ldt + "是" + ldt.getDayOfWeek().
getDisplayName(TextStyle.FULL, Locale.CHINESE) +
",他的下一个周五日期是" + nextFriday);
}
或者通过 TemporalAdjusters.ofDateAdjuster:
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
//可以作为判断条件 -> with 方法中自定义接口,实现同样功能:获取"下个星期五"的日期。
TemporalAdjuster nextFridayAdjuster = TemporalAdjusters.ofDateAdjuster(new UnaryOperator<LocalDate>() {
@Override
public LocalDate apply(LocalDate localDate) {
//获取当前日期是星期几
int i = localDate.get(ChronoField.DAY_OF_WEEK);
DayOfWeek dayOfWeekNow = DayOfWeek.of(i);
if (dayOfWeekNow == DayOfWeek.MONDAY) return localDate.plus(4, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.TUESDAY) return localDate.plus(3, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.WEDNESDAY) return localDate.plus(2, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.THURSDAY) return localDate.plus(1, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.FRIDAY) return localDate;
else if (dayOfWeekNow == DayOfWeek.SATURDAY) return localDate.plus(6, ChronoUnit.DAYS);
else if (dayOfWeekNow == DayOfWeek.SUNDAY) return localDate.plus(5, ChronoUnit.DAYS);
return null;
}
});
LocalDateTime nextFriday = ldt.with(nextFridayAdjuster);
//2022-01-01T00:00是星期六,他的下一个周五日期是2022-01-07T00:00
System.out.println(ldt + "是" + ldt.getDayOfWeek().
getDisplayName(TextStyle.FULL, Locale.CHINESE) +
",他的下一个周五日期是" + nextFriday);
}
g2. with + 时间结界
见 => 5. 新API详解 ,id=24 ChronoField 时间结界
g3. withNano 纳秒
获取当前时间的"纳秒数调整为1"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withNano(1);
//原时间:2022-01-01T00:00,修改后:2022-01-01T00:00:00.000000001
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g4. withSecond 秒
获取当前时间的"秒数调整为2"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withSecond(2);
//原时间:2022-01-01T00:00,修改后:2022-01-01T00:00:02
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g5. withMinute 分钟
获取当前时间的"分钟调整为3"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withMinute(3);
//原时间:2022-01-01T00:00,修改后:2022-01-01T00:03
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g6. withHour 小时
获取当前时间的"小时调整为4"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withHour(4);
//原时间:2022-01-01T00:00,修改后:2022-01-01T04:00
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g7. withDayOfMonth 第n天(月中)
获取当前时间的"月中第5天"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withDayOfMonth(5);
//原时间:2022-01-01T00:00,修改后:2022-01-05T00:00
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g8. withDayOfYear 第n天(年中)
获取当前时间的"年中第60天"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withDayOfYear(60);
//原时间:2022-01-01T00:00,修改后:2022-03-01T00:00
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g9. withMonth 月
获取当前时间的"月调整为7"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withMonth(7);
//原时间:2022-01-01T00:00,修改后:2022-07-01T00:00
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g10. withYear 年
获取当前时间的"年调整为8"的日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime withNano = ldt.withYear(8);
//原时间:2022-01-01T00:00,修改后:0008-01-01T00:00
System.out.println("原时间:" + ldt + ",修改后:" + withNano);
}
g11. 结合query使用
见 =>h. 日期查询 query
h. 日期查询 query
<= g. 自定义调节器 with
节日查询:“假设今天是2022年5月31日,计算出距离下个圣诞节(12.28)、儿童节(6.1)、劳动节(5.1)分别还有多少天”。
public static void main(String[] args) {
//创建日期对象2022年5月31日,模拟计算
LocalDate today = LocalDate.of(2022, 5, 31);
HashMap<String, Long> queryResult = today.query(new TemporalQuery<HashMap<String, Long>>() {
@Override
//TemporalAccessor是LocalDateTime、LocalDate的顶级父类接口
//相当于LocalDate就是这个接口的实现类,将temporal转换为LocalDate进行使用。
public HashMap<String, Long> queryFrom(TemporalAccessor temporalAccessor) {
//1.将 temporalAccessor 转为LocalDate对象
LocalDate ld = LocalDate.from(temporalAccessor);
//2.创建容器
HashMap<String, LocalDate> ldMap = new HashMap<>();
HashMap<String, Long> resultMap = new HashMap<>();
//3.封装当年的圣诞节/儿童节/劳动节的时间对象
ldMap.put("圣诞节", LocalDate.of(ld.getYear(), Month.DECEMBER, 2));
ldMap.put("儿童节", LocalDate.of(ld.getYear(), Month.JUNE, 1));
ldMap.put("劳动节", LocalDate.of(ld.getYear(), Month.MAY, 1));
//4.判断date是否已经超过了d1/d2/d3三个节日,如果超过了,则计算下一年的日期
for (String key : ldMap.keySet()) {
LocalDate holidayDate = ldMap.get(key);
//如果当前时间>当年节日,则节日日期+1年
if (ld.isAfter(holidayDate)) holidayDate = holidayDate.plusYears(1);
//计算:距离该节日还差几天
resultMap.put(key, ChronoUnit.DAYS.between(ld, holidayDate));
}
//5.返回结果
return resultMap;
}
});
//打印结果
for (String holidayName : queryResult.keySet()) {
//距离下一个儿童节还剩1天
//距离下一个劳动节还剩335天
//距离下一个圣诞节还剩185天
System.out.println("距离下一个" + holidayName + "还剩" + queryResult.get(holidayName) + "天");
}
}
i. 日期解析 format(日期 -> String)⭐️
i1. 标准的ISO日期格式 DateTimeFormatter.❓
id | 类名 | 作用 |
---|---|---|
21 | DateTimeFormatter | 日期格式化器,用于打印和解析日期时间对象。(常用 i. 日期解析 format(日期->String):作为*.with的参数,按照一些特殊规则计算时间) 常用方法: DateTimeFormatter.ofLocalizedDate 静态方法,自动识别时区的方式解析,需要传入一个FormatStyle的枚举值 DateTimeFormatter.ofPattern 静态方法,指定日期格式的解析,需要传入一个字符串日期格式 实例: String format1 = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE); String format2 = LocalDateTime.now().format(DateTimeFormatter.ofPattern(“yyyy-MM-dd’T’HH:mm:ss.SSS”)); -------------------------------------------------------------------------------------- DateTimeFormatter预制的格式化器,最常用的两个: 1. yyyy-MM-dd DateTimeFormatter.ISO_DATE => 2022-01-18 2. yyyy-MM-dd’T’HH:mm:ss.SSS DateTimeFormatter.ISO_DATE_TIME =>2022-01-18T18:12:51.639 -------------------------------------------------------------------------------------- 带不带 LOCAL 的对比: 仅对 OffsetDateTime、ZonedDateTime 有区别 1. LocalDateTime + ISO_DATE_TIME LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); => 2022-01-18T18:12:51.639 2. LocalDateTime + ISO_LOCAL_DATE_TIME LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); => 2022-01-18T18:12:51.639 3. OffsetDateTime + ISO_DATE_TIME OffsetDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); => 2022-01-18T18:12:51.639+08:00 4. OffsetDateTime + ISO_LOCAL_DATE_TIME OffsetDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); => 2022-01-18T11:12:51.639 5. ZonedDateTime + ISO_DATE_TIME ZonedDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); => 2022-01-18T18:12:51.639+08:00[Asia/Shanghai] 6. ZonedDateTime + ISO_LOCAL_DATE_TIME ZonedDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); => 2022-01-18T18:12:51.639 |
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
String format1 = ldt.format(DateTimeFormatter.ISO_DATE);
String format2 = ldt.format(DateTimeFormatter.ISO_DATE_TIME);
String format3 = ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"));
System.out.println(format1);//2022-01-18
System.out.println(format2);//2022-01-18T18:12:51.639
System.out.println(format2);//2022-01-18T18:12:51.639
}
i2. 自动识别时区 DateTimeFormatter.ofLocalizedDate(FormatStyle.❓))
id | 类名 | 作用 |
---|---|---|
22 | Enum FormatStyle | 枚举本地化日期,时间或日期时间格式化的风格。(常用 i. 日期解析 format(日期->String):作为 DateTimeFormatter.ofLocalizedDate(FormatStyle dateStyle) 静态方法的参数使用,并返回一个 DateTimeFormatter 对象) 例如: 全文格式(FormatStyle.FULL)=> 2022年1月18日 星期二 长文本格式(FormatStyle.LONG)=> 2022年1月18日 中等格式(FormatStyle.MEDIUM)=> 2022-1-18 短文格式(FormatStyle.SHORT)=> 22-1-18 实例: 全文格式解析本地日期时间 String format = LocalDateTime.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)); -------------------------------------------------------------------------------------- 需要注意 这种方式在不同时区的显示内容不一样,在其他时区不会显示中文 |
ofLocalizedDate表示自动根据时区识别本地格式,通过指定 全/长/中/短 几种格式来解析日期。
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
String fullTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL));
String longTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));
String mediumTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
String shortTime = ldt.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));
System.out.println(fullTime);//2022年1月18日 星期二
System.out.println(longTime);//2022年1月18日
System.out.println(mediumTime);//2022-1-18
System.out.println(shortTime);//22-1-18
}
j. 日期解析 parse 方法(String -> 日期)
直接使用静态方法parse但不符合格式的字符串会解析失败
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.parse("2022-01-18T18:12:51.639");
System.out.println(ldt);//2022-01-18T18:12:51.639
LocalDate ld = LocalDate.parse("2022-01-18T18:12:51.639");
//java.time.format.DateTimeParseException:
//Text '2022-01-18T18:12:51.639' could not be parsed, unparsed text found at index 10
System.out.println(ld);
}
4. 新API实例 - 时间段类
k. 实例化对象 of
k1. Duration.of(数量,单位)
这里需要传入2个参数,数量和单位,单位一般使用jdk8自带的实现类ChronoUnit(详情见 5. 新API详解 => id=14 ChronoUnit 时间单位枚举),也可以自定义 TemporalAmount 接口的实现类;
id | 类名 | 作用 |
---|---|---|
14 | Enum ChronoUnit | TemporalAmount 接口的实现类,采用枚举类的方式表示一些 计算常用时间单位。(常用 e.日期加减:作为plus,minus方法的参数,指定计算的最小单位) 例如: 一纳秒(ChronoUnit.NANOS) 一微秒(ChronoUnit.MICROS) 一毫秒(ChronoUnit.MILLIS) 一秒(ChronoUnit.SECONDS) 一分钟(ChronoUnit.MINUTES) 一小时(ChronoUnit.HOURS) 半天(ChronoUnit.HALF_DAYS) 一天(ChronoUnit.DAYS) 一周(ChronoUnit.WEEKS) 一个月(ChronoUnit.MONTHS) 一年(ChronoUnit.YEARS) 十年(ChronoUnit.DECADES) 百年(一个世纪)(ChronoUnit.CENTURIES) 千年(ChronoUnit.MILLENNIA) 十亿年(一个纪元)(ChronoUnit.ERAS) 2.92277266×1011年(永恒)(ChronoUnit.FOREVER) 实例: 获取举例今天100年以后的本地日期时间 LocalDate DecadesFromNow = LocalDate.now().plus(1,ChronoUnit.DECADES); -------------------------------------------------------------------------------------- TemporalUnit是个接口,一般直接使用该接口在Java8自带的实现类即可(ChronoUnit) idea查看uml图方式=> IDEA使用常见问题记录 的2.1.3 uml图 ![]() |
实例: 2022年1月1日0点0分0秒,加1纳秒。 |
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration1 = Duration.of(1, ChronoUnit.NANOS);//一纳秒
/*
Duration duration2 = Duration.of(1, ChronoUnit.MICROS);//一微秒
Duration duration3 = Duration.of(1, ChronoUnit.MILLIS);//一毫秒
Duration duration4 = Duration.of(1, ChronoUnit.SECONDS);//一秒
Duration duration5 = Duration.of(1, ChronoUnit.MINUTES);//一分钟
Duration duration6 = Duration.of(1, ChronoUnit.HOURS);//一小时
Duration duration7 = Duration.of(1, ChronoUnit.HALF_DAYS);//半天
Duration duration8 = Duration.of(1, ChronoUnit.DAYS);//一天
*/
try {
Duration duration9 = Duration.of(1, ChronoUnit.WEEKS);//一周
/*
Duration duration10 = Duration.of(1, ChronoUnit.MONTHS);//一月
Duration duration11 = Duration.of(1, ChronoUnit.YEARS);//一年
Duration duration12 = Duration.of(1, ChronoUnit.DECADES);//十年
Duration duration13 = Duration.of(1, ChronoUnit.CENTURIES);//百年(一个世纪)
Duration duration14 = Duration.of(1, ChronoUnit.MILLENNIA);//千年
Duration duration15 = Duration.of(1, ChronoUnit.ERAS);//十亿年(一个纪元)
Duration duration16 = Duration.of(1, ChronoUnit.FOREVER);//2.92277266×1011年(永恒)
*/
} catch (Exception e) {
e.printStackTrace();
}
LocalDateTime plus = ldt.plus(duration1);
System.out.println("原始时间 :" + ldt);
System.out.println("修改后时间:" + plus);
}
运行结果:
java.time.temporal.UnsupportedTemporalTypeException: Unit must not have an estimated duration
at java.time.Duration.plus(Duration.java:701)
at java.time.Duration.of(Duration.java:308)
at com.groupies.jdk8.day04....
原始时间 :2022-01-01T00:00
修改后时间:2022-01-01T00:00:00.000000001
出现报错信息 Unit must not have an estimated duration(单位必须不包含估计的时间) ,首先来定位一下源码,查找错误原因
step1. Duration of(long amount, TemporalUnit unit)源码:
step2. 找到报错的出处:
step3. 关于isDurationEstimated的解释:
step4. ChronoUnit中关于isDurationEstimated的定义:
step5. Duration.of(数量,单位)取值范围总结:
类型 | 类名 | 作为Duration.of的参数 |
---|---|---|
估算值 estimate | 一纳秒(ChronoUnit.NANOS) 一微秒(ChronoUnit.MICROS) 一毫秒(ChronoUnit.MILLIS) 一秒(ChronoUnit.SECONDS) 一分钟(ChronoUnit.MINUTES) 一小时(ChronoUnit.HOURS) 半天(ChronoUnit.HALF_DAYS) 一天(ChronoUnit.DAYS) | 可以 |
准确值 exact value | 一周(ChronoUnit.WEEKS) 一个月(ChronoUnit.MONTHS) 一年(ChronoUnit.YEARS) 十年(ChronoUnit.DECADES) 百年(一个世纪)(ChronoUnit.CENTURIES) 千年(ChronoUnit.MILLENNIA) 十亿年(一个纪元)(ChronoUnit.ERAS) 2.92277266×1011年(永恒)(ChronoUnit.FOREVER) | 不可以 |
k2. Duration.ofNanos(纳秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofNanos(1);
//2022-01-01T00:00 => 2022-01-01T00:00:00.000000001
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k3. Duration.ofMillils(毫秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofMillis(2);
//2022-01-01T00:00 => 2022-01-01T00:00:00.002
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k4. Duration.ofSeconds(秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofSeconds(3);
//2022-01-01T00:00 => 2022-01-01T00:00:03
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k5. Duration.ofSeconds(秒,纳秒)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofSeconds(4,5);
//2022-01-01T00:00 => 2022-01-01T00:00:04.000000005
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k6. Duration.ofMinutes(分钟)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofMinutes(6);
//2022-01-01T00:00 => 2022-01-01T00:06
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k7. Duration.ofHours(小时)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofHours(7);
//2022-01-01T00:00 => 2022-01-01T07:00
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k8. Duration.ofDays(天)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Duration duration = Duration.ofDays(8);
//2022-01-01T00:00 => 2022-01-09T00:00
LocalDateTime plus = ldt.plus(duration);
System.out.println(ldt + " =>" + plus);
}
k9. Period.of(年,月,日)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.of(1, 2, 3);
//2022-01-01T00:00 => 2023-03-04T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k10. Period.ofDays(日)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofDays(4);
//2022-01-01T00:00 => 2022-01-05T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k11. Period.ofWeeks(周)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofWeeks(5);
//2022-01-01T00:00 => 2022-02-05T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k12. Period.ofMonths(月)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofWeeks(5);
//2022-01-01T00:00 => 2022-07-01T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
k13. Period.ofYears(年)
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
Period period = Period.ofYears(7);
//2022-01-01T00:00 => 2029-01-01T00:00
LocalDateTime plus = ldt.plus(period);
System.out.println(ldt + " =>" + plus);
}
l. 时间间隔 between
l1. 范围间隔 Duration.between
支持LocalDateTime、LocalTime、Instant等秒级(Second)信息的时间对象;传入LocalDate类型可以通过编译,运行时会提示 Unsupported unit: Seconds;
public static void main(String[] args) {
LocalDateTime ldt1 = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime ldt2 = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
System.out.println(Duration.between(ldt1,ldt2));
LocalDate ld1 = LocalDate.of(2022, 1, 1);
LocalDate ld2 = LocalDate.of(2000, 1, 1);
System.out.println(Duration.between(ld1, ld2));
}
l2. 范围间隔 Period.between
仅支持LocalDate类型,传入其他类型编译不通过
public static void main(String[] args) {
LocalDate ld1 = LocalDate.of(2022, 1, 1);
LocalDate ld2 = LocalDate.of(2000, 1, 1);
//P-22Y
System.out.println(Period.between(ld1, ld2));
LocalDateTime ldt1 = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
LocalDateTime ldt2 = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
System.out.println(Period.between(ldt1,ldt2));
}
l3. 时间单位间隔 ChronoUnit.❓ .between
ChronoUnit共16种类型,时间单位也有Instant、LocalDate、LocalTime、LocalDateTime…等多种类型,排列组合方式过多,这里仅测试了LocalDate&ChronoUnit.between 之间的关系;
id | 类名 | 作用 |
---|---|---|
14 | Enum ChronoUnit | TemporalAmount 接口的实现类,采用枚举类的方式表示一些 计算常用时间单位。(常用 e.日期加减:作为plus,minus方法的参数,指定计算的最小单位) 例如: 一纳秒(ChronoUnit.NANOS) 一微秒(ChronoUnit.MICROS) 一毫秒(ChronoUnit.MILLIS) 一秒(ChronoUnit.SECONDS) 一分钟(ChronoUnit.MINUTES) 一小时(ChronoUnit.HOURS) 半天(ChronoUnit.HALF_DAYS) 一天(ChronoUnit.DAYS) 一周(ChronoUnit.WEEKS) 一个月(ChronoUnit.MONTHS) 一年(ChronoUnit.YEARS) 十年(ChronoUnit.DECADES) 百年(一个世纪)(ChronoUnit.CENTURIES) 千年(ChronoUnit.MILLENNIA) 十亿年(一个纪元)(ChronoUnit.ERAS) 2.92277266×1011年(永恒)(ChronoUnit.FOREVER) |
public static void main(String[] args) {
LocalDate ld1 = LocalDate.of(2022, 1, 1);
LocalDate ld2 = LocalDate.of(2000, 1, 1);
System.out.println("YEARS:" + ChronoUnit.YEARS.between(ld1, ld2));
System.out.println("MONTHS:" + ChronoUnit.MONTHS.between(ld1, ld2));
System.out.println("WEEKS:" + ChronoUnit.WEEKS.between(ld1, ld2));
System.out.println("DECADES:" + ChronoUnit.DECADES.between(ld1, ld2));
System.out.println("DAYS:" + ChronoUnit.DAYS.between(ld1, ld2));
System.out.println("HOURS:" + ChronoUnit.HOURS.between(ld1, ld2));
System.out.println("MINUTES:" + ChronoUnit.MINUTES.between(ld1, ld2));
System.out.println("SECONDS:" + ChronoUnit.SECONDS.between(ld1, ld2));
}
LocalDate对象没有小时的信息,所以不支持计算小时级别时间范围
5. 新API详解
id=2 DayOfWeek 星期枚举
文章过长不能保存,内容发布在另一篇blog => 3.1_28_1 JDK8新特性【Date】之DayOfWeek 星期枚举
id=4 Month 月枚举
文章过长不能保存,内容发布在另一篇blog => 3.1_28_2 JDK8新特性【Date】之Month 月枚举
id=14 ChronoUnit 时间单位枚举
文章过长不能保存,内容发布在另一篇blog => JDK8新特性【Date】之ChronoUnit 时间单位枚举
id=16 ZoneId 时区信息
文章过长不能保存,内容发布在另一篇blog => JDK8新特性【Date】之ZoneId 时区信息
id=24 ChronoField 时间结界
文章过长不能保存,内容发布在另一篇blog => DK8新特性【Date】之ChronoField 时间结界
6.旧API转换
对于老项目的改造,需要将 Date 或者 Calendar 转换为 java.time 包中相应的类。这里总结了一些类的转换过程。
6.1 java.util.Date -> java.sql.Date
6.2 java.util.Date -> java.time.Instant
6.3 java.util.Date -> java.time.LocalDate
6.4 java.sql.Date -> java.util.Date
6.5 java.sql.Date -> java.time.Instant
6.6 java.sql.Date -> java.time.LocalDate
6.7 java.sql.Timestamp -> java.time.Instant
6.8 java.sql.Timestamp -> java.time.toLocalDate
6.9 java.util.Calendar -> java.time.LocalDateTime
6.10 java.util.Calendar -> java.time.ZonedDateTime
文章过长不能保存,内容发布在另一篇blog => JDK8新特性【Date】之旧API转换
7. 注意事项
7.1 对比 OffsetDateTime & ZonedDateTime
LocalDateTime、OffsetDateTime、ZonedDateTime这三个哥们,LocalDateTime比较好理解,一般都没有异议。关于OffsetDateTime和ZonedDateTime对比如下:
组成:
1. OffsetDateTime: = LocalDateTime + ZoneOffset(偏移量)
2. ZonedDateTime: = LocalDateTime + ZoneId(时区信息)
偏移值:
1. OffsetDateTime:可以设置 偏移值
2. ZonedDateTime:无法设置 偏移值
夏令时:
1. OffsetDateTime:无法支持 夏令时调整
2. ZonedDateTime:可以支持 夏令时调整
区别: 等于ZoneOffset和ZoneId的区别
1. OffsetDateTime:代表一个瞬时值 ,《0时区 + 固定偏移量》 计算出来的
2. ZonedDateTime:代表一个动态计算值,《0时区 + 动态偏移量》(根据当时的规则)计算出来的
使用场景:
1. OffsetDateTime:由于其不变性的特点,主要用于传递数据,数据库存储、网络通信
2. ZonedDateTime:由于其时区性的特点,主要用于在特定时区里做时间显示
7.2 新API的 == 和 equals
1. ==: ×,比较的是两个对象在堆中的内存地址。
2. equals()方法: √ ,equals()方法继承自Object类,所有Object的子类都可以重写该方法,新版时间API重写该方法后,比较的是时间的值。
是由于新版API时间对象不可变特性(为了更好地支持多线程),每次对时间的计算都会返回一个新的时间对象,新的对象也就意味着新的堆内存地址,所以新版时间API比较时间时,要采用 equals(): 方式比较。
7.3 指定时区
构造日期时间对象时指定时区。为了明确代码意图,消除语义上的不确定性。
22/02/11
M
Unix 时间戳 Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。 ↩︎
纪元时间 指1970年1月1日格林威治午夜12点为起点,纪元日的定义与UNIX发展历史有关。 ↩︎
月对齐 重新定义一个关于星期几的新规则,规则描述:每月的1日作为周一(1.1日/2.1日/…12.1日),例如"2022年2月1日"是星期二,但在月对齐(ALIGNED_xxxx_MONTH)的新规则下,"2022年2月1日"是星期一。 ↩︎
年对齐 重新定义一个关于星期几的新规则,规则描述:每年的1月1日作为周一,例如"2022年1月1日"是星期六,但在年对齐(ALIGNED_xxxx_YEAR)的新规则下,"2022年1月1日"是星期一 ↩︎
公元 公历纪年法,是一种源自于西方社会的纪年方法。原称基督纪元,又称西历或西元。 ↩︎