当前位置:首页 > 文章 > 正文内容

Java 8 Time API

廖万里2年前 (2022-10-27)文章31468

Java 8 系列文章 持续更新中

日期时间API 也是Java 8重要的更新之一,Java从一开始就缺少一致的日期和时间方法,Java 8 Date Time API是Java核心API的一个非常好的补充。

为什么需要新的日期时间API

Java中现有的与日期和时间相关的类存在一些问题:

  • 日期时间类的定义不一致,在java.utiljava.sql包中都有Date类。同样,格式化和解析类是在java.text包中定义的。

  • java.util.Date同时包含日期和时间值,而java.sql.Date只包含日期值,把它放在java.sql包中是没有意义的。而且这两个类的名称相同,这本身就是一个非常糟糕的设计。

  • 没有为时间、时间戳、格式化和解析明确定义的类。我们有java.text.DateFormat抽象类用于解析和格式化,通常使用SimpleDateFormat类解析和格式化。

  • 所有Date类都是可变的,所以它们不是线程安全的,这也是JavaDateCalendar类最大的问题之一。

  • Date类不提供国际化,不支持时区。虽然引入了java.util.Calendarjava.util.TimeZone,但是它们也存在上面的问题。

DateCalendar类中定义的方法还有一些其他的问题,但是上面的问题清楚地表明,Java中需要一个健壮的日期时间API。这就是为什么 Joda Time 可以成为Java 日期时间高质量的替代品。

Java 8日期时间设计原则

Java 8日期时间API是基于 JSR-310 规范实现的。目的是为了解决遗留日期时间实现中的所有缺陷。新的日期时间API的一些设计原则如下:

  • 不变性:新的日期时间API中的所有类都是不可变的,适用于多线程环境。

  • 关注点分离:新的日期时间API明确区分了人类可读的日期、时间和机器时间(Unix时间戳),它为DateTimeDateTimeTimestampTimezone 等定义单独的类。

  • 清晰性:所有的类中都清晰地定义了方法,并执行相同的操作。例如,要获取当前时间实例可以用now()方法,在所有这些类中都定义了format()parse()方法,而不是为它们单独定义一个类。

    所有类都使用工厂模式策略模式来更好地操作。一旦您使用了其中一个类中的方法,使用其他类并不困难。

  • 实用的操作:所有新的日期时间API类都常见的方法,比如加、减、格式化、解析、在日期/时间中获取单独的部分等等。

  • 可扩展:新的日期时间API可以在ISO-8601日历系统上工作,但是我们也可以在其他非ISO日历上使用它。

Java 8日期时间API的包

Java8日期时间API由以下包组成。

  • java.time:这是Java 8日期时间API的基本包。所有主要的基类都是这个包的一部分,例如LocalDateLocalTimeLocalDateTimeInstantPeriodDuration等。所有这些类都是不可变的和线程安全的。大多数情况下,这些类足以处理常见的需求。

  • java.time.chrono:这个包为非ISO日历系统定义了通用API。我们可以扩展AbstractChronology类来创建我们自己的日历系统。

  • java.time.format:这个包包含用于格式化和解析日期时间对象的类。大多数时候我们不会直接使用它们,因为java.time包中的日期时间类已经提供了格式化和解析方法。

  • java.time.temporal:这个包包含temporal对象,我们可以使用它来找出与日期/时间对象相关的特定日期或时间。例如,我们可以使用它们来查找一个月的第一天或最后一天。您可以很容易地识别这些方法,因为它们的格式总是withXXX

  • java.time.zone:这个包包含用于支持不同时区及其规则的类。

Java 8日期时间API类的示例

下面通过一些日期时间API类的示例,来更好的了解Java 8日期时间API

1.LocalDate

LocalDate是一个不可变的日期类,它以yyyy-MM-dd的默认格式表示日期。可以使用now()方法来获取当前日期,还可以提供年、月和日期的输入参数来创建LocalDate实例。

这个类为now()提供了一个重载方法,在这里可以传递ZoneId来获取特定时区中的日期。这个类提供了与java.sql.Date相同的功能。

