Java 8 日期与时间类
本文介绍 Java 中旧日期类型以及 JDK 8 增加的 LocalDate、LocalDateTime 等新时间类型的使用

# Java 8 日期与时间类

# 传统时间 API

# Date 类

  1. Date 类在 Java 面世之初就存在于标准库中,但从 Java 1.1 开始,Date 类的所有方法都被弃用

  2. 使用示例

    // 获取当前时间,toString: Wed Jan 01 00:00:00 CST 2020
    Date date = new Date(); 
    // 对应的时间戳,long 类型
    long stamp = d.getTime(); 
    

# Calendar 类

  1. Java 1.1 推荐使用 Calendar 类处理时间

  2. 使用示例

    // 获取 Calendar 实例,默认当前时间
    Calendar calendar = Calendar.getInstance();
    // 通过 setTime() 设置 Calendar 对象的时间
    calendar.setTime(new Date());
    // 通过 getTime() 获取对应的 Date 对象
    Date date = calendar.getTime();
    // 通过年/月/日/时/分/秒设置时间,month 由 0 开始
    calendar.set(2020, 1, 1);
    calendar.set(2020, 1, 1, 8, 30, 30);
    // 通过 set(int field, int value) 设置时间字段
    calendar.set(Calendar.MONTH, 0);
    // 通过 get(int field) 获取对应时间字段
    int month = calendar.get(Calendar.MONTH) + 1;
    // 通过 after 和 before 方法比较 Calendar 对象的先后,返回布尔值
    Calendar oldCalendar = Calendar.getInstance();
    oldCalendar.set(2019, 1, 1, 8, 30, 30);
    boolean after = calendar.after(oldCalendar);
    

# 存在的问题

  1. 时间计算困难

    毫秒值与日期直接转换比较繁琐,通过毫秒值来计算时间差步骤较多

  2. 线程安全问题

    SimpleDateFormat 类是线程不安全的,在多线程的情况下,全局共享一个SimpleDateFormat类中的Calendar对象可能会出现异常

    因为 SimpleDateFormat 类 format 方法执行时使用一个 Calendar 类型成员变量报错时间,该变量被多个线程共享时就会出问题

# Java 8 新时间 API

# time 包常用类

  1. Instant 类

    Instant类对时间轴上的单一瞬时点建模,可以用于记录应用程序中的事件时间戳,之后学习的类型转换中,均可以使用Instant类作为中间类完成转换

  2. Duration 类

    Duration类表示秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性

  3. Period类

    Period类表示一段时间的年、月、日

  4. LocalDate 类

    LocalDate是一个不可变的日期时间对象,表示日期,通常被视为年-月-日

  5. LocalTime 类

    LocalTime是一个不可变的日期时间对象,代表一个时间,通常被看作是小时-秒,时间表示为纳秒精度

  6. LocalDateTime 类

    LocalDateTime类是一个不可变的日期时间对象,代表日期时间,通常被视为年-月-日-时-分-秒

  7. ZonedDateTime 类

    ZonedDateTime是具有时区的日期时间的不可变表示,此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间

# now 方法

  1. now 方法根据当前日期或时间创建实例

  2. 使用示例

    // 使用 now 方法创建 Instant 的实例对象
    Instant instantNow = Instant.now();
    // 使用 now 方法创建 LocalDate 的实例对象
    LocalDate localDateNow = LocalDate.now();
    // 使用 now 方法创建 LocalTime 的实例对象
    LocalTime localTimeNow = LocalTime.now();
    // 使用 now 方法创建 LocalDateTime 的实例对象
    LocalDateTime localDateTimeNow = LocalDateTime.now();
    // 使用now方法创建 ZonedDateTime 的实例对象
    ZonedDateTime zonedDateTimeNow = ZonedDateTime.now();
    // 祖鲁时间(格林尼治时间 GMT /国际标准时间 UTC)
    System.out.println("Instant:" + instantNow);
    // 年-月-日 yy-MM-dd
    System.out.println("LocalDate:" + localDateNow);
    // 时:分:秒 HH:mm:ss
    System.out.println("LocalTime:" + localTimeNow);
    // 年-月-日T时:分:秒
    System.out.println("LocalDateTime:" + localDateTimeNow);
    // 年-月-日T时:分:秒+08:00[Asia/Shanghai] 表示时区
    System.out.println("ZonedDateTime:" + zonedDateTimeNow);
    /*
        Instant:2020-11-26T08:12:23.426Z
        LocalDate:2020-11-26
        LocalTime:16:12:23.473
        LocalDateTime:2020-11-26T16:12:23.473
        ZonedDateTime:2020-11-26T16:12:23.473+08:00[Asia/Shanghai]
    */
    
  3. time 包其他类也可以使用 now 方法更精准的获取某些信息

    • Year类(表示年)

    • YearMonth类(表示年月)

    • MonthDay类(表示月日)

