基本概念
常用类
java.time包包含处理日期时间所需的类。常用的类有:
- Instant: An instantaneous point on the time-line.
- LocalDateTime: A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.
- ZonedDateTime: A date-time with a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00 Europe/Paris.
时间戳与时间的区别
任意时刻,全球只有一个时间戳Instant;但每个地点的本地时间LocalDateTime可能不同。
举例:时间戳1688871330,对应北京时间2023-07-09T10:55:30,对应伦敦时间2023-07-09T03:55:30。
@Test
public void convertEpochSecondToLocalDateTimeTest() {
System.out.println(Instant.ofEpochSecond(1688871330).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime());
System.out.println(Instant.ofEpochSecond(1688871330).atZone(ZoneId.of("Europe/London")).toLocalDateTime());
}
反过来也是一样。不同地点的LocalDateTime相同,对应的Instant很可能不同。因此,在将LocalDateTime转换为Instant时,一定要带上准确的时区信息。
举例:本地时间2023-07-09T10:55:30,按北京时间转换得到时间戳1688871330,按伦敦时间转换得到时间戳1688896530。
@Test
public void convertLocalDateTimeToEpochSecondTest() {
System.out.println(LocalDateTime.of(2023, 7, 9, 10, 55, 30).atZone(ZoneId.of("Asia/Shanghai")).toEpochSecond());
System.out.println(LocalDateTime.of(2023, 7, 9, 10, 55, 30).atZone(ZoneId.of("Europe/London")).toEpochSecond());
}
反例:获取本地时间后使用UTC时区转换为时间戳。如果本地时间不是UTC时区,那么这样拿到的时间戳会存在偏移。
@Test
public void wrongUsageOfLocalDateTimeTest() {
System.out.println(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC));
}
最佳实践
获取当前时间戳
ZonedDateTime和Instant都可以拿到当前时间戳。语义上Instant更合适。
@Test
public void getEpochSecondTest() {
System.out.println(ZonedDateTime.now().toEpochSecond());
System.out.println(Instant.now().getEpochSecond());
}
获取指定格式时间字符串
@Test
public void getISOFormatTest() {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}