// 当前日期LocalDate today = LocalDate.now();
System.out.println("当前日期=" + today);// 通过提供年月日参数创建日期LocalDate nowYear_1024 = LocalDate.of(2022, Month.OCTOBER, 24);
System.out.println("参数日期=" + nowYear_1024);// 通过时区获取当前日期LocalDate todayShanghai = LocalDate.now(ZoneId.of("Asia/Shanghai"));
System.out.println("当前日期(CTT)=" + todayShanghai);// 从纪元日(1970-01-01)开始的第多少天LocalDate dateFromBase = LocalDate.ofEpochDay(365);
System.out.println("1970-01-01的第365天= " + dateFromBase);// 某年的第多少天LocalDate hundredDay2022 = LocalDate.ofYearDay(2022, 100);
System.out.println("2022年的第100天=" + hundredDay2022);

运行之后结果如下:

当前日期=2022-10-26特殊日期=2022-10-24当前日期(CTT)=2022-10-261970-01-01的第365天= 1971-01-012022年的第100天=2022-04-10

2.LocalTime

LocalTime是一个不可变的时间类,它以HH:mm:ss.SSS的默认格式表示时间。与LocalDate一样,这个类提供了时区支持,并可以通过传递小时、分钟和秒作为输入参数来创建实例。

// 当前时间LocalTime time = LocalTime.now();
System.out.println("当前时间=" + time);// 通过提供时分秒参数创建日期LocalTime specificTime = LocalTime.of(12, 20, 25, 40);
System.out.println("参数时间=" + specificTime);// 通过时区获取当前时间LocalTime timeShanghai = LocalTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println("当前时间(CTT)=" + timeShanghai);// 从纪元日开始的第多少秒LocalTime specificSecondTime = LocalTime.ofSecondOfDay(100);
System.out.println("从纪元日开始的第100秒=" + specificSecondTime);

运行之后结果如下:

当前时间=15:39:18.948参数时间=12:20:25.000000040当前时间(CTT)=15:39:18.949从0开始的第100秒=00:01:40

3.LocalDateTime

LocalDateTime是一个不可变的日期时间类,它以yyyy-MM-ddTHH:mm:ss.SSS的默认格式表示时间日期。它提供了一个工厂方法,该方法使用LocalDateLocalTime作为参数创建LocalDateTime实例。

// 当前日期时间LocalDateTime now = LocalDateTime.now();
System.out.println("当前日期时间=" + now);// 通过提供LocalDate和LocalTime参数创建日期时间now = LocalDateTime.of(LocalDate.now(), LocalTime.now());
System.out.println("当前日期时间=" + now);// 通过提供年月日时分秒参数创建日期时间LocalDateTime specificTime = LocalDateTime.of(2022, Month.OCTOBER, 24, 10, 24, 24);
System.out.println("参数日期时间=" + specificTime);// 通过时区获取当前日期时间LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println("当前日期时间(CTT)=" + todayKolkata);// 从纪元日开始的第多少秒LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(100, 0, ZoneOffset.UTC);
System.out.println("从纪元日开始的第100秒= " + dateFromBase);

运行之后结果如下:

当前日期时间=2022-10-26T15:51:59.070当前日期时间=2022-10-26T15:51:59.071参数日期时间=2022-10-24T10:24:24当前日期时间(CTT)=2022-10-26T15:51:59.071从纪元日开始的第100秒=1970-01-01T00:01:40

注意:以上例子通过输入参数创建实例时,如果输入了无效的参数name将会抛出java.time.DateTimeException

4.Instant

instant类用于处理机器可读的时间格式。instant类将日期时间存储在unix时间戳中。

// 当期时间戳Instant timestamp = Instant.now();
System.out.println("当期时间戳= "+timestamp);// 从纪元日开始的第多少毫秒Instant specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli());
System.out.println("从纪元日开始="+specificTime);

运行之后结果如下:

当期时间戳=2022-10-26T08:08:40.429Z从纪元日开始=2022-10-26T08:08:40.429Z

Java8日期时间API类的实用方法

大多数日期时间类都会提供各种实用方法,例如加/减天数、周数、月数等。还有一些其他实用方法可以使用时间调整器TemporalAdjuster调整日期,并计算两个日期之间的时间段。