# of 方法

  1. of 方法根据给定的参数生成对应的日期/时间对象

  2. 使用示例

    // 2018 年 8 月 8 日
    LocalDate localDate = LocalDate.of(2018, 8, 8);
    // 8 点 8 分 8 秒,秒为 0 或省略则 toString 不显示
    LocalTime localTime = LocalTime.of(8, 8, 8);
    // 2018 年 8 月 8 日 8 点 8 分 8 秒
    LocalDateTime localDateTime = LocalDateTime.of(2018, 8, 8, 8, 8, 8);
    
    System.out.println("localTime: " + localTime);
    System.out.println("localDate: " + localDate);
    System.out.println("localDateTime:" + localDateTime);
    /*
        localDate: 2018-08-08
        localTime: 08:08:08
        localDateTime:2018-08-08T08:08:08
    */
    

# ZoneId 时区类

  1. ZoneId 用于表示时区

  2. ZoneId.getAvailableZoneIds 返回一个 set,里面包含了约 600 个时区,如 Asia/Shanghai

  3. ZoneId.of 传入表示时区的字符串返回时区对象

  4. ZonedDateTime 设置时区

    // 获取 LocalDateTime
    LocalDateTime localDate = LocalDateTime.now();
    // LocalDateTime atZone 返回 ZonedDateTime 对象
    // 设置该 LocalDateTime 对象时区为上海
    ZonedDateTime zonedDateTime = localDate.atZone(ZoneId.of("Asia/Shanghai"));
    System.out.println(zonedDateTime);
    // 获取时区为东京的对应时间
    ZonedDateTime tokyoDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
    System.out.println(tokyoDateTime);
    /*
    	2020-11-26T16:54:31.692+08:00[Asia/Shanghai]
        2020-11-26T17:54:31.692+09:00[Asia/Tokyo]
    */
    

# Month 枚举类

  1. Month 月份枚举

    // 使用 Month 枚举获得月份
    LocalDateTime localDate = LocalDateTime.of(2018, Month.AUGUST, 8, 8, 8);
    

    注意老版本 Calendar 月份是从 0 开始,LocalDate/LocalDateTime 月份都是是从 1 开始

  2. Month.of 方法

    Month month = Month.of(12);
    System.out.println(month);
    // DECEMBER
    

# plus 和 minus 方法

  1. LocalDate 的 plus 方法

    • LocalDate plusDay(long days) 增加天数
    • LocalDate plusWeeks(long weeks) 增加周数
    • LocallDate plusMonths(long months) 增加月数
    • LocalDate plusYears(long years) 增加年数
  2. LocalTime 的 plus 方法

    • LocalTime plusNanos(long nanos) 增加纳秒
    • LocalTime plusSeconds(long seconds) 增加秒
    • LocalTime plusMinutes(long minutes) 增加分钟
    • LocalTime plusHours(long hours) 增加小时
  3. plus(TemporalAmount amoutToadd)

    TemporalAmount 是一个接口,Period 是其实现类,代表一段时间

    LocalDateTime localDateTime = LocalDateTime.now();
    // 1 年 2 个月 3 天
    Period p = Period.of(1, 2, 3);
    // 在 localDateTime 基础上加上 p 表示的一段时间
    LocalDateTime dateTimeAfterPlus = localDateTime.plus(p);
    
  4. plus(long amountToadd, TemporalUnit unit)

    TemporalUnit是一个接口,ChronoUnit 是其实现类,封装了许多时间段

    LocalDateTime localDateTime = LocalDateTime.now();
    // 加 1 天
    LocalDateTime localDateTime1 = localDateTime.plus(1, ChronoUnit.DAYS);
    // 加 2 小时
    LocalDateTime localDateTime2 = localDateTime.plus(2, ChronoUnit.HOURS);
    

