JDK8新特性:新日期时间API全面学习

旧版jdk对时间和日期的设计非常差

1、设计不合理 在java.util和Java.sql 包中都有日期类,java.util.Data同时包含日期和时间 而Java.sql.Date仅仅包含日期 此外用于格式化和解析的类在java.text包下 new Date()年份从1900算起

2、非线程安全 所有的日期类都是可变的 这是Java日期类最大的问题之一 用SimpleFormatter在多线程格式化时会出现问题

3、时区处理麻烦 日期类并不提供国际化 没有时区支持

新的日期API

JDK 8中增加了一套全新的日期时间API,这套API设计合理,是线程安全的。新的日期及时间API位于java.time包中,下面是一些关键类。

LocalDate表示日期,包含年月日,格式为2019-10-16
LocalTime表示时间,包含时分秒,格式为16:38:54.158549300
LocalDateTime表示日期时间,包含年月日,时分秒,格式为2018-09-06T15:33:56.750
DateTimeFormatter日期时间格式化类。
lnstant时间戳,表示一个特定的时间瞬间。
Duration用于计算2个时间(LocalTime,时分秒)的距离
Period用于计算2个日期(LocalDate,年月日)的距离
ZonedDateTime包含时区的时间

Java中使用的历法是ISO8601日历系统,它是世界民用历法,也就是我们所说的公历。

平年有365天,闰年是366天。此外Java8还提供了4套其他历法,分别是:

        ThaiBuddhistDate:泰国佛教历

        MinguoDate:中华民国历

        JapaneseDate:日本历

        HijrahDate:伊斯兰历

正文将通过对这8个类的详细使用介绍来学习新日期时间API的用法

1、LocalDate:

初始化日期:

  • 创建指定日期 localDate.of(int,int,int)

LocalDate date = LocalDate.of(2022,12,5);
System.out.println("date = " + date);
//sout: date = 2022-12-05
  • 获取当前日期 LocalDate.now()

LocalDate now = LocalDate.now();
System.out.println("now = " + now);
//sout: now = 2022-06-18
  • 获取日期信息

LocalDate date = LocalDate.of(2022,12,5);
​
int year = date.getYear(); 
// 得到年份:year = 2022
Month month = date.getMonth(); 
// 得到月份 month = DECEMBER(Month是枚举类型 获取数值可通过getValue )
int monthGetValue = date.getMonth().getValue();
// 得到月份 monthGetValue = 12
int monthValue = date.getMonthValue(); 
// 得到月份 monthValue = 12 相当于date.getMonth().getValue();
int dayOfYear = date.getDayOfYear(); 
// 得到一天在该年中的第多少天 dayOfYear = 339
int dayOfMonth = date.getDayOfMonth(); 
// 得到一天在月中的第多少天 dayOfMonth = 5 也就是经常说的几号
DayOfWeek dayOfWeek = date.getDayOfWeek(); 
// 得到星期 dayOfWeek = MONDAY(DayOfWeek 是枚举类型 获取数值可通过getValue)
int dayOfWeekGetValue = date.getDayOfWeek().getValue(); 
// 得到一天在改星期的第多少天 dayOfWeekGetValue = 1 也就是常说的礼拜几

2、LocalTime

  • 获取指定时间

LocalTime localTime = LocalTime.of(10, 30, 59);
System.out.println("localTime = " + localTime);
//sout: localTime = 10:30:59
  • 获取当前时间

LocalTime now = LocalTime.now();
System.out.println("now = " + now);
//sout: now = 10:04:49.918
  • 获取时间信息

LocalTime localTime = LocalTime.of(10, 30, 59);
​
int hour = localTime.getHour();
// hour = 10
int minute = localTime.getMinute();
// minute = 30
int second = localTime.getSecond();
// second = 59
int nano = localTime.getNano();
// nano = 1120 返回纳秒级字段。此方法返回一个介于0到999,999,999之间的整数值,即一秒的纳秒数

3、LocalDateTime

  • 获取指定日期时间

LocalDateTime localDateTime = LocalDateTime.of(2022, 6, 18, 10, 16, 55);
System.out.println("localDateTime = " + localDateTime);
//sout: localDateTime = 2022-06-18T10:16:55
  • 获取当前日期时间

LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
//sout: now = 2022-06-18T10:19:43.398
  • 获取日期时间信息

和LocalDate获取日期 LocalTime获取时间用法一致,可想像成两个的结合体