LocalDate today = LocalDate.now();//获取年份,判断年份是否是闰年System.out.println("Year "+today.getYear()+" is Leap Year? "+today.isLeapYear());//比较两个时间System.out.println("Today is before 01/01/2023? "+today.isBefore(LocalDate.of(2023,1,1)));//通过LocalDate创建LocalDateTimeSystem.out.println("Current Time="+today.atTime(LocalTime.now()));//加减操作System.out.println("10 days after today will be "+today.plusDays(10));
System.out.println("3 weeks after today will be "+today.plusWeeks(3));
System.out.println("20 months after today will be "+today.plusMonths(20));

System.out.println("10 days before today will be "+today.minusDays(10));
System.out.println("3 weeks before today will be "+today.minusWeeks(3));
System.out.println("20 months before today will be "+today.minusMonths(20));//时间调整器调整时间System.out.println("First date of this month= "+today.with(TemporalAdjusters.firstDayOfMonth()));LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
System.out.println("Last date of this year= "+lastDayOfYear);Period period = today.until(lastDayOfYear);
System.out.println("Period Format= "+period);
System.out.println("Months remaining in the year= "+period.getMonths());

运行之后结果如下:

Year 2022 is Leap Year? falseToday is before 01/01/2023? trueCurrent Time=2022-10-26T16:25:04.74010 days after today will be 2022-11-053 weeks after today will be 2022-11-1620 months after today will be 2024-06-2610 days before today will be 2022-10-163 weeks before today will be 2022-10-0520 months before today will be 2021-02-26First date of this month= 2022-10-01Last date of this year= 2022-12-31Period Format= P2M5D
Months remaining in the year= 2

Java8日期时间的解析和格式化

经常用到的操作有:将日期时间格式化为不同格式String,解析String以获得日期时间对象。

// 格式化LocalDate date = LocalDate.now();// 默认格式System.out.println("Default format of LocalDate=" + date);// 自定义格式System.out.println(date.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE));LocalDateTime dateTime = LocalDateTime.now();// 默认格式System.out.println("Default format of LocalDateTime=" + dateTime);// 自定义格式System.out.println(dateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
System.out.println(dateTime.format(DateTimeFormatter.BASIC_ISO_DATE));Instant timestamp = Instant.now();// 默认格式System.out.println("Default format of Instant=" + timestamp);// 解析LocalDateTime dt = LocalDateTime.parse("2022年10月24日10时24分24秒",
        DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒"));
System.out.println("Default format after parsing = " + dt);

运行之后结果如下:

Default format of LocalDate=2022-10-262022年10月26日20221026Default format of LocalDateTime=2022-10-26T16:37:51.3002022年10月26日16时37分51秒20221026Default format of Instant=2022-10-26T08:37:51.301ZDefault format after parsing = 2022-10-24T10:24:24

对遗留日期时间的支持

遗留日期/时间类几乎在所有应用程序中都使用,因此必须有向下兼容。这就是为什么我们可以通过一些实用方法将遗留类转换为新类,反之亦然。

//Date转InstantInstant timestamp = new Date().toInstant();//Instant转LocalDateTimeLocalDateTime date = LocalDateTime.ofInstant(timestamp,
        ZoneId.of(ZoneId.SHORT_IDS.get("CTT")));
System.out.println("Date = " + date);//Calendar转InstantInstant time = Calendar.getInstance().toInstant();
System.out.println(time);//TimeZone转ZoneIdZoneId defaultZone = TimeZone.getDefault().toZoneId();
System.out.println(defaultZone);//ZonedDateTime from specific CalendarZonedDateTime gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime();
System.out.println(gregorianCalendarDateTime);//Date API to Legacy classesDate dt = Date.from(Instant.now());
System.out.println(dt);TimeZone tz = TimeZone.getTimeZone(defaultZone);
System.out.println(tz);GregorianCalendar gc = GregorianCalendar.from(gregorianCalendarDateTime);
System.out.println(gc);

运行之后结果如下:

