APP下载

完美解决日期和时间缺陷:Java8新特性之日期和时间API

消息来源:baojiabao.com 作者: 发布时间:2024-05-15

报价宝综合消息完美解决日期和时间缺陷:Java8新特性之日期和时间API

一、什么是Java8日期和时间API

Java 8 Date Time API是JSR-310实现。它旨在克服传统日期时间实现中的所有缺陷。新Date Time API的设计原则是:

1、不可变性

新Date Time API中的所有类都是不可变的,适用于多执行绪环境。

2、关注点分离

新API明确区分人类可读日期时间和机器时间(unix时间戳)。它为Date、Time、DateTime、Timestamp、Timezone等定义了单独的类。

3、清晰度

方法明确定义并在所有类中执行相同的操作。例如,要获取当前例项,我们有now方法。在所有这些类中定义了format和parse方法,而不是为它们设定单独的类。

所有类都使用工厂模式和策略模式来更好地处理。一旦你在其中一个类中使用了这些方法,使用其他类并不难。

4、容易使用

所有新的Date Time API类都带有执行常见任务的方法,例如加号、减号、格式、解析,在日期/时间中获取单独的部分等。

5、可扩充套件

新的Date Time API适用于ISO-8601日历系统,但我们也可以将其与其他非ISO日历一起使用。

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

Java8之前的日期和时间相关类存在一些问题:

1、没有统一定义

在java.util和java.sql包中都有Date类,格式化和解析类又再次定义在java.text包中。

2、java.sql.Date设计糟糕

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

3、定义不完整

时间,时间戳,格式和解析没有明确定义的类。通常用SimpleDateFormat类用于解析和格式化。

4、非执行绪安全

所有Date类都是可变的,因此它们不是执行绪安全的。 这是Java Date和Calendar类最大的问题之一。

5、没有合理的国际化和时区支援

日期类不提供国际化,没有时区支援。 因此引入了java.util.Calendar和java.util.TimeZone类,但它们也具有上面列出的所有问题。

三、如何使用新的日期时间API

1、LocalDate

LocalDate是一个不可变类,它表示预设格式为yyyy-MM-dd的Date。

我们可以使用now方法获取当前日期。

我们还可以提供年,月和日的输入引数来建立LocalDate例项。

此类为now提供过载方法,我们可以通过ZoneId获取特定时区的日期。

该类提供与java.sql.Date相同的功能。

示例程式码如下:

//当前日期

LocalDate today = LocalDate.now();

System.out.println("Current Date=" + today);

//通过输入引数建立日期

LocalDate firstDay_2019 = LocalDate.of(2019, Month.JANUARY, 1);

System.out.println("Specific Date=" + firstDay_2019);

//通过ZoneId建立日期

LocalDate todayShanghai = LocalDate.now(ZoneId.of("Asia/Shanghai"));

System.out.println("Current Date in IST=" + todayShanghai);

//从基准日期开始建立日期

LocalDate dateFromBase = LocalDate.ofEpochDay(365);

System.out.println("365th day from base date= " + dateFromBase);

LocalDate hundredDay2019 = LocalDate.ofYearDay(2019, 100);

System.out.println("100th day of 2014=" + hundredDay2019);

2、LocalTime

LocalTime是一个不可变类,其例项表示人类可读格式的时间。 它的预设格式是hh:mm:ss.zzz。 就像LocalDate一样,这个类通过传递小时,分钟和秒作为输入引数来提供时区支援和建立例项。

示例程式码如下:

//当前时间

LocalTime time = LocalTime.now();

System.out.println("Current Time=" + time);

//通过输入引数建立时间

LocalTime specificTime = LocalTime.of(12, 20, 25, 40);

System.out.println("Specific Time of Day=" + specificTime);

//通过ZoneId建立时间

LocalTime timeShanghai = LocalTime.now(ZoneId.of("Asia/Shanghai"));

System.out.println("Current Time in IST=" + timeShanghai);

//通过基准日期建立时间

