Java8 以前关于时间的类是 Date 和 Calendar,不过这两个类设计的很有问题,一个是带有默认的时区(timezone),另一个是类是 mutable 的,这样在使用时要特别注意线程安全问题,而且也没有办法阻止其他的线程修改日期。
Java8 添加了 java.time 包,重新设计了时间类,让时间的操作更加友好。
总的来说,time 包分为两类,一是表示瞬时时间,即一个时间点,另一个是一段时间,代表两个时间的差。
我们将时间从过去到未来看成一条连续的时间线,通常我们使用的某一个时间点,譬如几点几分开会,几点几分活动开始,因此先来了解一下表达一个时间点的类。
Instant
类是时间戳,代表 UTC 时区从 1970年1月1日0点0分0秒到当前时刻所经过的时间(精度可到纳秒)。Instant
与时区无关,它的计时是以 UTC 时区为准的。
// Instant 初始化
Instant instant1 = Instant.now();
Instant instant2 = Instant.ofEpochMilli(10000000L);
Instant instant3 = Instant.ofEpochSecond(10000000L);
// Instant 判定在时间线上的前后
// true
System.out.println(instant1.isAfter(instant2));
// false
System.out.println(instant1.isBefore(instant2));
Instant
可通过指定 TimeZone 来转换成某一个时区的时间 ZonedDateTime zonedDateTime = instant1.atZone(ZoneId.systemDefault());
, time 包中的各个时间类都可以相互转换,因为它们表示的只是时间的某一方面。
日期类指的是年月日,而不带时分秒的类,这些相关的类与时区无关,表达的是一个日常的时间概念。
LocalDate
由年月日组成,通常 LocalDate
用于表示某一个时间,像生日,结婚纪念日等。注意,虽然 LocalDate
中有一个 local,但是其中并不包含时区,你只能用这个时间和你本地的人交流。
LocalDate
封装了很多对日期的操作。
// 初始化
LocalDate localDate = LocalDate.of(2020, 7, 6);
LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = LocalDate.now(ZoneId.systemDefault());
// 年月日
localDate.getMonth();
localDate.getYear();
localDate.getDayOfWeek();
localDate.getDayOfMonth();
localDate.getDayOfYear();
// 下一个周三
TemporalAdjuster nextWed = TemporalAdjusters.next(DayOfWeek.WEDNESDAY);
//2020-07-08
LocalDate nextWedDate = localDate.with(nextWed);
TemporalAdjuster
是用于设置时间的通用类,后面再写。
这三个类比较简单,用的比较少。
YearMonth yearMonth = YearMonth.now();
YearMonth.of(2020, 7);
MonthDay monthDay = MonthDay.now();
Year year = Year.now();
Year year1 = Year.of(2020);
Year year2 = Year.now(ZoneId.systemDefault());
本地时间类与日期类一样,也代表一个本地时间,与时区无关.
LocalTime
代表的是时分秒,用此类来制作一个时钟。
while(true) {
LocalTime localTime = LocalTime.now();
System.out.println(localTime.getHour() + ":" +
localTime.getMinute() + ":" + localTime.getSecond());
Thread.sleep(1000L);
}
LocalDateTime
代表一个完整的本地时间,与时区无关,虽然上面的类的of
有一个需要时区参数的初始化函数,但是只用于获取当地时区时间,在初始化完成之后,Local 类中并没有保存时区信息,要显式表示时区,就需要使用下面的 ZonedDateTime
或 OffsetDateTime
LocalDateTime localDateTime = LocalDateTime.now();
// 下个月的同一时间
localDateTime.plusMonths(1);
// 去年的同一时间
localDateTime.withYear(2019);
时区代表地球上的某一个区域,形式为 region/city (Asia/Tokyo)
, 时区实际上由两部分组成,一为 id,就是上面的表示形式,一为 Offset,Offset 就是与 格林尼治UTC 的一个偏差,通常用 [+-]时:分
(+09:00) 表示。 因此时区实质上就是预定义好的便于人类记忆的时差集合,对应的类是 ZoneId
如果预定义的时区不符合要求,那就可以直接使用 ZoneOffset
来定义自己的到 UTC 的时差(定义一个1小时3分钟的时差ZoneOffset.ofHoursMinutes(1, 3);
), hour 可正可负(hour -18, 18, minute 0-59)
ZonedDateTime
与 LocalDateTime
类多了时区信息。
//本地北京时间
ZonedDateTime zonedDateTime = ZonedDateTime.now();
// 转换为西雅图时间
ZonedDateTime seattleTime = zonedDateTime.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
System.out.println(seattleTime);
OffsetDateTime
是 LocalDateTime
与 ZonedOffset
组合起来形成的一个类。
//构造一个 +01:00 的时间
LocalDateTime localDateTime = LocalDateTime.now();
OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, ZoneOffset.ofHoursMinutes(1, 0));
// 查看 +02:45 时差处的时间
System.out.println(offsetDateTime.withOffsetSameInstant(ZoneOffset.ofHoursMinutes(2, 45)));
time 包使用了统一的命名规则,这源于它们的共同接口 Temporal
与 TemporalAccessor
, 及统一命名的静态工厂函数。
具体如下:
API | 含义 |
---|---|
of | 静态,用具体时间初始化 |
now | 静态,当前时间 |
parse | 静态,使用Formatter 解析 |
plus | 方法,增加时间,返回新拷贝 |
minus | 方法,减少时间 |
with | 方法,setter |
get | getter |
is | 方法,检查 |
to | 方法,将其转换为另一个 |
at | 方法,将两个对象组合起来 |
format | 方法,根据 |
这次新增的表示时间段的类是 Duration
和 Period
,
Duration
一般用于表示一段与时间线无关的时间。可以理解成一个线段, 它用于机器时间(与 Instant
类组合使用)。
// 初始化
Duration duration = Duration.ofDays(1);
// 增加10s
duration.plusSeconds(10);
Period
类提供了一种通过日期来测量的时间段,它可以和 LocalDate
一起使用,基于人类时间。
// 获取从2020-7-1到现在过了多少天
LocalDate localDate = LocalDate.now();
LocalDate localDate1 = LocalDate.of(2020, 7, 1);
Period period = Period.between(localDate1, localDate);
period.getDays();
Temporal 是时间的意思,Adjuster 是调整的意思,Java8 将修改转换的高级功能放到了这个类中,各个时间类都包含 with(TemporalAdjuster ta)
方法。
TemporalAdjuster
是一个接口,TemporalAdjusters
提供了各种实用方法来获取 adjuster。前面 LocalDate
中使用 adjuster 获取了下周三的时间
firstDayOfMonth 调整到当月的第一天
lastDayOfMonth 当月最后一天 firstDayOfNextMonth 下月第一天 firstDayOfYear, lastDayOfYear, firstDayOfNextYear next 下周几 nextOrSame 如果当天是周几,直接返回,否则返回下周几
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。