Java8新特性的日期时间Api


为什么使用JDK8新特性日期时间?

JDK8之前的System.currentTimeMillis()、Date、Calender日期,它们面临的问题是:

  • 可变性:像日期和时间这样的类应该是不可变的
  • 偏移性:Date中的年份是从1900开始,而月份都是从0开始
  • 格式化:格式化只对Date有用,Calender则不行
  • 线程不安全
  • 不能处理闰秒

新日期类

Java8吸收了Joda-Time的精华,以一个新的开始为Java创建优秀的API。新的java.time中包含了所有关于LocalDate、LocalTime、LocalDateTime、ZonedDateTime和Duration类。

  • LocalDate:代表IOS格式(yyyy-MM-dd)的日期。
  • LocalTime:表示一个时间,而不是日期。
  • LocalDateTime:是用来表示日期和时间。

Date类新增了toInstant()方法,用于把Date转换成新的表示形式。

新日期类和Date的区别?
LocalDate、LocalTime、LocalDateTime类它们的实例是不可变的对象(final修饰类),分别表示使用ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前时间信息,也不包含与时区相关的信息。

ps:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。

Date转新日期类

//Date转Instant
Instant instant = new Date().toInstant();

//Date转LocalDate
Instant instant = new Date().toInstant();
LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();

//Date转LocalDateTime
Instant instant = new Date().toInstant();
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

新日期类转Date

//Instant转Date
Date date= Date.from(Instant.now());

//LocalDate转Date
Instant instant = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant();
Date date= Date.from(instant);

//LocalDateTime转Date
Instant instant = LocalDateTime.now().toInstant(ZoneOffset.of("+8"));
Instant instant = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
Date date = Date.from(instant);

新日期格式化

java.time.format.DateTimeFormmatter类提供了三种格式化方法:

  • 预定义的标准格式,如:ISO_LOCAL_DATE_TIME
  • 本地化相关的格式,如:ofLocalizedDateTime(FormatStyle.LONG)
  • 自定义的格式,如:ofPattern(“yyyy-MM-dd”)

常用方法:

  • ofPattern(String pattern):静态方法,返回一个指定字符串格式的DateTimeFormatter
  • format(TemporalAccessor t):格式化一个日期、时间、返回字符串
  • parse(CharSequence text):将指定格式的字符序列解析为一个日期、时间

日期格式化

  1. yyyy-MM-dd格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String localDateStr = formatter.format(LocalDate.now());
String localDateTimeStr = formatter.format(LocalDateTime.now());
//Instant不能直接使用DateTimeFormatter格式化,需要先转换成LocalDate和LocalDateTime
String instantStr = formatter.format(Instant.now().atZone(ZoneId.systemDefault()).toLocalDate());
  1. yyyy-MM-dd HH:mm:ss格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//LocalDate不能使用该格式会抛异常,因为没有时分秒
String localDateTimeStr = formatter.format(LocalDateTime.now());
//Instant
String instant = formatter.format(Instant.now().atZone(ZoneId.systemDefault()).toLocalDateTime());

时间差计算

Period类

@Test
public void test() {
    LocalDate bgnDate = LocalDate.of(2020, 10, 10);
    LocalDate endDate = LocalDate.of(2022, 5, 5);
    Period period = Period.between(bgnDate, endDate);
    int years = period.getYears();
    int months = period.getMonths();
    int days = period.getDays();
    long totalMonths = period.toTotalMonths();
    System.out.println("总月份:"+totalMonths);
    System.out.println("相差年份:"+years);
    System.out.println("相差月份:"+months);
    System.out.println("相差天数:"+days);
}

运行结果:
在这里插入图片描述
只有满足一年或一个月才算

ps:periodbetween方法实现也是使用LocalDate的untils方法

在这里插入图片描述

Duration类

@Test
public void test() {
	LocalDate bgnDate = LocalDate.of(2020, 10, 10);
	LocalDate endDate = LocalDate.of(2022, 5, 5);
	Duration duration = Duration.between(bgnDate, endDate);
	long toDays = duration.toDays();
	long years = duration.get(ChronoUnit.YEARS);
	long months = duration.get(ChronoUnit.MONTHS);
	long days = duration.get(ChronoUnit.DAYS);
	long weeks = duration.get(ChronoUnit.WEEKS);
}

异常信息:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds

	at java.time.LocalDate.until(LocalDate.java:1614)
	at java.time.Duration.between(Duration.java:475)
	at com.cgws.fintech.fundmall.bizfund.util.DateUtil.test(DateUtil.java:64)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)

异常原因:是因为我between方法入参给的是LocalDate,需要LocalDateTime

异常解决:

@Test
public void test() {
    LocalDate bgnDate = LocalDate.of(2020, 10, 10);
    LocalDateTime bgnTime = bgnDate.atTime(0, 0, 0);
    LocalDate endDate = LocalDate.of(2022, 5, 5);
    LocalDateTime endTime = endDate.atTime(10, 5, 0);
    Duration duration = Duration.between(bgnTime, endTime);
    long toDays = duration.toDays();
    long seconds = duration.get(ChronoUnit.SECONDS);
    System.out.println("相差天数:"+toDays);
    System.out.println("相差秒数:"+seconds);
}

运行结果:
在这里插入图片描述

until方法

@Test
public void test() {
    LocalDate bgnDate = LocalDate.of(2020, 10, 10);
    LocalDate endDate = LocalDate.of(2022, 5, 5);
    long days = bgnDate.until(endDate, ChronoUnit.DAYS);
    long years = bgnDate.until(endDate, ChronoUnit.YEARS);
    long months = bgnDate.until(endDate, ChronoUnit.MONTHS);
    long weeks = bgnDate.until(endDate, ChronoUnit.WEEKS);
    System.out.println("相差年份:"+years);
    System.out.println("相差月份:"+months);
    System.out.println("相差天数:"+days);
    System.out.println("相差周期:"+weeks);
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值