LocalDateTime now = LocalDateTime.now();
System.out.println("年:" + now.getYear());
System.out.println("月:" + now.getMonthValue());
System.out.println("日:" + now.getDayOfMonth());
System.out.println("时:" + now.getHour());
System.out.println("分:" + now.getMinute());
System.out.println("秒:" + now.getSecond());
/*
年:2022
月:6
日:18
时:10
分:41
秒:46
  • 修改日期时间

    对日期时间的修改,对已存在的LocalDateTime对象 按照原来的模板创建新的对象 并不会修改原来的日期对象

    with-- 对某个值进行修改(替换)

    withYear(int year);

    withMonth(int month);

    withDayOfMonth(int dayOfMonth);

    withDayOfYear(int dayOfYear);

    withHour(int hour);

    withMinute(int minute);

    withSecond(int second);

    withNano(int nanoOfSecond)

    LocalDateTime now = LocalDateTime.now();
    System.out.println("年:" + now.getYear());  // 年:2022
    System.out.println("now = " + now);         // now = 2022-06-18T11:06:20.318
    LocalDateTime localDateTime1 = now.withYear(1998);
    System.out.println("localDateTime1 = " + localDateTime1);
    //localDateTime1 = 1998-06-18T11:04:56.474
    System.out.println("年:" + localDateTime1.getYear());  // 年:1998

    plus-- 对某个值进行增加

    plusYears(long years);

    plusMonths(long months);

    plusWeeks(long weeks);

    plusDays(long days);

    plusHours(long hours);

    plusMinutes(long minutes);

    plusSeconds(long seconds);

    plusNanos(long nanos);

    LocalDateTime now = LocalDateTime.now();
    System.out.println("年:" + now.getYear());
    LocalDateTime localDateTime = now.plusYears(1);
    System.out.println("年:" + localDateTime.getYear());
    
        
    /*
    年:2022
    年:2023

    minus-- 对某个值进行减少

    方法和用法跟plus如出一辙

  • 日期时间的比较

    boolean isAfter(ChronoLocalDateTime<?> other) 是否在参数日期时间之后

    boolean isBefore(ChronoLocalDateTime<?> other) 是否在参数日期时间之前

    boolean isEqual(ChronoLocalDateTime<?> other) 是否等于参数日期时间

    LocalDateTime now = LocalDateTime.now();
    LocalDateTime plusDays = now.plusDays(1);
    LocalDateTime minusDays = now.minusDays(1);
    ​
    boolean after = plusDays.isAfter(now);
    System.out.println("after = " + after);
    // after = true
    boolean before = minusDays.isBefore(now);
    System.out.println("before = " + before);
    // before = true
    boolean equal = plusDays.isEqual(minusDays);
    System.out.println("equal = " + equal);
    // equal = false

4、格式化和解析操作

在jdk8中我们可以通过java.time.format.DateTimeFormatter 类可以进行日期的解析和格式化操作

格式化输出 String format(DateTimeFormatter formatter)

LocalDateTime now = LocalDateTime.now();
// 指定格式
DateTimeFormatter isoLocalDateTime = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String format = now.format(isoLocalDateTime);
System.out.println("format = " + format);
//sout: format = 2022-06-18T14:04:43.506
// 自定义格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String s = now.format(dateTimeFormatter);
System.out.println("s = " + s);
//sout: s = 2022-06-18 14:04:43

字符串解析成日期对象

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 
LocalDateTime parse = LocalDateTime.parse("2022-05-20 22:20:20", dateTimeFormatter);
System.out.println("parse = " + parse);
// sout:parse = 2022-05-20T22:20:20

5、Instant类

在jdk8中新增一个Instant类 (时间戳) 1970-1-1 00:00:00 以来和秒数或者纳秒数

Instant now = Instant.now();
System.out.println("now = " + now);
// sout:now = 2022-06-18T06:19:50.220Z
​
// 获取从1970-1-1 00:00:00到现在的秒
long epochSecond = now.getEpochSecond();
System.out.println("epochSecond = " + epochSecond);
// sout:epochSecond = 1655533190
Thread.sleep(5000);
Instant after = Instant.now();
System.out.println("间隔时间 = " + (after.getEpochSecond() - now.getEpochSecond()));
// sout: 间隔时间 = 5

6、计算日期时间差

JDK8中提供两个工具类Duration、Period 来计算时间差

  1. Duration 用来计算两个时间差 (LocalTime)Duration between(Temporal startInclusive, Temporal endExclusive)

  2. Period 用来计算两个日期差(LocalDate) Period between(LocalDate startDateInclusive, LocalDate endDateExclusive)

// 通过Duration来计算时间差
LocalTime now = LocalTime.now();
LocalTime plusHours = now.plusHours(1).plusMinutes(12).plusSeconds(33);
Duration duration = Duration.between(now, plusHours);
System.out.println("duration = " + duration.toHours()+"小时"+duration.toMinutes()+"分钟"+duration.toMillis()+"秒");
// sout: duration = 1小时72分钟4353000秒
​
// 通过Period来计算日期差
LocalDate nowDate = LocalDate.now();
LocalDate date = LocalDate.of(2022, 10, 12);
Period between = Period.between(nowDate, date);
System.out.println("period = " + between.getYears()+"年"+between.getMonths()+"月"+between.getDays()+"日");
// sout:period = 0年3月24日

7、时间矫正器

TemporalAdjuster类是一个函数式接口,提供了一个抽象方法adjustInto 该方法被多个类实现 每个实现类下也有不同的操作 本文就不作详细展开了

LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
// sout: now = 2022-06-18T15:17:13.481
TemporalAdjuster adjuster = t -> t.plus(Period.ofDays(1)); // 加一天
LocalDateTime with1 = now.with(adjuster);
System.out.println("with1 = " + with1);
// sout: with1 = 2022-06-19T15:17:13.481
​
TemporalAdjuster adjuster1 = (temporal)->{
LocalDateTime dateTime = (LocalDateTime) temporal;
LocalDateTime localDateTime = dateTime.plusMonths(1).withDayOfMonth(1); //下个月第一天
return localDateTime;
};
LocalDateTime with = now.with(adjuster1);
System.out.println("with = " + with);
// sout: with = 2022-07-01T15:17:13.481

TemporalAdjusters类中预定义实现

TemporalAdjusters类有很多预定义的static方法返回TemporalAdjuster对象,使用不同方式调节Temporal对象而与Temporal实现无关。

dayOfWeekInMonth(2,DayOfWeek.TUESDAY)  一周中的某一天,例如,三月中第二个星期二
firstDayOfMonth()  当前月的第一天
firstDayOfNextMonth() 下一个月的第一天
firstDayOfNextYear()  下一年的第一天
firstDayOfYear()  当年的第一天
lastDayOfMonth()  当月的最后一天
lastDayOfYear()  当年的最后一天
​
previous(DayOfWeek.MONDAY) 上周周一
previousOrSame(DayOfWeek.MONDAY) 上周或当天发生的一周中的周一
next(DayOfWeek.MONDAY) 下周周一
nextOrSame(DayOfWeek.MONDAY)  下周或当天发生的一周中的周一

8、日期时间的时区

JDK8中加入了对时区的支持,LocalDate、LocalTime、LocalDateTime 是不带时区的,带时区的日期时间类型分别是 ZoneDate、ZoneTime、ZoneDateTime。

其中每个时区都对应着不同的ID ID的格式为“区域、城市” 例如 Asia/ShangHai等

ZoneId : 该类中包含了所有的时区信息

// 获取所有的时区id
ZoneId.getAvailableZoneIds().forEach(s->{
    if (s.contains("Shang")){
        System.out.println("s = " + s);
    }
});
​
// 获取当前时间 中国使用的 东八区的时区 比标准时间早8小时
LocalDateTime now = LocalDateTime.now();
System.out.println("now = " + now);
​
// 获取标准时间
ZonedDateTime zonedDateTime = ZonedDateTime.now(Clock.systemUTC());
System.out.println("标准时区时间 = " + zonedDateTime);
​
// 使用计算机默认的时区 创建日期时间
ZonedDateTime zonedDateTime1 = ZonedDateTime.now();
System.out.println("默认时区时间 = " + zonedDateTime1);
​
// 使用指定的时区创建日期时间
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("America/Marigot"));
System.out.println("自定义时区时间 = " + zonedDateTime2);
s = Asia/Shanghai
now = 2022-06-18T16:24:34.836
标准时区时间 = 2022-06-18T08:24:34.836Z
默认时区时间 = 2022-06-18T16:24:34.836+08:00[Asia/Shanghai]
自定义时区时间 = 2022-06-18T04:24:34.836-04:00[America/Marigot]

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值