共计 2992 个字符,预计需要花费 8 分钟才能阅读完成。
在阅读本文之前,请先看上一篇文章 有关机器时间、UTC 时间、本地时间的总结。
Java 新时间 API 中有三个特别重要的类,分别是 Instant、LocalDateTime、ZonedDateTime,它们分别对应到上一篇文章中讲到的时间概念为:机器时间、无时区的本地时间、有时区的本地时间。
机器时间其实可以理解为 UTC 时间的另一种表现形式,其可以唯一确定时间线上的某一时刻。
无时区的本地时间因为没有时区信息,所以其无法唯一确定时间线上的某一时刻。
有时区的本地时间其实是在 UTC 时间的基础上加一些时间偏移,所以也是可以唯一确定时间线上的某一时刻。
Java 的新时间 API 其实都是围绕这三个类来实现的,所以,彻底理解这三个类的目的及使用场景对于灵活使用 Java 新时间 API 来说非常重要。
下面我们用示例来讲解下 Java 的新时间 API 究竟怎么用。
- 获取当前时间的年月日等信息。
static void t1() {LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.getYear());
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt.getYear());
// 对于获取当前时刻的 human time 信息(年月日时分秒)来说
// 用 LocalDateTime 或者 ZonedDateTime 都是一样的
// 他们的底层都是先获取 machine time,然后再按照所在时区
// 将 machine time 转成 human time
// ZonedDateTime 比 LocalDateTime 的唯一区别就是携带了时区信息
// 但如果只是为了获取年月日等信息,时区是没用的
}
- 获取某一机器时间的年月日等信息。
static void t2() {long millis = System.currentTimeMillis();
Instant instant = Instant.ofEpochMilli(millis);
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(ldt.getYear());
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(zdt.getYear());
// 机器时间要先转成 Instant 实例后,才能被 Java 新时间 API 使用
}
- 人类时间转机器时间。
static void t3() {
// 由于 LocalDateTime 没有时区信息,所以它无法直接转成机器时间
// 只能通过主动提供时区信息的方式才可以
LocalDateTime ldt = LocalDateTime.now();
long millis = ldt.toInstant(ZoneOffset.of("+08:00")).toEpochMilli();
System.out.println(millis);
// 由于 ZonedDateTime 内已经有时区信息了,所以它可以直接转成机器时间
ZonedDateTime zdt = ZonedDateTime.now();
millis = zdt.toInstant().toEpochMilli();
System.out.println(millis);
// 还需要注意的是,代表人类时间的类并不是直接转成的机器时间,而是通过 Instant 类间接完成
}
- 解析时间字符串。
static void t4() {
// 被解析的字符串不能有时区信息
LocalDateTime ldt = LocalDateTime.parse("2019-09-25T16:32:42");
System.out.println(ldt);
// 被解析的字符串必须有时区信息
ZonedDateTime zdt = ZonedDateTime.parse("2019-09-25T16:32:42+08:00");
System.out.println(zdt);
}
- 时间的运算。
static void t5() {
// LocalDateTime 的时间加减就是纯粹的加减
LocalDateTime ldt = LocalDateTime.parse("2019-03-10T01:59:59");
System.out.println(ldt.plusHours(1).getHour()); // 输出:2
// ZonedDateTime 的时间加减还会考虑时区信息
// 比如 2019-03-10T02:00:00 开始,美国开始施行 daylight saving time (夏令时)
// 他们的本地时间会向后拨一个小时,即:凌晨 2 点会变成凌晨 3 点
// 有关 daylight saving time 更多信息,请看以下文章:// https://en.wikipedia.org/wiki/Daylight_saving_time
ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/New_York"));
System.out.println(zdt.plusHours(1).getHour()); // 输出:3
// 所以说,如果涉及到时间的运算,要用 ZonedDateTime
}
- 获取某一机器时间所属那天的零点的机器时间。
static long startOfDay(long millis) {return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
.atStartOfDay(ZoneId.systemDefault())
.toInstant()
.toEpochMilli();}
- 获取某一机器时间所属那个星期的星期一零点的机器时间。
static long startOfWeek(long millis) {return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
.atStartOfDay(ZoneId.systemDefault())
.with(DayOfWeek.MONDAY)
.toInstant()
.toEpochMilli();}
- 获取某一机器时间所属那个月的一号零点的机器时间。
static long startOfMonth(long millis) {return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
.atStartOfDay(ZoneId.systemDefault())
.withDayOfMonth(1)
.toInstant()
.toEpochMilli();}
好,例子就这么多吧,我觉得到这里大家都差不多懂了。
有关 Java 新时间 API 更多介绍,请参考 Java 官方教程:
https://docs.oracle.com/javas…
希望对大家有所帮助。
完。
更多原创文章,请关注我微信公众号:
正文完