# with 方法

  1. with 方法可以直接对时间的某一项进行修改

    • LocalDateTime withNano(int i) 修改纳秒
    • LocalDateTime withSecond(int i) 修改秒
    • LocalDateTime withMinute(int i) 修改分支
    • LocalDateTime withHour(int i) 修改小时
    • LocalDateTime withDayOfMonth(int i) 修改日
    • LocalDateTime withMonth(int i) 修改月
    • LocalDateTime withYear(int i) 修改年
  2. with(TemporalField field, long newValue)

    temporalField是一个接口,ChronoField 是其实现类,提供了许多日期字段的枚举

    LocalDateTime localDateTime = LocalDateTime.of(2018, 8, 8, 8, 8, 8);
    // 修改到 10 月
    LocalDateTime localDateTimeModified = localDateTime.withMonth(10);
    // 修改到 10 月
    LocalDateTime localDateTimeModified = localDateTime.with(ChronoField.MONTH_OF_YEAR, 10);
    
  3. with(TemporalAdjuster adjuster)

    TemporalAdjuster 是一个函数式接口,可以自定义 TemporalAdjuster 实现类完成想要的修改

    TemporalAdjusters 封装了许多方法,返回 TemporalAdjuster 的实现

    TemporalAdjusters 的 next、previous 方法配合 DayOfWeek 枚举类,可以方便的获取下周或上周的某天

    LocalDateTime localDateTime = LocalDateTime.of(2018, 8, 8, 8, 8, 8);
    // 改为当月第一天
    LocalDateTime localDateTime1 = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
    // 改为下个月第一天
    LocalDateTime localDateTime2 = localDateTime.with(TemporalAdjusters.firstDayOfNextMonth());
    // 自定义 TemporalAdjuster,改为当月倒数第二天
    LocalDateTime localDateTime3 = localDateTime.with(new TemporalAdjuster() {
                @Override
                public Temporal adjustInto(Temporal temporal) {
                    return temporal.with(ChronoField.DAY_OF_MONTH, temporal.range(ChronoField.DAY_OF_MONTH).getMaximum() -1 );
                }
            });
    // next、previous 方法配合 DayOfWeek 枚举类,如:下一个周五
    LocalDateTime localDateTime4 = localDateTime.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
    

# query 方法

  1. LocalDate、LocalTime 有一个 query 方法,用来进行对日期的查询

  2. R query(TemporalQuery query) 是一个泛型方法,返回的数据是传入的泛型类的类型

  3. TemporalQuery 是一个泛型接口,通过重写其 queryFrom(TemporalAccessor temporal) 方法,传入时间返回数据

    LocalDate localDate = LocalDate.of(2018, 8, 8);
    // 返回是否过了当年的劳动节
    boolean isAfterLabour = localDate.query(new TemporalQuery<Boolean>() {
        @Override
        public Boolean queryFrom(TemporalAccessor temporal) {
            LocalDate today = LocalDate.from(temporal);
            LocalDate labour = LocalDate.of(today.getYear(), 5 ,1);
            return today.isAfter(labour);
        }
    });
    

# parse 和 format

  1. parse 方法是 LocalDate、LocalDateTime 的静态方法,将字符串转为时间或日期对象

  2. format 是 LocalDate、LocalDateTime 的实例方法,用于格式化字符串

  3. DateTimeFormatter 类封装了常用的格式作为静态变量,也可使用 ofPattern 方法自定义格式

    // LocalDate.parse,默认解析 yyyy-MM-dd
    LocalDate parsedDate1 = LocalDate.parse("2018-08-08");
    // LocalDate.parse 指定格式
    LocalDate parsedDate2 = LocalDate.parse("2018/11/1", DateTimeFormatter.ofPattern("yyyy/M/d"));
    
    LocalDateTime localDateTime = LocalDateTime.of(2018,8,8,8,8,8);
    // localDateTime 对象可以直接调用 format 方法进行格式化
    // 2018-08-08
    String s1 = localDateTime.format(DateTimeFormatter.ISO_DATE);
    // 2018-08-08T08:08:08
    String s2 = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
    // DateTimeFormatter.ofPattern 自定义格式 -> 2018.08.08
    String s3 = localDateTime.format(DateTimeFormatter.ofPattern("yyyy.MM.dd"));
    
Comment here, be cool~

Copyright © 2020 CadeCode

Theme 2zh powered by VuePress

本页访问次数 0

Loading