Java新特性之TimeAPI

什么是TimeAPI

  java.time.*是Java 8引入的Date&Time&Zone类库,提供日期,时间,瞬间和持续时间的主要API。

为什么要TimeAPI

  旧的 java.util.Date以及java.util.Calendar被开发者普遍吐槽,所以借鉴了 Joda Time 的优点,开发了新的API。

旧API的问题

  • 非线程安全 : java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • 设计很差 :Java的日期/时间类的定义并不一致,在java.utiljava.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • 时区处理麻烦 : 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendarjava.util.TimeZone类,但他们同样存在上述所有的问题。

新API的优点

  • Local(本地) : 简化了日期时间的处理,没有时区的问题。
  • Zoned(时区) : 通过制定的时区处理日期时间。
  • 新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。

如何使用TimeAPI

类说明

说明
Clock 一个时钟,使用时区提供对当前时刻,日期和时间的访问。
Duration 基于时间的时间量,例如’34.5秒’。
Instant 时间线上的瞬时点。
LocalDate ISO-8601日历系统中没有时区的日期,例如2007-12-03。
LocalDateTime ISO-8601日历系统中没有时区的日期时间,例如2007-12-03T10:15:30。
LocalTime 在ISO-8601日历系统中没有时区的时间,例如10:15:30。
MonthDay ISO-8601日历系统中的一个月 - 例如 - 12-03。
OffsetDateTime 在ISO-8601日历系统中与UTC / Greenwich偏移的日期时间,例如2007-12-03T10:15:30 + 01:00。
OffsetTime 在ISO-8601日历系统中与UTC / Greenwich偏移的时间,例如10:15:30 + 01:00。
Period ISO-8601日历系统中基于日期的时间量,例如“2年,3个月和4天”。
Year ISO-8601日历系统中的一年,例如2007。
YearMonth ISO-8601日历系统中的年度月份,例如2007-12。
ZonedDateTime ISO-8601日历系统中具有时区的日期时间,例如2007-12-03T10:15:30 + 01:00欧洲/巴黎。
ZoneId 时区ID,例如Europe / Paris。
ZoneOffset 与格林威治/ UTC的时区偏移,例如+02:00。

枚举类说明

枚举类 说明
DayOfWeek 星期几,例如’星期二’。
Month 一个月,例如’七月’。

异常

异常 Description
DateTimeException 用于表示计算日期时间问题的异常。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.time.Clock;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Test11 {

	public static void main(String[] args) {
		Clock clock = Clock.systemUTC();
		System.out.println(clock.instant());
		System.out.println(clock.millis());
		System.out.println(clock.getZone());

		// 获取本地日期
		final LocalDate date = LocalDate.now();
		final LocalDate dateFromClock = LocalDate.now(clock);

		System.out.println(date);
		System.out.println(dateFromClock);

		// 获取本地时间
		final LocalTime time = LocalTime.now();
		final LocalTime timeFromClock = LocalTime.now(clock);

		System.out.println(time);
		System.out.println(timeFromClock);

		// 获取本地日期和本地时间,是LocalTime和LocalDate的集合
		final LocalDateTime datetime = LocalDateTime.now();
		final LocalDateTime datetimeFromClock = LocalDateTime.now(clock);

		System.out.println(datetime);
		System.out.println(datetimeFromClock);

		// 获取分区日期/时间
		final ZonedDateTime zonedDatetime = ZonedDateTime.now();
		final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now(clock);
		final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));

		System.out.println(zonedDatetime);
		System.out.println(zonedDatetimeFromClock);
		System.out.println(zonedDatetimeFromZone);

		// 获取两个日期之间的间隔时间
		final LocalDateTime from = LocalDateTime.of(2014, Month.APRIL, 16, 0, 0, 0);
		final LocalDateTime to = LocalDateTime.of(2015, Month.APRIL, 16, 23, 59, 59);

		final Duration duration = Duration.between(from, to);
		System.out.println("间隔多少天: " + duration.toDays());
		System.out.println("间隔多少小时: " + duration.toHours());
	}

}

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2019-04-15T05:54:13.750Z
1555307653835
Z
2019-04-15
2019-04-15
13:54:13.850
05:54:13.850
2019-04-15T13:54:13.850
2019-04-15T05:54:13.850
2019-04-15T13:54:13.850+08:00[Asia/Shanghai]
2019-04-15T05:54:13.850Z
2019-04-14T22:54:13.850-07:00[America/Los_Angeles]
间隔多少天: 365
间隔多少小时: 8783

参考文献

Java 8 官方文档
Java 8 新特性
Java 8 新特性终极指南

今日诗词

作者信息