LocalTime specificSecondTime = LocalTime.ofSecondOfDay(10000);

System.out.println("10000th second time= " + specificSecondTime);

3、LocalDateTime

LocalDateTime是一个不可变的日期时间物件,表示日期时间,预设格式为yyyy-MM-dd-HH-mm-ss.zzz。 它提供了一个工厂方法,该方法使用LocalDate和LocalTime输入引数来建立LocalDateTime例项。

示例程式码如下:

//当前日期

LocalDateTime today = LocalDateTime.now();

System.out.println("Current DateTime=" + today);

//通过LocalDate和LocalTime建立日期

today = LocalDateTime.of(LocalDate.now(), LocalTime.now());

System.out.println("Current DateTime=" + today);

//通过输入引数建立日期

LocalDateTime specificDate = LocalDateTime.of(2019, Month.JANUARY, 1, 10, 10, 30);

System.out.println("Specific Date=" + specificDate);

//通过ZoneId建立日期

LocalDateTime todayShanghai = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));

System.out.println("Current Date in IST=" + todayShanghai);

//通过基准日期建立日期

LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC);

System.out.println("10000th second time from 01/01/1970= " + dateFromBase);

4、Instant

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

示例程式码如下:

//当前时间戳

Instant timestamp = Instant.now();

System.out.println("Current Timestamp = " + timestamp);

//通过timestamp建立

Instant specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli());

System.out.println("Specific Time = " + specificTime);

//建立Duration

Duration thirtyDay = Duration.ofDays(30);

System.out.println(thirtyDay);

5、日期工具类

大多数日期时间类提供各种实用方法,例如加/减天,周,月等。

示例程式码如下:

LocalDate today = LocalDate.now();

//判断是否是闰年

System.out.println("Year " + today.getYear() + " is Leap Year? " + today.isLeapYear());

//比较日期

System.out.println("Today is before 01/01/2015? " + today.isBefore(LocalDate.of(2015, 1, 1)));

//通过LocalTime建立LocalDateTime

System.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());

6、日期解析和格式化

将日期格式化为不同格式然后解析String以获取Date Time物件是很常见的。

示例程式码如下:

//预设日期格式

LocalDate date = LocalDate.now();

System.out.println("Default format of LocalDate=" + date);

//指定日期格式

System.out.println(date.format(DateTimeFormatter.ofPattern("d::MMM::uuuu")));

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("d::MMM::uuuu HH::mm::ss")));

System.out.println(dateTime.format(DateTimeFormatter.BASIC_ISO_DATE));

//预设Instant格式

Instant timestamp = Instant.now();

System.out.println("Default format of Instant=" + timestamp);

//字串解析

LocalDateTime dt = LocalDateTime.parse("27::Apr::2019 21::39::48",

DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss"));

System.out.println("Default format after parsing = " + dt);

7、旧版日期时间支援

//java.util.Date转Instant

Instant timestamp = new Date().toInstant();

LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.of(ZoneId.SHORT_IDS.get("PST")));

System.out.println("Date = " + date);

//java.util.Date转Instant

Instant time = Calendar.getInstance().toInstant();

System.out.println(time);

//java.util.TimeZone转ZoneId

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

System.out.println(defaultZone);

//GregorianCalendar转ZonedDateTime

ZonedDateTime gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime();

System.out.println(gregorianCalendarDateTime);

//Instant转java.util.Date

Date dt = Date.from(Instant.now());

System.out.println(dt);

//ZoneId转java.util.TimeZone

TimeZone tz = TimeZone.getTimeZone(defaultZone);

System.out.println(tz);

//ZonedDateTime转GregorianCalendar

GregorianCalendar gc = GregorianCalendar.from(gregorianCalendarDateTime);

System.out.println(gc);

一些最常用的类将是LocalDate和LocalDateTime。 它非常容易使用,可以让你轻松找到对应的方法去完成特定的工作。

将遗留类迁移到新的Date Time类需要一些时间,但它非常值得。

2019-09-22 22:54:00

相关文章