Java日期时间API详解:LocalDate、LocalTime、LocalDateTime
Java日期时间API详解:LocalDate、LocalTime、LocalDateTime
概述
Java 8引入了全新的日期时间API(java.time包),提供了更强大、更易用的日期时间处理能力。新的API是不可变的、线程安全的,解决了旧API(Date、Calendar)的许多问题。
1. LocalDate
import java.time.LocalDate;
import java.time.Month;
import java.time.DayOfWeek;
import java.time.temporal.TemporalAdjusters;
public class LocalDateExample {
public static void main(String[] args) {
// 创建LocalDate
LocalDate today = LocalDate.now();
System.out.println("今天: " + today);
LocalDate specificDate = LocalDate.of(2024, Month.JANUARY, 15);
System.out.println("特定日期: " + specificDate);
LocalDate fromString = LocalDate.parse("2024-01-15");
System.out.println("从字符串解析: " + fromString);
// 获取日期信息
System.out.println("年: " + today.getYear());
System.out.println("月: " + today.getMonth());
System.out.println("月份数字: " + today.getMonthValue());
System.out.println("日: " + today.getDayOfMonth());
System.out.println("星期: " + today.getDayOfWeek());
System.out.println("一年中的第几天: " + today.getDayOfYear());
// 日期操作
LocalDate tomorrow = today.plusDays(1);
System.out.println("明天: " + tomorrow);
LocalDate nextWeek = today.plusWeeks(1);
System.out.println("下周: " + nextWeek);
LocalDate nextMonth = today.plusMonths(1);
System.out.println("下个月: " + nextMonth);
LocalDate lastMonth = today.minusMonths(1);
System.out.println("上个月: " + lastMonth);
// 日期调整
LocalDate nextMonday = today.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println("下周一: " + nextMonday);
LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("本月最后一天: " + lastDayOfMonth);
// 日期比较
System.out.println("是否在之后: " + today.isAfter(specificDate));
System.out.println("是否在之前: " + today.isBefore(specificDate));
System.out.println("是否相等: " + today.equals(specificDate));
}
}
2. LocalTime
import java.time.LocalTime;
public class LocalTimeExample {
public static void main(String[] args) {
// 创建LocalTime
LocalTime now = LocalTime.now();
System.out.println("现在: " + now);
LocalTime specificTime = LocalTime.of(14, 30, 0);
System.out.println("特定时间: " + specificTime);
LocalTime fromString = LocalTime.parse("14:30:00");
System.out.println("从字符串解析: " + fromString);
// 获取时间信息
System.out.println("时: " + now.getHour());
System.out.println("分: " + now.getMinute());
System.out.println("秒: " + now.getSecond());
System.out.println("纳秒: " + now.getNano());
// 时间操作
LocalTime later = now.plusHours(2);
System.out.println("两小时后: " + later);
LocalTime earlier = now.minusMinutes(30);
System.out.println("30分钟前: " + earlier);
// 时间比较
System.out.println("是否在之后: " + now.isAfter(specificTime));
System.out.println("是否在之前: " + now.isBefore(specificTime));
}
}
3. LocalDateTime
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeExample {
public static void main(String[] args) {
// 创建LocalDateTime
LocalDateTime now = LocalDateTime.now();
System.out.println("现在: " + now);
LocalDateTime specificDateTime = LocalDateTime.of(2024, 1, 15, 14, 30);
System.out.println("特定日期时间: " + specificDateTime);
// 从LocalDate和LocalTime组合
LocalDateTime combined = LocalDateTime.of(
LocalDate.of(2024, 1, 15),
LocalTime.of(14, 30)
);
System.out.println("组合: " + combined);
// 日期时间操作
LocalDateTime tomorrow = now.plusDays(1).plusHours(2);
System.out.println("明天此时加2小时: " + tomorrow);
// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(formatter);
System.out.println("格式化: " + formatted);
// 解析
LocalDateTime parsed = LocalDateTime.parse("2024-01-15 14:30:00", formatter);
System.out.println("解析: " + parsed);
// 提取日期和时间
System.out.println("日期: " + now.toLocalDate());
System.out.println("时间: " + now.toLocalTime());
}
}
4. Instant和Duration
import java.time.Instant;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
public class InstantDurationExample {
public static void main(String[] args) {
// Instant:时间戳
Instant now = Instant.now();
System.out.println("现在: " + now);
Instant fromMillis = Instant.ofEpochMilli(1705312200000L);
System.out.println("从毫秒: " + fromMillis);
Instant fromSeconds = Instant.ofEpochSecond(1705312200);
System.out.println("从秒: " + fromSeconds);
// Duration:时间间隔
Instant start = Instant.now();
// 模拟一些操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("持续时间: " + duration);
System.out.println("秒: " + duration.getSeconds());
System.out.println("毫秒: " + duration.toMillis());
// Duration计算
Duration twoHours = Duration.ofHours(2);
Duration thirtyMinutes = Duration.ofMinutes(30);
Duration total = twoHours.plus(thirtyMinutes);
System.out.println("总时间: " + total);
System.out.println("总分钟: " + total.toMinutes());
}
}
5. Period
import java.time.Period;
import java.time.LocalDate;
public class PeriodExample {
public static void main(String[] args) {
// Period:日期间隔
LocalDate startDate = LocalDate.of(2024, 1, 1);
LocalDate endDate = LocalDate.of(2024, 12, 31);
Period period = Period.between(startDate, endDate);
System.out.println("期间: " + period);
System.out.println("年: " + period.getYears());
System.out.println("月: " + period.getMonths());
System.out.println("天: " + period.getDays());
// Period计算
Period twoYears = Period.ofYears(2);
Period threeMonths = Period.ofMonths(3);
Period tenDays = Period.ofDays(10);
Period total = twoYears.plus(threeMonths).plus(tenDays);
System.out.println("总期间: " + total);
// 使用Period调整日期
LocalDate futureDate = LocalDate.now().plus(total);
System.out.println("未来日期: " + futureDate);
}
}
6. ZonedDateTime和时区
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class ZonedDateTimeExample {
public static void main(String[] args) {
// 获取当前时区的日期时间
ZonedDateTime now = ZonedDateTime.now();
System.out.println("现在: " + now);
// 指定时区
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println("东京时间: " + tokyoTime);
ZonedDateTime newYorkTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println("纽约时间: " + newYorkTime);
// 时区转换
ZonedDateTime converted = now.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println("伦敦时间: " + converted);
// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
String formatted = now.format(formatter);
System.out.println("格式化: " + formatted);
}
}
7. 实际应用示例
日期工具类
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class DateUtils {
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter DATETIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 获取当前日期字符串
public static String getCurrentDate() {
return LocalDate.now().format(DATE_FORMATTER);
}
// 获取当前日期时间字符串
public static String getCurrentDateTime() {
return LocalDateTime.now().format(DATETIME_FORMATTER);
}
// 计算两个日期之间的天数
public static long daysBetween(LocalDate start, LocalDate end) {
return ChronoUnit.DAYS.between(start, end);
}
// 计算两个日期之间的月数
public static long monthsBetween(LocalDate start, LocalDate end) {
return ChronoUnit.MONTHS.between(start, end);
}
// 判断是否是闰年
public static boolean isLeapYear(int year) {
return Year.isLeap(year);
}
// 获取某月的天数
public static int getDaysInMonth(int year, int month) {
return YearMonth.of(year, month).lengthOfMonth();
}
// 日期字符串转LocalDate
public static LocalDate parseDate(String dateStr) {
return LocalDate.parse(dateStr, DATE_FORMATTER);
}
// 日期时间字符串转LocalDateTime
public static LocalDateTime parseDateTime(String dateTimeStr) {
return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
}
public static void main(String[] args) {
System.out.println("当前日期: " + getCurrentDate());
System.out.println("当前日期时间: " + getCurrentDateTime());
LocalDate start = LocalDate.of(2024, 1, 1);
LocalDate end = LocalDate.of(2024, 12, 31);
System.out.println("2024年天数: " + daysBetween(start, end));
System.out.println("2024年是否闰年: " + isLeapYear(2024));
System.out.println("2024年2月天数: " + getDaysInMonth(2024, 2));
}
}
8. 最佳实践
- 使用新API:优先使用java.time包,而不是Date和Calendar
- 不可变对象:LocalDate、LocalTime等都是不可变的,线程安全
- 使用DateTimeFormatter:格式化日期时间
- 时区处理:使用ZonedDateTime处理时区相关操作
- 避免使用Date:Date是可变的,线程不安全
总结
Java 8引入的新日期时间API提供了更强大、更易用的日期时间处理能力。掌握LocalDate、LocalTime、LocalDateTime等类的使用,是现代Java编程的重要技能。