您的位置 首页 java

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

一、什么是 java 8日期和时间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 today Shanghai  = 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类需要一些时间,但它非常值得。

文章来源:智云一二三科技

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

文章地址:https://www.zhihuclub.com/180280.shtml

关于作者: 智云科技

热门文章

网站地图