Java基础篇之——第三版时间API
作者:互联网
jdk1.8之后Java终于迎来了全新的时间API,摒弃了以往Date类中的难用,死板的模板,我们可以使用全新的API更加方便地去使用时间:
JDK 1.0 java.util.Date 第一版 时间API
JDK 1.1 Calendar 第二版 时间API
缺点:可变性差,偏移性差,年份从1900年开始,月份从0开始,格式化能力差,Calendar就不支持格式化。
在我们使用jdk 1.8的情况下,你会发现 Date 类中有太多太多已被弃用的方法,所以更新新的时间API是非常明智的!
这次我们讨论内容有三个部分:
- 如何使用新API
- 从旧API过渡到新API
- 所有方法总结
第一节:新API使用
首先介绍三种时间对象:LocalDate,LocalTime,LocalDateTime。
顾名思义,他们表示:本地日期,本地时间,本地日期+时间。
何为本地?就是当前的世界时钟+当前时区,例如我现在的时区就是上海,也就是UTC + 8 时区。
还有另外三种时间对象:OffsetDateTime(携带时区的LocalDateTime),ZonedDateTime(携带时区+地区的 LocalDateTime),Instant(机器时间)。这三种对象比较特殊,我们在之后会好好认识它们。
现在,让我们先从简单的练练手:
LocalDate date = LocalDate.now();
// 2021-11-19
LocalTime time = LocalTime.now();
// 21:31:54.533170600
LocalDateTime dateTime = LocalDateTime.now();
// 2022-02-12T10:30:19.831515600
LocalTime是可以精确到纳秒的,还是比较精确的,现在我们已经知道获取当前时间的方法: now(),那么我们还有其他方法可以使用吗?当然有,而且非常丰富!
方法我规划成以下三类:
1.生成时间的方法
2.时间口语化的方法
3.时间计算的方法
1.1 生成时间的方法
不单单是now(),你还可以通过其他方式来定制化时间,请看实例:
1).使用of工厂方法通过int值生成时间
LocalDate date = LocalDate.of(2022,1,1);
// 2022-01-01
LocalTime date = LocalTime.of(10,1,1);
// 10:10:01
LocalDateTime date = LocalDateTime.of(2022,1,1,10,1,1);
// 2022-01-01T10:10:01
LocalDateTime dateTime = LocalDateTime.of(2022, Month.FEBRUARY, 22,22,22,22);
// 2022-02-22T22:22:22 (通过 Month 枚举类)
//date 和 time 合成 dateTime
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.of(date,time);
// 2022-01-01T10:10:01
2).parse方法通过Stings生成时间
//第一种方式使用parse方法,通过字符串创建时间对象
LocalDate parse = LocalDate.parse("2022-01-01");
// 2022-01-01
LocalTime parse = LocalTime.parse("18:10:10");
// 18:10:10
LocalDateTime parse = LocalDateTime.parse("2022-01-01T18:10:10");
// 2022-01-01T18:10:10
//parse方法故名思意是一种格式化字符串输出日期的方式,我们可以传入日期的字符串格式来输出日期
//第二种方式使用parse方法,传入字符串以及自定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//日期格式,我们自定义了日期格式
LocalDateTime parse = LocalDateTime.parse("2022/01/01 18:10:10",formatter);
//传入自定义日期格式和符合格式的字符串
//第三种方式使用parse方法,传入字符串以及JDK提供的日期格式
LocalDateTime parse = LocalDateTime.parse("2022-01-01T18:10:10",DateTimeFormatter.ISO_LOCAL_DATE_TIME);
// 2022-01-01T18:10:10
LocalDate parse = LocalDate.parse("20220212",DateTimeFormatter.BASIC_ISO_DATE);
// 2022-01-01
3).通过from方法,完成LocalDate,LocalTime,LocaldDateTime之间的互相转化:
//实例1:dateTime转date
LocalDateTime dateTime = LocalDateTime.now();
//2022-02-22T16:00:00
LocalDate date = LocalDate.from(dateTime);
//2022-02-22
//实例2:dateTime转Time
LocalDateTime dateTime = LocalDateTime.now();
//2022-02-22T16:00:00
LocalTime date = LocalTime.from(dateTime);
//16:00:00.944884500
//date和time是没有办法转化为LocalDateTime的,因为缺少信息(除非传入的对象既可以转化为date也可以转化为time,这是博主还不知道的例外情况)
//data对象补全time合成dateTime
LocalDate date = LocalDate.now();
LocalDateTime dateTime = date.atTime(10, 10, 10);
//2022-01-01T10:10:10
//time对象补全data合成datetime
LocalTime time = LocalTime.now();
LocalDateTime dateTime1 = time.atDate(LocalDate.of(2022,2,22));
//2022-02-22T10:10:10
//但是OffsetDateTime和ZonedDateTime携带的信息比LocalDateTime还要详细,所以可以向下转换为LocalDateTime
//实例3:ZonedDateTime转LocalDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.now();
LocalDateTime from = LocalDateTime.from(zonedDateTime);
时间类的都实现了接口Temporal(它继承了TemporalAccessor),所以它们都实现了四种可以生成自己的工厂方法:from,now,of,parse
1.2 口语化时间的方法
所谓口语化时间,这是我自己想出来的,因为实在想不到用什么词了,大体意思就是,我可以获取时间中的年、月、日、时、分、秒、周几。
//1.获取年:
LocalDateTime now = LocalDateTime.now();
System.out.println(now.getYear());
//2022
//2.获取月
LocalDateTime now = LocalDateTime.now();
System.out.println(now.getMonth());
//MARCH
System.out.println(now.getMonth());
//3
//3.来点特别的,今年的第几天
LocalDateTime now = LocalDateTime.now();
System.out.println(now.getDayOfYear());
//77,今天是2022年的3月18日
//4.这个月的第几天
System.out.println(now.getDayOfMonth());
//18
//5.今天是本周几
System.out.println(now.getDayOfWeek());
//FRIDAY
//6.ChronoField 枚举来指定获取的信息
System.out.println(now.get(ChronoField.DAY_OF_MONTH));
//3
我们能从LocalDateTime 中获取如此多的信息,除此之外我们还能获得当前的时分秒,纳秒,如果是LocalTime和LocalDate,它们只能获得自己相应的部分,例如LocalTime只能知道当前的时分秒,而不能知道当前是本月的第几天。
最后,ChronoField枚举类是非常重要的时间API枚举类之一,我们会在之后的with方法中再次遇见它。
1.3 时间计算的方法
本小节介绍时间的修改,时间的计算,那么我们来了解下
1).时间的加减
//当前时间:2022-02-12 11:32:35
//1.通过ChronoUnit枚举来演示 时间加法
LocalDateTime date1 = now.plus(6, ChronoUnit.DAYS);
//2022-02-18 11:32:35
//2.通过ChronoUnit枚举来演示 时间减法
LocalDateTime date2 = now.minus(1,ChronoUnit.MONTHS);
//2022-01-12 11:32:35
//3.直接调用的月份减法,当然还有减去日,减去秒等等,不重复演示
LocalDateTime date3 = now.minusMonths(1);
//2022-01-12 11:32:35
//4.加上一段时期,Preiod.of([年],[月],[日])
Period period = Period.of(1, 0, 0);
LocalDateTime date1 = now.plus(period);
//2023-02-12 11:32:35
//5.一个小补充,两个时间之间的加减演示,得到两个时间之间相差多少天
LocalDateTime dateTime1 = LocalDateTime.now();
LocalDateTime dateTime2 = LocalDateTime.now().plusDays(10);
//当前时间加10天
long days = dateTime1.until(dateTime2, ChronoUnit.DAYS);
//10
//之后我们还会接触到两种可以得到时间差额的方法
时间加减方法可以传入一个Period对象来表示加上/减少多少时间之后我们会介绍到它。现在我们通过 ChronoUnit 枚举 来表示对该时间的操控,最简单的还是直接使用minusDay、plusHours这些方法,从名字上就能表达出你需要对时间做什么。
2.时间的修改
//实例1:修改年份
LocalDateTime dateTime2 = dateTime1.withYear(2010);
//2010-01-11T10:20:30
//实例2:修改月份
LocalDateTime dateTime2 = dateTime1.withDayOfMonth(10);
//2022-10-11T10:20:30
//实例3:通过ChronoField枚举修改,可玩性更高!
LocalDateTime dateTime2 = dateTime1.with(ChronoField.DAY_OF_MONTH,11);
//2022-01-11T10:20:30
是原本的对象并不会被修改,它会创造一个副本,也就是原本对象的修改版! 同样的,再次强调唯二的两个时间枚举工具 ChronoField 和 ChronoUnit
3.时区偏移
时区是按照一定的规则将区域划分成的标准时间相同的区间。在 ZoneRules 这个类中包含 了 40 个这样的实例。你可以简单地通过调用 ZoneId 的 getRules()得到指定时区的规则。每个特定的 ZoneId 对象都由一个地区 ID 标识,比如:
ZoneId romeZone = ZoneId.of("Asia/Shanghai");
记得我们之前说过date和不能转化为dateTime么?现在添加时区后它就变成更加详细的ZonedDateTime!
ZoneId romeZone = ZoneId.of("Asia/Shanghai");
//时区建立好了!
//LocalDate转ZonedDateTime
LocalDate date = LocalDate.of(2014, Month.MARCH, 18);
ZonedDateTime zdt1 = date.atStartOfDay(romeZone);
//2014-03-18T00:00+08:00[Asia/Shanghai]
//LocalDateTime转ZonedDateTime
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
ZonedDateTime zdt2 = dateTime.atZone(romeZone);
//2014-03-18T13:45+08:00[Asia/Shanghai]
//Instant转ZonedDateTime
Instant instant = Instant.now();
ZonedDateTime zdt3 = instant.atZone(romeZone);
//2022-02-12T15:33:43.468020900+08:00[Asia/Shanghai]
这种方式是通过ZoneId定义的地区名称来进行时区偏移:
但是如果说我们不知道当前的时区属于何种时区该怎么办?
我们要使用数字的方式来进行时区偏差:
ZoneOffset shanghai = ZoneOffset.of("+08:00");
//上海,北京时间偏差+8
LocalDateTime dateTime1 = LocalDateTime.ofInstant(Instant.now(), shanghai);
//还不清楚Instant是什么?别担心,第二节就会介绍它,它其实就代表伦敦当地时间,时区是+00:00
最后,就是时间格式化输出成字符串,所有的功课都掌握好了,相信你也可以随心所欲的操纵全新的时间API了,那么输出成字符串,在页面上展现我们的成果:
//实例1:自定义格式化输出形式
DateTimeFormatter date = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//自定义建立格式化输出形式
String format = LocalDateTime.now().format(formatter);
System.out.println(format);
//2022-03-18 20:19:02
//实例2:JDK原生时间格式化形式
String format = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
System.out.println(format);
//2022-03-18T20:20:53.0526567
String format = LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(format);
//20220318 (这种格式似乎不是给人类看的)
//实例3:(复杂的)高细粒度 时间格式化
DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder()
.appendText(ChronoField.YEAR)
.appendLiteral("年")
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendLiteral("月")
.appendText(ChronoField.DAY_OF_MONTH)
.appendLiteral("日 ")
.appendText(ChronoField.HOUR_OF_DAY)
.appendLiteral("点")
.appendText(ChronoField.MINUTE_OF_HOUR)
.appendLiteral("分")
.appendText(ChronoField.SECOND_OF_MINUTE)
.appendLiteral("秒")
.parseCaseInsensitive()
.toFormatter();
String format = LocalDateTime.now().format(italianFormatter);
//2022年02月22日 22点22分22秒
第二节:旧API过渡
Java最讲究的就是向前兼容了,不然JDK1.8 之前的Java代码可能就无法使用或者没办法互相调用了!别担心,Java还是留有让我们从旧时代过渡到新时代的路子的!
1.Instant
LocalDateTime 和 Instant 是为不同的目的而设计的,一个是为了便于人阅读使用, 另一个是为了便于机器处理,因此不能将二者混用。
Instant和LocalDateTime、LocalDate、LocalTime等一样,都继承了Temporal,所以它也有from,parse,now方法,但是没有format方法,它可以帮助我们从旧API:java.util.Date来过渡到我们崭新的时代:
Date date = new Date();
//假设获取了一个Date对象
Instant instant = Instant.ofEpochMilli(date.getTime());
//将Date转化为纳秒形式注入到Instant中
ZoneId zoneId = TimeZone.getDefault().toZoneId();
//将旧时区转化为新时区
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, zoneId);
//给机器阅读的时间 转化 为给人类阅读的时间
System.out.println(dateTime);
//2022-03-18T21:11:36.938
2. 时间间隔对象:Duration和Period
我们先了解下这两个对象,这两者都可以运用于时间相隔运算,它们都有between方法,但是不同的是:
Duration 类主要用于以秒和纳秒衡量时间的长短,可以得到两个时间相差多少秒,时,分,天等,也可以在此基础上加上\减去一定的时间,获取它的信息需要使用to方法来转化
Period 类主要是年月日之间的时间值它通过get方法获得年月日
LocalDateTime now1 = LocalDateTime.now();
LocalDateTime now2 = now1.plusDays(10);
//在now2的基础上又加了10天
Duration between = Duration.between(now1, now2);
System.out.println(between.minusDays(1).toDays());
//计算两个时间之间相隔多少天,减去1天获取结果:9
Period between1 = Period.between(now1.toLocalDate(), now2.toLocalDate());
System.out.println(between1.plusDays(10).getDays());
//计算两个时间之间相隔多少天,再加上10天:20
第三节:总结
我们介绍了 时间API通过实现父类Temporal(继承TemporalAccessor)来实现 对时间的操纵:
时间类通用方法
方法 |
静态方法 |
方法描述 |
返回值 |
from |
yes |
传入Temporal对象创建对象实例 |
Temporal |
now |
yes |
依据系统时间创建Temporal对象 |
Temporal |
of |
yes |
传入Temporal对象的部分创建Temporal |
Temporal |
parse |
yes |
传入字符串创建Temporal对象 |
Temporal |
atOffset |
no |
Temporal时区偏移 |
Temporal |
atZone |
no |
Temporal时区设定 |
Temporal |
format |
no |
Temporal格式化输出 |
String |
get |
no |
读取Temporal部分值 |
int |
minus |
no |
Temporal减去一定的时长 |
Temporal |
plus |
no |
Temporal加上一定的时长 |
Temporal |
with |
no |
返回Temporal修改后的副本 |
Temporal |
而时间间隔对象 Duration 和 Period 来对时间对象的计算进行补全:
时间间隔通用方法
方法 |
静态方法 |
方法描述 |
返回值 |
between |
yes |
创建两个时间点的时间间隔 |
interval |
from |
yes |
由一个临时时间点创建时间间隔l |
interval |
of |
yes |
由它组成部分创建时间间隔 |
interval |
parse |
yes |
由字符串创建时间间隔 |
interval |
addTo |
no |
时间间隔叠加到temporal上 |
temporal |
get |
no |
读取时间间隔状态 |
Long |
isNegative |
no |
时间间隔是否为负值 |
boolean |
isZero |
no |
时间间隔是否为0 |
boolean |
minus |
no |
时间间隔之间相减 |
interval |
multipliedBy |
no |
时间间隔乘以某个量标 |
interval |
negated |
no |
忽略某个时长 |
interval |
plus |
no |
时间间隔之间相加 |
interval |
subtractFrom |
no |
temporal减去该时间间隔 |
Temporal |
通过时间间隔,我们可以知道两个时间之间差额,更有利于我们的计算!
标签:10,Java,Temporal,第三版,API,时间,2022,LocalDateTime,now 来源: https://www.cnblogs.com/dingcx817/p/16023666.html