从Java 8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:
- 本地日期和时间:
LocalDateTime,LocalDate,LocalTime; - 带时区的日期和时间:
ZonedDateTime; - 时刻:
Instant; - 时区:
ZoneId,ZoneOffset; - 时间间隔:
Duration。
以及一套新的用于取代SimpleDateFormat的格式化类型DateTimeFormatter。
和旧的API相比,新API严格区分了时刻、本地日期、本地时间和带时区的日期时间,并且,对日期和时间进行运算更加方便。
(1) LocalDateTime
LocalDateTime无法与时间戳进行转换,因为LocalDateTime没有时区,无法确定某一时刻。需要用到
ZonedDateTime
创建
LocalDate localDate = LocalDate.now();// 日期对象
LocalTime localTime = LocalTime.now();// 时间对象
LocalDateTime localDateTime = LocalDateTime.now();// 日期和时间对象
LocalDate localDate1 = localDateTime.toLocalDate(); // 转换到当前日期
LocalTime localTime1 = localDateTime.toLocalTime(); // 转换到当前时间
System.out.println(localDate);// 2025-06-30
System.out.println(localTime);// 14:58:21.119143200
System.out.println(localDateTime);// 2025-06-30T14:58:21.119143200
LocalDateTime、LocalDate和LocalTime默认严格按照ISO 8601规定的日期和时间格式进行打印。
通过指定的日期和时间创建LocalDateTime
//方法1:使用of方法
LocalDateTime localDateTime = LocalDateTime.of(2020, Month.JANUARY, 1, 1,12, 34);
LocalDate localDate = LocalDate.of(2020,Month.JANUARY,1);
LocalTime localTime = LocalTime.of(15,16,17);
System.out.println(localDate);// 2020-01-01
System.out.println(localTime);// 15:16:17
System.out.println(localDateTime);// 2020-01-01T01:12:34
//方法2:严格按照ISO 8601的格式
LocalDateTime localDateTime2 = LocalDateTime.parse("2020-01-01T01:12:34");
LocalDate localDate2 = LocalDate.parse("2020-01-01");
LocalTime localTime2 = LocalTime.parse("15:16:17");
System.out.println(localDate2);// 2020-01-01
System.out.println(localTime2);// 15:16:17
System.out.println(localDateTime2);// 2020-01-01T01:12:34
格式化输出
如果要自定义输出的格式,或者要把一个非ISO 8601格式的字符串解析成LocalDateTime,可以使用新的DateTimeFormatter
// 自定义格式
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
System.out.println(formatter.format(localDateTime));// 2025/06/30 16:05:54
// 用自定义格式解析
LocalDateTime localDateTime1 = LocalDateTime.parse("2025/06/30 01:00:00", formatter);
System.out.println(formatter.format(localDateTime1));// 2025/06/30 01:00:00
加减
// 自定义格式
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
System.out.println(formatter.format(localDateTime));// 2025/06/30 17:09:47
// 加法plusXxx
System.out.println(localDateTime.plusDays(1));// 加一天:2025-07-01T17:09:47.461976900
System.out.println(localDateTime.plusHours(2));// 加两个小时:2025-06-30T19:09:47.461976900
System.out.println(localDateTime.plusDays(1).plusHours(2));// 加一天零2个小时:2025-07-01T19:09:47.461976900
// 减法minusXxx
System.out.println(localDateTime.minusDays(1).minusHours(2));// 减一天零2个小时:2025-06-29T15:09:47.461976900
// 调整时间 withXxx
System.out.println(localDateTime.withHour(1));// 将时间设置成凌晨1点:2025-06-30T01:09:47.461976900
System.out.println(localDateTime.withMonth(2));// 将月份调整到2月(因为2不满30,将变成最大天):2025-02-28T17:09:47.461976900
// 下月第一天
System.out.println(LocalDate.now().with(TemporalAdjusters.firstDayOfNextMonth()));//下月第一天 2025-07-01
System.out.println(LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()));//本月第一天 2025-06-01
System.out.println(LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()));//本月最后一天:2025-06-30
对比
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime target = LocalDateTime.of(2020, Month.JANUARY, 1, 1,12, 34);
System.out.println(localDateTime);// 2025-06-30T18:04:45.132876900
System.out.println(target);// 2020-01-01T01:12:34
System.out.println(localDateTime.isBefore(target));//在时间之前 false
System.out.println(localDateTime.isAfter(target));//在时间之后 true
时间间隔
-
Duration表示两个时刻之间的时间间隔。 -
Period表示两个日期之间的天数。
LocalDateTime target = LocalDateTime.of(2020, Month.JANUARY, 1, 1,12, 34);
LocalDateTime target2 = LocalDateTime.of(2021, Month.SEPTEMBER, 2, 3,4, 5);
System.out.println(target);// 2020-01-01T01:12:34
System.out.println(target2);// 2021-09-02T03:04:05
// 时间间隔
Duration duration = Duration.between(target, target2);
System.out.println(duration);// PT14641H51M31S :相差14641小时51分钟31秒
// 天数间隔
long period = target2.until(target, ChronoUnit.DAYS);// -610:target2比target晚21天
System.out.println(period);
// 日期间隔
Period period1 = LocalDate.of(2021,Month.SEPTEMBER,2).until(LocalDate.of(2020, Month.JANUARY, 1));
System.out.println(period1);// P-1Y-8M-1D:相差一年八个月一天
(2) ZonedDateTime
LocalDateTime总是表示本地日期和时间,要表示一个带时区的日期和时间,我们就需要ZonedDateTime。
ZonedDateTime理解成LocalDateTime加ZoneId。ZoneId是java.time引入的新的时区类。
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt);// 2025-07-01T13:37:03.438413800+08:00[Asia/Shanghai]
ZonedDateTime zdt2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println(zdt2);// 2025-07-01T01:37:03.439414-04:00[America/New_York]
用LocalDateTime实现
//用LocalDateTime实现
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt3 = ldt.atZone(ZoneId.systemDefault());
System.out.println(zdt3);// 2025-07-01T13:42:01.560138800+08:00[Asia/Shanghai]
ZonedDateTime zdt4 = ldt.atZone(ZoneId.of("America/New_York"));
System.out.println(zdt4);// 2025-07-01T13:42:01.560138800-04:00[America/New_York]
获取时间戳
ZonedDateTime zonedDateTime = ZonedDateTime.now();// 2025-07-01T14:20:11.403281900+08:00[Asia/Shanghai]
System.out.println(zonedDateTime.getLong(INSTANT_SECONDS));//1751348521
System.out.println(zonedDateTime.toEpochSecond());//1751348521
也可以转为
Instant操作,详见下面Instant部分
时区转换
withZoneSameInstant
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt);// 2025-07-01T13:45:02.520222100+08:00[Asia/Shanghai]
ZonedDateTime zdt2 = ZonedDateTime.now().withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println(zdt2);
(3)时间戳:Instant
Instant instant = Instant.now();
System.out.println(instant);// 2025-07-01T06:06:23.918918Z
System.out.println(instant.getEpochSecond());// 秒:1751349983
System.out.println(instant.toEpochMilli());// 毫秒:1751349983918
//转换成ZonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(zonedDateTime);// 2025-07-01T14:06:23.918918+08:00[Asia/Shanghai]
// 转回Instant
System.out.println(zonedDateTime.toInstant());//2025-07-01T06:06:23.918918Z
//转换成LocalDateTime
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(localDateTime);// 2025-07-01T14:06:23.918918
//指定时间戳
Instant instant2 = Instant.ofEpochSecond(1234567890);
System.out.println(instant2);// 2009-02-13T23:31:30Z
LocalDateTime,ZoneId,Instant,ZonedDateTime和long都可以互相转换:
┌─────────────┐
│LocalDateTime│────┐
└─────────────┘ │ ┌─────────────┐
├───>│ZonedDateTime│
┌─────────────┐ │ └─────────────┘
│ ZoneId │────┘ ▲
└─────────────┘ ┌─────────┴─────────┐
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Instant │<───>│ long │
└─────────────┘ └─────────────┘










网友评论