1. GMT、UTC
1.1 GMT:格林威治(也称:格林尼治)时间,也叫世界时(Universal Time),也叫世界标准时间。是指位于英国伦敦郊区的【皇家格林尼治天文台】的标准时间,是本初子午线上的地方时,是0时区的区时。
1.2 UTC:Coordinated Universal Time,直译为:世界协调时间。它是以原子时作为计量单位的时间,计算结果极其严谨和精密。它比GMT时间更来得精准,误差值必须保持在0.9秒以内,倘若大于0.9秒就会通过闰秒来“解决”。
1.3 二者区别:
- GMT是老的时间计量标准,根据地球的自转和公转来计算时间的,自转一圈是一天,公转一圈是一年。UTC是根据原子钟进行计时的,比GMT更加精确。
- 二者在数值上几乎相等(不精确到秒的情况下)。
- GMT是带有时区信息的(0时区),而UTC不带有时区信息。
2. Java8时间类概述
由于Java Date/Calendar API被广大开发者诟病,所以2014年随着Java 8的发布引入了全新的JSR 310日期时间。JSR 310日期时间所有API均在java.time包中。
3. ZoneId类与ZoneOffset类
3.1 ZoneId类用于表示时区,ZoneOffset类用于表示偏移量。时区是特定于地区而言的,它和地理上的地区(包括规则)强绑定在一起。比如整个中国都叫东八区,纽约在西五区等等。而偏移量仅仅记录了偏移的小时分钟而已,除此之外无任何其它信息。
3.2 生成ZoneId的三种方式:
- 第一种为通过时区Id获取, 时区Id是字符串,通过ZoneId.getAvailableZoneIds()可查看所有可用的时区id。(推荐)
ZoneId zoneId1 = ZoneId.of("Australia/Sydney");
System.out.println(ZoneId.getAvailableZoneIds());
// sout [Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/GMT+8, Africa/Nairobi, ...]
- 第二种为通过偏移量获取,偏移量的合法前缀有UTC、GMT和UT,具体值的写法为[+/-mm:ss]或[+/-mm]。
ZoneId zoneId2 = ZoneId.ofOffset("UTC", ZoneOffset.of("+08"));
ZoneId zoneId3 = ZoneId.ofOffset("GMT", ZoneOffset.of("-08:30"));
ZoneId zoneId4 = ZoneId.ofOffset("UT", ZoneOffset.of("+08:00"));
- 第三种为在ZoneDateTime中获取时区,ZoneDateTime类是带有时区信息的日期时间类。
ZoneId zoneId5 = ZoneId.from(ZonedDateTime.now());
4. Instant类
4.1 Instant类表示的是一个时间戳,UTC格式下,距离1970年1月1日0时0分0秒的秒数,可精确到纳秒。Instant类不带有时区信息,是推荐的时间表示。
4.2 Instant类的两种创建方式:
- 第一种是通过Instant.now(),获取的是当前时间戳。
- 第二种是通过Instant.ofEpochSecond(),获取的是距起始秒特定秒数的时间。
4.3 Instant类的常用方法
Instant instant1 = Instant.now();
System.out.println("instant1 : "+instant1);
System.out.println("纪元秒 : "+instant1.getEpochSecond());
System.out.println("毫 秒 : "+instant1.toEpochMilli());
System.out.println("纳 秒 : "+instant1.getNano()); // 获取纳秒,不超过1000000000
ZonedDateTime zonedDateTime = instant1.atZone(ZoneId.of("Australia/Sydney")); // 转换为带时区信息的日期时间
System.out.println("悉尼时区时间: "+zonedDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
Instant instant2 = Instant.ofEpochSecond(100);
System.out.println("instant2 : "+instant2);
// sout
// instant1 : 2023-09-04T02:08:54.132Z
// 纪元秒 : 1693793334
// 毫 秒 : 1693793334132
// 纳 秒 : 132000000
// 悉尼时区时间: 2023-09-04 12:08:54
// instant2 : 1970-01-01T00:01:40Z
5. LocalXxx类
5.1 LocalDate表示本地时区的日期,LocalTime表示本地时区的时间,LocalDateTime表示本地时区的日期时间。LocalDate与LocalTime合并可构造出LocalDateTime。
5.2 LocalDateTime与ZoneDateTime的区别:虽然LocalDateTime也能修改时区信息,但是它更多的使用场景是不需要考虑时区时的日期时间表示。也就是说,没有跨时区表示日期时间的需要时使用LocalDateTime。当需要考虑时区时,最好使用ZoneDateTime。
5.3 Instant、LocalDateTime、ZoneDateTime的相互转换:
// Instant、LocalDateTime、ZoneDateTime的相互转换
Instant instant = Instant.now();
// Instant -> LocalDateTime
LocalDateTime localDateTimeIns = LocalDateTime.ofInstant(instant, ZoneId.of("Australia/Sydney"));
// Instant -> ZoneDateTime
ZonedDateTime zonedDateTimeIns = ZonedDateTime.ofInstant(instant, ZoneId.of("Australia/Sydney"));
// LocalDateTime -> ZoneDateTime
ZonedDateTime zonedDateTimeLDT = ZonedDateTime.of(localDateTimeIns, ZoneId.of("Australia/Sydney"));
6. Duration类和Period类
6.1 二者均用于表示时间区间,Duration类用于Time级别的,而Period类用于Date级别的。
7. 总结
- GMT是旧的时间标准,UTC是新的时间标准。
- Instant表示时间戳,不带有时区信息。
- ZoneId表示时区,ZoneOffset表示偏移量。
- ZoneDateTime表示带时区的日期时间。
- LocalDate表示本地日期,LocalTime表示本地时间,LocalDateTime表示本地日期时间。
- Duration为时间区间,Period为日期区间。