在 java.time 包中,不同日期时间对象(如 LocalDate、LocalDateTime、Instant)之间的转换是常见操作。以下详细介绍核心转换方法及示例:
LocalDate 表示日期(无时间),使用 atStartOfDay() 方法将其转换为 LocalDateTime,默认时间为当天 00:00:00。例如:
package com.hxstrive.java_date_time.convert; import java.time.LocalDate; import java.time.LocalDateTime; public class DateToDateTime { public static void main(String[] args) { // 创建LocalDate对象 LocalDate date = LocalDate.of(2023, 10, 5); // 转换为LocalDateTime(默认00:00:00) LocalDateTime dateTime = date.atStartOfDay(); System.out.println("LocalDate: " + date); // 输出:2023-10-05 System.out.println("LocalDateTime: " + dateTime); // 输出:2023-10-05T00:00 } }
运行结果:
LocalDate: 2023-10-05 LocalDateTime: 2023-10-05T00:00
LocalDateTime 包含日期和时间,toLocalDate() 方法提取其中的日期部分,得到 LocalDate。例如:
package com.hxstrive.java_date_time.convert; import java.time.LocalDate; import java.time.LocalDateTime; public class DateTimeToDate { public static void main(String[] args) { // 创建LocalDateTime对象 LocalDateTime dateTime = LocalDateTime.of(2023, 10, 5, 14, 30); // 提取日期部分,转换为LocalDate LocalDate date = dateTime.toLocalDate(); System.out.println("LocalDateTime: " + dateTime); System.out.println("LocalDate: " + date); } }
运行结果:
LocalDateTime: 2023-10-05T14:30 LocalDate: 2023-10-05
Instant 表示UTC 时间戳(从 1970-01-01T00:00:00Z 开始的毫秒数),与 LocalDateTime(本地日期时间)的转换需要指定时区(TimeZone)。
将 Instant 转换为 LocalDateTime 需要先调用 atZone(ZoneId) 方法指定时区,然后再使用 toLocalDateTime() 方法进行转换。其中:
Instant.atZone(ZoneId) 将 UTC 时间戳转换为指定时区的ZonedDateTime;
toLocalDateTime() 提取本地日期时间。
示例代码:
package com.hxstrive.java_date_time.convert; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; public class InstantToDateTime { public static void main(String[] args) { // 获取当前UTC时间戳(Instant) Instant instant = Instant.now(); // 转换为东八区(Asia/Shanghai)的LocalDateTime LocalDateTime dateTime = instant .atZone(ZoneId.of("Asia/Shanghai")) // 绑定时区 .toLocalDateTime(); // 提取本地日期时间 System.out.println("Instant: " + instant); System.out.println("LocalDateTime(东八区): " + dateTime); } }
运行结果:
Instant: 2025-09-23T01:24:34.229381400Z LocalDateTime(东八区): 2025-09-23T09:24:34.229381400
将 LocalDateTime 转换成 Instant 也需要两步,先使用 atZone(ZoneId) 将本地日期时间绑定到某个时区,得到 ZonedDateTime,然后通过 toInstant() 方法转换为 Instant。其中:
LocalDateTime.atZone(ZoneId) 方法用于将本地日期时间绑定到指定时区,得到ZonedDateTime。
toInstant() 方法用于将 ZonedDateTime 转换为 UTC 时间戳。
示例代码:
package com.hxstrive.java_date_time.convert; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; public class DateTimeToInstant { public static void main(String[] args) { // 创建本地日期时间(默认无时区) LocalDateTime dateTime = LocalDateTime.of(2023, 10, 5, 14, 30); // 绑定东八区,转换为Instant(UTC时间戳) Instant instant = dateTime .atZone(ZoneId.of("Asia/Shanghai")) // 绑定时区 .toInstant(); // 转换为UTC时间 System.out.println("LocalDateTime: " + dateTime); System.out.println("Instant(UTC): " + instant); } }
运行结果:
LocalDateTime: 2023-10-05T14:30 Instant(UTC): 2023-10-05T06:30:00Z
java.util.Date 与新的日期时间 API(LocalDateTime、LocalDate、Instant)之间的转换需要注意时区的处理,因为旧的 Date 包含时区信息(本质上是 UTC 时间),而新的本地日期时间类不包含时区信息。
转换说明:
Date -> Instant:直接使用Date.toInstant()方法,两者都是表示 UTC 时间线上的一个点,可以直接转换。
Date -> LocalDateTime:需要通过Instant作为中间转换,必须指定时区(ZoneId),因为LocalDateTime是本地时间,依赖时区计算。常用时区:ZoneId.systemDefault()(系统默认)、ZoneId.of("UTC")(UTC 时区)、ZoneId.of("Asia/Shanghai")(上海时区)
Date -> LocalDate:先通过atZone(ZoneId)将Instant转换为带时区的ZonedDateTime,再调用toLocalDate()提取日期部分(忽略时间)。
示例代码:
package com.hxstrive.java_date_time.convert; import java.util.Date; import java.time.LocalDateTime; import java.time.LocalDate; import java.time.Instant; import java.time.ZoneId; public class FromDate { public static void main(String[] args) { // 创建一个java.util.Date对象 Date date = new Date(); System.out.println("原始Date对象: " + date); // 1. Date转换为Instant Instant instant = date.toInstant(); System.out.println("转换为Instant: " + instant); // 2. Date转换为LocalDateTime (需要指定时区) // 使用系统默认时区 LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); System.out.println("转换为LocalDateTime(系统默认时区): " + localDateTime); // 使用指定时区,例如UTC LocalDateTime utcDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.of("UTC")); System.out.println("转换为LocalDateTime(UTC时区): " + utcDateTime); // 3. Date转换为LocalDate (需要指定时区) LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); System.out.println("转换为LocalDate: " + localDate); } }
运行结果:
原始Date对象: Tue Sep 23 09:32:18 CST 2025 转换为Instant: 2025-09-23T01:32:18.146Z 转换为LocalDateTime(系统默认时区): 2025-09-23T09:32:18.146 转换为LocalDateTime(UTC时区): 2025-09-23T01:32:18.146 转换为LocalDate: 2025-09-23
要将 LocalDate、LocalDateTime、Instant 转换为 Date,需要先了解一下这几个日期类的核心差异:
LocalDate:仅包含日期(无时间、无时区)
LocalDateTime:包含日期和时间(无时区)
Instant:表示 UTC 时间线上的一个瞬间(无时区概念,本质是时间戳)
Date:包含日期和时间,内部存储为自 1970-01-01 UTC 以来的毫秒数
转换操作如果涉及 LocalDate 和 LocalDateTime 时,必须指定时区(ZoneId),且所有转换都需要通过Instant 作为中间桥梁。例如:
LocalDateTime → Date:必须通过 atZone(zoneId) 关联时区,得到包含时区信息的 ZonedDateTime,再通过 toInstant() 获取 Instant,最后用 Date.from(instant) 完成转换。
LocalDate → Date:由于 LocalDate 不含时间,需先用 atStartOfDay() 补充时间(默认当天 00:00:00),后续转换流程与 LocalDateTime 相同。
Instant → Date:转换最直接,因为 Instant 和 Date 都是基于 UTC 时间戳的,可直接用 Date.from(instant) 转换。
示例代码:
package com.hxstrive.java_date_time.convert; import java.util.Date; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Instant; import java.time.ZoneId; public class ToDate { public static void main(String[] args) { // 指定时区 ZoneId zoneId = ZoneId.of("Asia/Shanghai"); // 亚洲/上海时区 // 1. LocalDateTime 转换为 Date LocalDateTime localDateTime = LocalDateTime.now(); // 步骤:LocalDateTime + 时区 → ZonedDateTime → Instant → Date Instant ldtInstant = localDateTime.atZone(zoneId).toInstant(); Date dateFromLdt = Date.from(ldtInstant); System.out.println("LocalDateTime 转换结果: " + dateFromLdt); // 2. LocalDate 转换为 Date(默认时间为当天00:00:00) LocalDate localDate = LocalDate.now(); // 步骤:LocalDate → LocalDateTime(补充时间)→ ZonedDateTime → Instant → Date LocalDateTime ldToLdt = localDate.atStartOfDay(); // 补充时间为00:00:00 Instant ldInstant = ldToLdt.atZone(zoneId).toInstant(); Date dateFromLd = Date.from(ldInstant); System.out.println("LocalDate 转换结果: " + dateFromLd); // 3. Instant 转换为 Date Instant instant = Instant.now(); Date dateFromInstant = Date.from(instant); System.out.println("Instant 转换结果: " + dateFromInstant); // 验证不同时区的影响(对比UTC时区) ZoneId utcZone = ZoneId.of("UTC"); Date dateFromLdtUtc = Date.from(localDateTime.atZone(utcZone).toInstant()); System.out.println("LocalDateTime(UTC时区) 转换结果: " + dateFromLdtUtc); } }
运行结果:
LocalDateTime 转换结果: Tue Sep 23 10:04:56 CST 2025 LocalDate 转换结果: Tue Sep 23 00:00:00 CST 2025 Instant 转换结果: Tue Sep 23 10:04:56 CST 2025 LocalDateTime(UTC时区) 转换结果: Tue Sep 23 18:04:56 CST 2025
Calendar与新日期时间 API(LocalDate、LocalDateTime、Instant)的转换可以通过Instant作为中间桥梁,再需要注意时区处理。
转换说明:
Calendar → Instant:直接使用calendar.toInstant()方法,Calendar内部存储的是基于其自身时区的时间,转换为Instant时会自动转为 UTC 时间。
Calendar → LocalDateTime:
先通过calendar.getTimeZone().toZoneId()获取Calendar使用的时区
再用LocalDateTime.ofInstant(...)结合时区进行转换
也可以指定其他时区(如系统默认时区ZoneId.systemDefault())
Calendar → LocalDate:
先将Calendar转为Instant,再关联时区得到ZonedDateTime
最后通过toLocalDate()提取日期部分(仅包含年、月、日)
示例代码:
package com.hxstrive.java_date_time.convert; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Calendar; import java.util.TimeZone; public class FromCalendar { public static void main(String[] args) { // 创建一个Calendar实例(默认时区和 Locale) Calendar calendar = Calendar.getInstance(); System.out.println("原始Calendar: " + calendar.getTime()); // 1. Calendar 转换为 Instant Instant instant = calendar.toInstant(); System.out.println("Calendar -> Instant: " + instant); // 2. Calendar 转换为 LocalDateTime // 获取Calendar的时区 ZoneId zoneId = calendar.getTimeZone().toZoneId(); LocalDateTime localDateTime = LocalDateTime.ofInstant(calendar.toInstant(), zoneId); System.out.println("Calendar -> LocalDateTime: " + localDateTime); // 3. Calendar 转换为 LocalDate LocalDate localDate = LocalDateTime.ofInstant(calendar.toInstant(), zoneId).toLocalDate(); System.out.println("Calendar -> LocalDate: " + localDate); } }
运行结果:
原始Calendar: Tue Sep 23 09:59:49 CST 2025 Calendar -> Instant: 2025-09-23T01:59:49.574Z Calendar -> LocalDateTime: 2025-09-23T09:59:49.574 Calendar -> LocalDate: 2025-09-23
将 LocalDate、LocalDateTime、Instant 这些新日期时间类型转换为 Calendar(旧的日期时间类)时,需要注意两者在设计上的差异:
新日期类型(LocalDate等)本身不包含时区信息(Instant除外,它是 UTC 时间)
Calendar包含时区信息,且内部依赖Date进行时间存储
核心转换思路:新日期类型 → Instant → Date(或毫秒数) → Calendar
示例代码:
package com.hxstrive.java_date_time.convert; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Calendar; import java.util.TimeZone; public class ToCalendar { public static void main(String[] args) { Instant instant = Instant.parse("2024-10-22T12:30:00.000+08:00"); System.out.println("instant=" + instant); LocalDateTime localDateTime = LocalDateTime.of(2024, 10, 22, 12, 30, 0, 0); System.out.println("localDateTime=" + localDateTime); LocalDate localDate = LocalDate.of(2024, 10, 22); System.out.println("localDate=" + localDate); ZoneId zoneId = ZoneId.of("Asia/Shanghai"); // Instant 转换为 Calendar Calendar calendarFromInstant = Calendar.getInstance(); calendarFromInstant.setTimeInMillis(instant.toEpochMilli()); // 或使用TimeZone设置时区 calendarFromInstant.setTimeZone(TimeZone.getTimeZone(zoneId)); System.out.println("Instant -> Calendar: " + calendarFromInstant.getTime()); // LocalDateTime 转换为 Calendar Calendar calendarFromLdt = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); calendarFromLdt.setTimeInMillis(localDateTime.atZone(zoneId).toInstant().toEpochMilli()); System.out.println("LocalDateTime -> Calendar: " + calendarFromLdt.getTime()); // LocalDate 转换为 Calendar(默认使用当天的00:00:00) Calendar calendarFromLd = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); calendarFromLd.setTimeInMillis(localDate.atStartOfDay(zoneId).toInstant().toEpochMilli()); System.out.println("LocalDate -> Calendar: " + calendarFromLd.getTime()); } }
运行结果:
instant=2024-10-22T04:30:00Z localDateTime=2024-10-22T12:30 localDate=2024-10-22 Instant -> Calendar: Tue Oct 22 12:30:00 CST 2024 LocalDateTime -> Calendar: Tue Oct 22 12:30:00 CST 2024 LocalDate -> Calendar: Tue Oct 22 00:00:00 CST 2024