Java 8 时间API完整案例指南
Java 8引入了全新的日期时间API(java.time包),解决了旧API的线程安全性和设计问题,下面通过完整案例来学习。

环境准备
import java.time.*; import java.time.format.*; import java.time.temporal.*; import java.util.*; import java.util.stream.*;
基础日期时间操作
1 获取当前日期时间
public class BasicDateTimeDemo {
public static void main(String[] args) {
// 当前日期
LocalDate today = LocalDate.now();
System.out.println("当前日期: " + today);
// 当前时间
LocalTime currentTime = LocalTime.now();
System.out.println("当前时间: " + currentTime);
// 当前日期时间
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("当前日期时间: " + currentDateTime);
// 带时区的日期时间
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println("带时区的日期时间: " + zonedDateTime);
// 指定时区
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println("东京时间: " + tokyoTime);
}
}
2 创建指定日期时间
public class CreateDateTimeDemo {
public static void main(String[] args) {
// 创建指定日期
LocalDate date = LocalDate.of(2024, 3, 15);
System.out.println("指定日期: " + date);
// 创建指定时间
LocalTime time = LocalTime.of(14, 30, 45, 100);
System.out.println("指定时间: " + time);
// 创建指定日期时间
LocalDateTime dateTime = LocalDateTime.of(2024, 3, 15, 14, 30, 45);
System.out.println("指定日期时间: " + dateTime);
// 从字符串解析
LocalDate parsedDate = LocalDate.parse("2024-03-15");
System.out.println("解析日期: " + parsedDate);
LocalDateTime parsedDateTime = LocalDateTime.parse("2024-03-15T14:30:45");
System.out.println("解析日期时间: " + parsedDateTime);
// 使用自定义格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate customDate = LocalDate.parse("2024/03/15", formatter);
System.out.println("自定义格式日期: " + customDate);
}
}
日期时间操作
1 加减操作
public class DateTimeArithmeticDemo {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
// 加天、周、月、年
LocalDate plusDays = today.plusDays(10);
LocalDate plusWeeks = today.plusWeeks(2);
LocalDate plusMonths = today.plusMonths(3);
LocalDate plusYears = today.plusYears(1);
System.out.println(" " + today);
System.out.println("加10天: " + plusDays);
System.out.println("加2周: " + plusWeeks);
System.out.println("加3月: " + plusMonths);
System.out.println("加1年: " + plusYears);
// 减天、周、月、年
LocalDate minusDays = today.minusDays(5);
LocalDate minusMonths = today.minusMonths(2);
System.out.println("减5天: " + minusDays);
System.out.println("减2月: " + minusMonths);
// 使用TemporalAmount
LocalDate plusPeriod = today.plus(Period.ofYears(1).plusMonths(2).plusDays(3));
System.out.println("加1年2月3天: " + plusPeriod);
// 时间加减
LocalTime time = LocalTime.of(10, 30);
LocalTime plusHours = time.plusHours(2);
LocalTime minusMinutes = time.minusMinutes(45);
System.out.println("时间加2小时: " + plusHours);
System.out.println("时间减45分钟: " + minusMinutes);
}
}
2 日期时间修改
public class DateTimeModifyDemo {
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.of(2024, 3, 15, 14, 30, 45);
System.out.println("原始: " + dateTime);
// 修改年份
LocalDateTime withYear = dateTime.withYear(2025);
System.out.println("修改年份: " + withYear);
// 修改月份
LocalDateTime withMonth = dateTime.withMonth(12);
System.out.println("修改月份: " + withMonth);
// 修改天
LocalDateTime withDay = dateTime.withDayOfMonth(1);
System.out.println("修改天: " + withDay);
// 修改小时
LocalDateTime withHour = dateTime.withHour(9);
System.out.println("修改小时: " + withHour);
// 修改时间部分
LocalDateTime withTime = dateTime.with(LocalTime.NOON);
System.out.println("修改为中午: " + withTime);
// 修改日期部分
LocalDateTime withDate = dateTime.with(LocalDate.of(2023, 1, 1));
System.out.println("修改日期: " + withDate);
// 使用ChronoField
LocalDateTime withField = dateTime.with(ChronoField.DAY_OF_WEEK, 1); // 设为星期一
System.out.println("设为周一: " + withField);
}
}
日期时间比较
public class DateTimeCompareDemo {
public static void main(String[] args) {
LocalDate date1 = LocalDate.of(2024, 3, 15);
LocalDate date2 = LocalDate.of(2024, 3, 20);
// 比较日期
System.out.println("date1是否在date2之前: " + date1.isBefore(date2));
System.out.println("date1是否在date2之后: " + date1.isAfter(date2));
System.out.println("date1是否等于date2: " + date1.isEqual(date2));
// compareTo方法
int comparison = date1.compareTo(date2);
System.out.println("比较结果: " + comparison); // 负数表示date1在date2之前
// 时间比较
LocalTime time1 = LocalTime.of(10, 30);
LocalTime time2 = LocalTime.of(11, 30);
System.out.println("time1是否早于time2: " + time1.isBefore(time2));
// 日期时间比较
LocalDateTime dt1 = LocalDateTime.of(2024, 3, 15, 10, 30);
LocalDateTime dt2 = LocalDateTime.of(2024, 3, 15, 11, 30);
System.out.println("dt1是否早于dt2: " + dt1.isBefore(dt2));
// 判断是否闰年
System.out.println("2024是闰年吗: " + date1.isLeapYear());
// 检查日期有效性
System.out.println("2月29日是否有效: " + Year.isLeap(2024));
}
}
日期时间间隔
public class DurationPeriodDemo {
public static void main(String[] args) {
// Period: 日期之间的间隔(年、月、日)
LocalDate startDate = LocalDate.of(2023, 1, 1);
LocalDate endDate = LocalDate.of(2024, 3, 15);
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());
// Duration: 时间之间的间隔(小时、分钟、秒)
LocalTime startTime = LocalTime.of(10, 30, 0);
LocalTime endTime = LocalTime.of(14, 45, 30);
Duration duration = Duration.between(startTime, endTime);
System.out.println("时间间隔: " + duration);
System.out.println("间隔小时: " + duration.toHours());
System.out.println("间隔分钟: " + duration.toMinutes());
System.out.println("间隔秒: " + duration.getSeconds());
// 使用ChronoUnit计算
LocalDateTime startDateTime = LocalDateTime.of(2024, 3, 1, 10, 30);
LocalDateTime endDateTime = LocalDateTime.of(2024, 3, 15, 14, 45);
long daysBetween = ChronoUnit.DAYS.between(startDateTime, endDateTime);
long hoursBetween = ChronoUnit.HOURS.between(startDateTime, endDateTime);
long minutesBetween = ChronoUnit.MINUTES.between(startDateTime, endDateTime);
System.out.println("日期时间间隔天数: " + daysBetween);
System.out.println("日期时间间隔小时: " + hoursBetween);
System.out.println("日期时间间隔分钟: " + minutesBetween);
// 创建指定的Period和Duration
Period customPeriod = Period.of(2, 3, 5); // 2年3月5天
Duration customDuration = Duration.ofHours(24).plusMinutes(30); // 24小时30分钟
System.out.println("自定义间隔: " + customPeriod + " 和 " + customDuration);
}
}
格式化和解析
public class DateTimeFormatDemo {
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.now();
// 内置格式
System.out.println("ISO日期: " + dateTime.format(DateTimeFormatter.ISO_DATE));
System.out.println("ISO日期时间: " + dateTime.format(DateTimeFormatter.ISO_DATE_TIME));
System.out.println("BASIC_ISO日期: " + dateTime.format(DateTimeFormatter.BASIC_ISO_DATE));
// 自定义格式
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
System.out.println("自定义格式: " + dateTime.format(customFormatter));
// 多种格式模式
String[] patterns = {
"yyyy-MM-dd",
"yyyy/MM/dd",
"dd-MM-yyyy",
"MMM dd, yyyy",
"EEEE, MMM dd yyyy HH:mm:ss",
"yyyy年MM月dd日 EEEE HH时mm分ss秒"
};
for (String pattern : patterns) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
System.out.println(pattern + " => " + dateTime.format(formatter));
}
// 解析字符串
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate parsedDate = LocalDate.parse("2024/03/15", parseFormatter);
System.out.println("解析结果: " + parsedDate);
// 使用Locale
DateTimeFormatter localeFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy", Locale.US);
System.out.println("美国格式: " + dateTime.format(localeFormatter));
// 使用DateTimeFormatterBuilder
DateTimeFormatter complexFormatter = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd")
.appendLiteral(" at ")
.appendPattern("HH:mm")
.toFormatter();
System.out.println("复杂格式: " + dateTime.format(complexFormatter));
}
}
时区处理
public class ZoneHandleDemo {
public static void main(String[] args) {
// 所有时区
Set<String> allZones = ZoneId.getAvailableZoneIds();
System.out.println("可用时区数量: " + allZones.size());
// 常用时区
String[] commonZones = {"Asia/Shanghai", "Asia/Tokyo", "America/New_York", "Europe/London"};
// 显示不同时区的时间
LocalDateTime now = LocalDateTime.now();
System.out.println("本地时间: " + now);
for (String zoneId : commonZones) {
ZonedDateTime zonedDateTime = now.atZone(ZoneId.of(zoneId));
System.out.println(zoneId + ": " + zonedDateTime);
}
// 时区转换
ZonedDateTime shanghaiTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime tokyoTime = shanghaiTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
ZonedDateTime newYorkTime = shanghaiTime.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println("\n上海时间: " + shanghaiTime);
System.out.println("东京时间: " + tokyoTime);
System.out.println("纽约时间: " + newYorkTime);
// 与UTC的偏移量
ZoneOffset offset = ZoneOffset.of("+08:00");
OffsetDateTime offsetTime = OffsetDateTime.now(offset);
System.out.println("带偏移时间: " + offsetTime);
// 使用ZoneOffset计算
LocalDateTime baseTime = LocalDateTime.of(2024, 3, 15, 12, 0);
ZonedDateTime utcTime = baseTime.atZone(ZoneOffset.UTC);
ZonedDateTime cstTime = utcTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));
System.out.println("UTC时间: " + utcTime);
System.out.println("中国时间: " + cstTime);
}
}
日期时间工具类
public class DateTimeUtilsDemo {
public static void main(String[] args) {
// 获取日期各部分
LocalDateTime now = LocalDateTime.now();
System.out.println("年: " + now.getYear());
System.out.println("月: " + now.getMonthValue());
System.out.println("日: " + now.getDayOfMonth());
System.out.println("小时: " + now.getHour());
System.out.println("分钟: " + now.getMinute());
System.out.println("秒: " + now.getSecond());
// 获取星期和月份名称
DayOfWeek dayOfWeek = now.getDayOfWeek();
Month month = now.getMonth();
System.out.println("星期: " + dayOfWeek);
System.out.println("月份: " + month);
System.out.println("今天是星期几: " + dayOfWeek.getValue()); // 1-7
// 日期调整器
LocalDate date = LocalDate.of(2024, 3, 15);
// 当月最后一天
LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
// 下个月第一天
LocalDate firstDayOfNextMonth = date.with(TemporalAdjusters.firstDayOfNextMonth());
// 当月第一个星期一
LocalDate firstMonday = date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
// 这个月的第二个星期日
LocalDate secondSunday = date.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.SUNDAY));
System.out.println("当月最后一天: " + lastDayOfMonth);
System.out.println("下月第一天: " + firstDayOfNextMonth);
System.out.println("当月第一个周一: " + firstMonday);
System.out.println("当月第二个周日: " + secondSunday);
}
}
综合案例:日期时间处理工具
public class DateTimeUtility {
// 1. 计算年龄
public static int calculateAge(LocalDate birthDate) {
return Period.between(birthDate, LocalDate.now()).getYears();
}
// 2. 格式化日期
public static String formatDate(LocalDate date, String pattern) {
return date.format(DateTimeFormatter.ofPattern(pattern));
}
// 3. 获取日期所在季度
public static int getQuarter(LocalDate date) {
return (date.getMonthValue() - 1) / 3 + 1;
}
// 4. 判断是否工作日
public static boolean isWorkingDay(LocalDate date) {
DayOfWeek day = date.getDayOfWeek();
return day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY;
}
// 5. 获取两个日期之间所有日期
public static List<LocalDate> getDatesBetween(LocalDate start, LocalDate end) {
return Stream.iterate(start, date -> date.plusDays(1))
.limit(ChronoUnit.DAYS.between(start, end) + 1)
.collect(Collectors.toList());
}
// 6. 日期时间转时间戳并返回
public static long toTimestamp(LocalDateTime dateTime) {
return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
// 7. 时间戳转日期时间
public static LocalDateTime fromTimestamp(long timestamp) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
}
public static void main(String[] args) {
// 测试各种方法
LocalDate birthDate = LocalDate.of(1990, 5, 15);
System.out.println("年龄: " + calculateAge(birthDate));
LocalDate today = LocalDate.now();
System.out.println("格式化日期: " + formatDate(today, "yyyy年MM月dd日"));
System.out.println("所在季度: " + getQuarter(today) + "季度");
System.out.println("是否工作日: " + (isWorkingDay(today) ? "是" : "否"));
// 获取本周的日期
LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
LocalDate sunday = monday.plusDays(6);
List<LocalDate> weekDates = getDatesBetween(monday, sunday);
System.out.println("本周日期: " + weekDates);
// 时间戳转换
long timestamp = toTimestamp(LocalDateTime.now());
System.out.println("时间戳: " + timestamp);
System.out.println("还原时间: " + fromTimestamp(timestamp));
}
}
实际应用案例
public class RealWorldApplications {
public static void main(String[] args) {
// 场景1:会议安排
LocalDateTime meetingStart = LocalDateTime.of(2024, 3, 15, 10, 0);
LocalDateTime meetingEnd = meetingStart.plusHours(2).plusMinutes(30);
Duration meetingDuration = Duration.between(meetingStart, meetingEnd);
System.out.println("会议时长: " + meetingDuration.toMinutes() + "分钟");
// 场景2:订单超时处理
LocalDateTime orderTime = LocalDateTime.now().minusMinutes(30);
Duration timeout = Duration.between(orderTime, LocalDateTime.now());
boolean isExpired = timeout.toMinutes() > 30;
System.out.println("订单是否超时: " + (isExpired ? "已超时" : "未超时"));
// 场景3:日历事件
LocalDate today = LocalDate.now();
LocalDate eventDate = today.plusDays(7);
boolean isUpcoming = eventDate.isAfter(today) && eventDate.isBefore(today.plusWeeks(2));
System.out.println("事件是否在两周内: " + isUpcoming);
// 场景4:生日提醒
LocalDate personBirthday = LocalDate.of(1990, 3, 15);
LocalDate nextBirthday = personBirthday.withYear(today.getYear());
if (nextBirthday.isBefore(today)) {
nextBirthday = nextBirthday.plusYears(1);
}
long daysUntilBirthday = ChronoUnit.DAYS.between(today, nextBirthday);
System.out.println("距离生日还有: " + daysUntilBirthday + "天");
// 场景5:日志时间处理
LocalDateTime logTime = LocalDateTime.now();
String logTimestamp = logTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
System.out.println("日志时间戳: " + logTimestamp);
// 场景6:时间范围判断
LocalTime now = LocalTime.now();
LocalTime startWork = LocalTime.of(9, 0);
LocalTime endWork = LocalTime.of(18, 0);
boolean isWorking = !now.isBefore(startWork) && !now.isAfter(endWork);
System.out.println("是否在工作时间: " + (isWorking ? "是" : "否"));
}
}
Java 8时间API的优势:
- 不可变性:所有类都是不可变的,线程安全
- 清晰的方法名:如
plusDays(),minusMonths(),withYear()等 - 丰富的格式化选项:支持自定义模式和本地化
- 完整的时区支持:可以轻松处理不同时区的转换
- 精确的时间计算:支持纳秒级别的精度
- 与旧API的兼容:提供了
toInstant()等方法转换
这些API使得Java中的日期时间处理变得简单、清晰且不易出错。