0%

Java 函数式编程(五):Java 8 的日期和时间 API

1. Java 8 日期和时间 API 的优点

  • Java 8 以前的日期和时间 API,主要的类是 DateCalendar,由于它的设计有一些不足Java 8 引入了一套新的 API,位于包 java.time 下。
  • 它引入了更多的类,但概念更为清晰更为强大和易用

2. Java 8 中表示日期和时间的类有

  • Instant:表示时刻,不直接对应年月日信息,需要通过时区转换。
  • LocalDateTime:表示与时区无关的日期和时间,不直接对应时刻,需要通过时区转换。
  • ZoneId/ZoneOffset:表示时区
  • LocalDate:表示与时区无关的日期,与 LocalDateTime 相比,只有日期,没有时间信息。
  • LocalTime:表示与时区无关的时间,与 LocalDateTime 相比,只有时间,没有日期信息。
  • ZonedDateTime:表示特定时区的日期和时间

3. 怎样理解 Instant

  • Instant 表示时刻,获取当前时刻:Instant now = Instant.now();
  • 可以根据 Epoch Time (纪元时)创建 Instant。比如,另一种获取当前时刻的代码为:Intant now = Instant.ofEpochMilli( Sytem.currentTimeMillis() );
  • Date 也表示时刻,InstantDate 可以通过纪元时相互转换
    • 转换 DateInstant: public static Instant toInstant(Date date) { return Instant.ofEpochMilli(date.getTime()); }
    • 转换 IntantDate: public static Date toDate(Instant instant) { return new Date(instant.toEpochMilli()); }

4. 怎样理解 LocalDateTime

  • LocalDateTime 表示与时区无关的日期和时间,获取系统默认时区的当前日期和时间:LocalDateTime ldt = LocalDateTime.now();
  • 还可以直接用年月日等信息构建 LocalDateTime。比如:LocalDateTime ldt = LocalDateTime.of(2017, 7, 11, 20, 45, 5);
  • LocalDateTime 有很多方法,可以获取年月日时分秒星期等信息:
    • public int getYear()
    • public int getMonthValue()
    • public int getDayOfMonth()
    • public int getHour()
    • pubic int getMinute()
    • public int getSecond()
    • publict DayOfWeek getDayOfWeek()

5. 怎样理解 ZoneId/ZoneOffset

  • LocalDateTime 不能直接转为时刻 Instant,转换需要一个参数 ZoneOffset
  • ZoneOffset 表示相对于格林尼治的时区差,北京是 +08:00。比如,转换一个 LocalDateTime 为北京的时刻:public static Instant boBeijingInstant(LocalDateTime ldt) { return ldt.toInstant(ZoneOffset.of("+08:00")); }
  • 给定一个时刻,使用不同时区解读,日历信息是不同的,Instant 有方法根据时区返回一个 ZonedDateTime: public ZonedDateTime atZone(ZoneId zone)
  • 默认时区是 ZoneId.systemDefault(),可以这样构建 ZoneId: ZoneId bjZone = ZoneId.of("GMT+08:00);
  • ZoneOffsetZoneId 的子类,可以根据时区差构造。

6. 怎样理解 LocalDate/LocalTime

  • 可以认为 LocalDateTime 由两部分组成,一部分是日期 LocalDate,另一部分是时间 LocalTime
  • LocalDate 加上时间可以构成 LocalDateTimeLocalTime 加上日期可以构成 LocalDateTime

7. 怎样理解 ZonedDateTime

  • ZonedDateTime 表示特定时区的日期和时间,获取系统默认时区的当前日期和时间为:ZonedDateTime zdt = ZonedDateTime.now();

  • LocalDateTime.now() 也是获取默认时区的当前日期和时间,二者的区别是:

    • LocalDateTime 内部不会记录时区信息,只会单纯记录年月日时分秒等信息。
    • ZonedDateTime 除了记录日历信息,还会记录时区,它的其他大部分构建方法都需要显示传递时区。
  • ZonedDateTime 可以直接转换为 Instant:

    1
    2
    ZonedDateTime ldt = ZonedDateTime.now(); 
    Instant now = ldt.toInstant();

8. Java 8 中的格式化

  • Java 8 中,主要的格式化类是 java.time.format.DateTimeFormatter,它是线程安全的

  • Demo:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    LocalDateTime ldt = LocalDateTime.of(2016, 8, 18, 14, 20, 45);
    System.out.println(formatter.format(ldt));

    输出为:2016-08-18 14:20:45

    //将字符串转化为日期和时间对象,可以使用对应类的 parse 方法
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    String str = "2016-08-18 14:20:45";
    LocalDateTime ldt = LocalDateTime.parse(str, formatter);

9. Java 8 中怎样设置/修改时间

  • 修改时期和时间有两种方式,一种是直接设置绝对值,另一中是在现有值的基础上进行相对增减操作。Java 8 的大部分类都支持这两种方法。
  • Java 8 的大部分类都是不可变类,修改操作是通过创建并返回新对象来实现的,原对象本身不会变。

10. Java 8 中时间段的计算

  • Java 8 中表示时间段的类主要有两个:PeriodDuration
  • Period 表示日期差,用年月日表示,不能表示时间。
  • Duration 表示时间差,用时分秒表示,也可以用天表示,一天严格等于 24 小时,不能用年月表示。

11. Java 8 中与 Date/Calendar 对象的转换

  • Java 8 的日期和时间 API 没有提供与老的 Date/Calendar 相互转换的方法,但在实际中,我们可能是需要的。
  • Date 可以与 Instant 通过毫秒数相互转换。对于其他类型,也可以通过 毫秒数/ Instant 相互转换。
-------------------- 本文结束感谢您的阅读 --------------------