在 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