Date = 2022-10-26T16:47:38.3292022-10-26T08:47:38.429Z
Asia/Shanghai2022-10-26T16:47:38.455+08:00[Asia/Shanghai]
Wed Oct 26 16:47:38 CST 2022sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=31,lastRule=null]
java.util.GregorianCalendar[time=1666774058455,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=31,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2022,MONTH=9,WEEK_OF_YEAR=43,WEEK_OF_MONTH=4,DAY_OF_MONTH=26,DAY_OF_YEAR=299,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=4,HOUR_OF_DAY=16,MINUTE=47,SECOND=38,MILLISECOND=455,ZONE_OFFSET=28800000,DST_OFFSET=0]

可以看到,遗留的TimeZoneGregorianCalendartoString()方法过于冗长,对用户不友好。


本文链接:https://www.kkkliao.cn/?id=146 转载需授权!

分享到:

添加博主微信共同交流探讨信息差网赚项目: 19528888767 , 请猛戳这里→点我添加

版权声明:本文由廖万里的博客发布,如需转载请注明出处。

“Java 8 Time API” 的相关文章

华为梅开二度:鸿蒙3.0正式版推送+5.5G网络,网友:遥遥领先

华为梅开二度:鸿蒙3.0正式版推送+5.5G网络,网友:遥遥领先

对于华为手机来说,虽然手机业务受到了很大的压力,但是华为在很多领域的表现都不差,无论是汽车领域还是通信领域,都有着不错的市场表现力。而且这几年的华为在技术研发方面的投入资金也不小,这也意味着进步很大。而且从目前的市场角度来看,华为也迎来了梅开二度的情况,不仅针对鸿蒙OS3.0正式版进行了推送和变化,...

骁龙8和骁龙8+的日常体验,到底有多大差距?

骁龙8和骁龙8+的日常体验,到底有多大差距?

机哥写过一篇文章。主要呢,就是盘点了今年那些跳水比较严重的旗舰手机。像什么OPPO Find X5 Pro天玑版啊、小米12 Pro啊、一加10 Pro啊等等。相比起刚上市时定价,现在这些机型,普遍的降价幅度都超过了2000块。原本是卖5000多,现在却只卖3000多。。机哥当时发完文章,底下很大一...

六年前端面试报告

六年前端面试报告

2022.10.20 在当前公司待了两年多,被离职了,拿了点赔偿金继续面试。薪资期望 13-15, 趁着今天1024整理下面试过程。上一次面试我是4年经验,简历也好改,加上两年经验,补上现公司项目就出去找工作了。简历改完后,首先分析下自己现阶段水平,大概能要多少,定一个期望薪资。再就是背面试题了。自...

专访中凝科技90后董事长王天赋:7年打造气凝胶“小巨人”,未来3年冲刺上市

专访中凝科技90后董事长王天赋:7年打造气凝胶“小巨人”,未来3年冲刺上市

本文来源:时代周报 作者:黄嘉祥气凝胶是世界上密度最小的固体,被誉为可以改变世界的多功能新材料,这条超百亿级别的新赛道正在崛起,入局者越来越多。90后“创二代”王天赋正是气凝胶赛道的创业者之一,他在2015年创办了深圳中凝科技有限公司(下称“中凝科技”),带领团队研制气凝胶,在全球首创气凝胶无氯常压...

腾讯突然宣布关闭这项业务,阿里巴巴和百度还能做什么?

腾讯突然宣布关闭这项业务,阿里巴巴和百度还能做什么?

腾讯地图官网近日宣布,电脑端的腾讯地图将于11月11日停止服务,用户可以下载腾讯地图App。今年5月,搜狗地图也暂停了电脑端的服务,如今仅剩百度地图一家仍旧提供电脑端服务。这一变化,与移动互联网的发展不无关系。虽然电脑端地图服务商缩水,但在移动端,背靠阿里巴巴的高德地图、百度的重要业务板块百度地图,...

小米12SPro深度体验评测,什么叫“水 桶 旗 舰”啊?

小米12SPro深度体验评测,什么叫“水 桶 旗 舰”啊?

首先,依然是祖传一句话评价:补齐了唯一短板的水桶旗舰。其实就像年初的时候评价小米12Pro一样,今年的12系列看得出小米是在努力的优化体验,而不是单纯的堆叠参数,所以更注重手感的12和12S,以及徕卡加持下算法提升、影调有明显改善的小米12S Ultra便应运而生,至于今年的12Pro和12S Pr...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。