日期时间处理常用写法
日期时间处理是开发中常见的需求。Java 8引入了新的时间API,提供了更好的日期时间处理能力。本文详细介绍日期时间处理的常用写法和最佳实践。
📋 目录
🎯 一、Java 8+ 时间API
1.1 LocalDate、LocalTime、LocalDateTime
创建日期时间:
java
// LocalDate(日期)
LocalDate date1 = LocalDate.now(); // 当前日期
LocalDate date2 = LocalDate.of(2024, 1, 1); // 指定日期
LocalDate date3 = LocalDate.of(2024, Month.JANUARY, 1); // 使用Month枚举
LocalDate date4 = LocalDate.parse("2024-01-01"); // 从字符串解析
// LocalTime(时间)
LocalTime time1 = LocalTime.now(); // 当前时间
LocalTime time2 = LocalTime.of(12, 30, 45); // 指定时间
LocalTime time3 = LocalTime.of(12, 30, 45, 123456789); // 包含纳秒
LocalTime time4 = LocalTime.parse("12:30:45"); // 从字符串解析
// LocalDateTime(日期时间)
LocalDateTime dateTime1 = LocalDateTime.now(); // 当前日期时间
LocalDateTime dateTime2 = LocalDateTime.of(2024, 1, 1, 12, 30);
LocalDateTime dateTime3 = LocalDateTime.of(date2, time2); // 组合日期和时间
LocalDateTime dateTime4 = LocalDateTime.parse("2024-01-01T12:30:45");获取日期时间字段:
java
LocalDateTime dateTime = LocalDateTime.now();
// 获取年
int year = dateTime.getYear(); // 2024
// 获取月
int month = dateTime.getMonthValue(); // 1-12
Month monthEnum = dateTime.getMonth(); // Month枚举
// 获取日
int day = dateTime.getDayOfMonth(); // 1-31
// 获取星期
DayOfWeek dayOfWeek = dateTime.getDayOfWeek(); // MONDAY-SUNDAY
int dayOfWeekValue = dayOfWeek.getValue(); // 1-7
// 获取时间
int hour = dateTime.getHour(); // 0-23
int minute = dateTime.getMinute(); // 0-59
int second = dateTime.getSecond(); // 0-59
int nano = dateTime.getNano(); // 0-9999999991.2 日期时间操作
日期加减:
java
LocalDate date = LocalDate.of(2024, 1, 1);
// 加天数
LocalDate plusDays = date.plusDays(10); // 2024-01-11
// 加周数
LocalDate plusWeeks = date.plusWeeks(2); // 2024-01-15
// 加月数
LocalDate plusMonths = date.plusMonths(1); // 2024-02-01
// 加年数
LocalDate plusYears = date.plusYears(1); // 2025-01-01
// 减天数
LocalDate minusDays = date.minusDays(5); // 2023-12-27
// 使用Period
Period period = Period.of(1, 2, 3); // 1年2个月3天
LocalDate result = date.plus(period);
// 使用Duration(用于时间)
LocalDateTime dateTime = LocalDateTime.now();
Duration duration = Duration.ofHours(2);
LocalDateTime result2 = dateTime.plus(duration);日期比较:
java
LocalDate date1 = LocalDate.of(2024, 1, 1);
LocalDate date2 = LocalDate.of(2024, 1, 10);
// 比较
boolean isBefore = date1.isBefore(date2); // true
boolean isAfter = date1.isAfter(date2); // false
boolean isEqual = date1.isEqual(date2); // false
// 计算天数差
long days = ChronoUnit.DAYS.between(date1, date2); // 9
// 计算月数差
long months = ChronoUnit.MONTHS.between(date1, date2);
// 计算年数差
long years = ChronoUnit.YEARS.between(date1, date2);
// 使用Period计算差值
Period period = Period.between(date1, date2);
int years2 = period.getYears();
int months2 = period.getMonths();
int days2 = period.getDays();日期修改:
java
LocalDate date = LocalDate.of(2024, 1, 15);
// 修改年
LocalDate withYear = date.withYear(2025); // 2025-01-15
// 修改月
LocalDate withMonth = date.withMonth(6); // 2024-06-15
// 修改日
LocalDate withDay = date.withDayOfMonth(20); // 2024-01-20
// 修改为当月第一天
LocalDate firstDay = date.withDayOfMonth(1); // 2024-01-01
// 修改为当月最后一天
LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); // 2024-01-31
// 修改为下个星期一
LocalDate nextMonday = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
// 修改为当月最后一个星期五
LocalDate lastFriday = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY));🎯 二、日期格式化
2.1 DateTimeFormatter
格式化日期:
java
LocalDateTime dateTime = LocalDateTime.now();
// 预定义格式
String format1 = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
// "2024-01-01T12:30:45"
String format2 = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE);
// "2024-01-01"
String format3 = dateTime.format(DateTimeFormatter.ISO_LOCAL_TIME);
// "12:30:45"
// 自定义格式
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format4 = dateTime.format(formatter1);
// "2024-01-01 12:30:45"
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String format5 = dateTime.format(formatter2);
// "2024年01月01日"
// 格式化模式
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("E, MMM dd, yyyy", Locale.CHINA);
String format6 = dateTime.format(formatter3);
// "星期一, 一月 01, 2024"解析日期:
java
// 解析字符串
String dateStr = "2024-01-01 12:30:45";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
// 解析日期
String dateStr2 = "2024-01-01";
LocalDate date = LocalDate.parse(dateStr2);
// 解析时间
String timeStr = "12:30:45";
LocalTime time = LocalTime.parse(timeStr);常用格式化模式:
java
// 日期格式
"yyyy-MM-dd" // 2024-01-01
"yyyy/MM/dd" // 2024/01/01
"dd-MM-yyyy" // 01-01-2024
"yyyy年MM月dd日" // 2024年01月01日
"EEEE, MMMM dd, yyyy" // Monday, January 01, 2024
// 时间格式
"HH:mm:ss" // 12:30:45
"hh:mm:ss a" // 12:30:45 PM
"HH:mm:ss.SSS" // 12:30:45.123
// 日期时间格式
"yyyy-MM-dd HH:mm:ss" // 2024-01-01 12:30:45
"yyyy-MM-dd'T'HH:mm:ss" // 2024-01-01T12:30:45
"yyyy-MM-dd HH:mm:ss.SSS" // 2024-01-01 12:30:45.1232.2 SimpleDateFormat(Java 8之前)
SimpleDateFormat使用:
java
// 格式化日期
Date date = new Date();
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = sdf1.format(date);
// 解析日期
String dateStr = "2024-01-01 12:30:45";
Date parsedDate = sdf1.parse(dateStr);
// 线程安全的DateFormat(推荐)
DateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
String formatted2 = sdf2.format(date);线程安全处理:
java
// 使用ThreadLocal保证线程安全
private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public String formatDate(Date date) {
return DATE_FORMAT.get().format(date);
}🎯 三、时区处理
3.1 ZonedDateTime
时区日期时间:
java
// 当前时区的日期时间
ZonedDateTime zonedDateTime1 = ZonedDateTime.now();
// 指定时区
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime zonedDateTime3 = ZonedDateTime.now(ZoneId.of("America/New_York"));
// 从LocalDateTime创建
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime4 = localDateTime.atZone(ZoneId.systemDefault());
// 时区转换
ZonedDateTime shanghaiTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime newYorkTime = shanghaiTime.withZoneSameInstant(ZoneId.of("America/New_York"));
// 获取时区信息
ZoneId zoneId = zonedDateTime1.getZone();
ZoneOffset offset = zonedDateTime1.getOffset();3.2 Instant
时间戳处理:
java
// 当前时间戳
Instant instant1 = Instant.now();
// 从毫秒创建
Instant instant2 = Instant.ofEpochMilli(System.currentTimeMillis());
// 从秒创建
Instant instant3 = Instant.ofEpochSecond(1704067200L);
// 转换为LocalDateTime
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant1, ZoneId.systemDefault());
// 转换为Date(旧API)
Date date = Date.from(instant1);
// 从Date转换
Instant instant4 = date.toInstant();🎯 四、日期计算
4.1 Period和Duration
Period(日期周期):
java
LocalDate date1 = LocalDate.of(2024, 1, 1);
LocalDate date2 = LocalDate.of(2024, 3, 15);
// 计算Period
Period period = Period.between(date1, date2);
int years = period.getYears(); // 0
int months = period.getMonths(); // 2
int days = period.getDays(); // 14
// 创建Period
Period period2 = Period.of(1, 2, 3); // 1年2个月3天
Period period3 = Period.ofYears(1);
Period period4 = Period.ofMonths(6);
Period period5 = Period.ofDays(30);Duration(时间周期):
java
LocalDateTime dateTime1 = LocalDateTime.of(2024, 1, 1, 10, 0, 0);
LocalDateTime dateTime2 = LocalDateTime.of(2024, 1, 1, 12, 30, 45);
// 计算Duration
Duration duration = Duration.between(dateTime1, dateTime2);
long seconds = duration.getSeconds(); // 9045秒
long minutes = duration.toMinutes(); // 150分钟
long hours = duration.toHours(); // 2小时
// 创建Duration
Duration duration2 = Duration.ofHours(2);
Duration duration3 = Duration.ofMinutes(30);
Duration duration4 = Duration.ofSeconds(60);
Duration duration5 = Duration.of(2, ChronoUnit.HOURS);4.2 ChronoUnit
时间单位计算:
java
LocalDateTime dateTime1 = LocalDateTime.of(2024, 1, 1, 10, 0, 0);
LocalDateTime dateTime2 = LocalDateTime.of(2024, 1, 15, 15, 30, 0);
// 计算时间差
long days = ChronoUnit.DAYS.between(dateTime1, dateTime2); // 14
long hours = ChronoUnit.HOURS.between(dateTime1, dateTime2); // 341
long minutes = ChronoUnit.MINUTES.between(dateTime1, dateTime2); // 20490
long seconds = ChronoUnit.SECONDS.between(dateTime1, dateTime2);
// 日期时间计算
LocalDateTime plus = dateTime1.plus(2, ChronoUnit.DAYS);
LocalDateTime minus = dateTime1.minus(1, ChronoUnit.MONTHS);4.3 TemporalAdjuster
日期调整器:
java
LocalDate date = LocalDate.of(2024, 1, 15);
// 当月第一天
LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
// 当月最后一天
LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
// 下个月第一天
LocalDate firstDayOfNextMonth = date.with(TemporalAdjusters.firstDayOfNextMonth());
// 当月最后一个星期X
LocalDate lastMonday = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY));
// 下一个星期X
LocalDate nextFriday = date.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
// 上一个星期X
LocalDate previousMonday = date.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
// 下一个或当天的星期X
LocalDate nextOrSameFriday = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY));
// 上一个或当天的星期X
LocalDate previousOrSameMonday = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));自定义调整器:
java
// 自定义调整器:下个工作日
TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(date -> {
DayOfWeek dayOfWeek = date.getDayOfWeek();
int daysToAdd = 1;
if (dayOfWeek == DayOfWeek.FRIDAY) {
daysToAdd = 3; // 周五加3天(周一)
} else if (dayOfWeek == DayOfWeek.SATURDAY) {
daysToAdd = 2; // 周六加2天(周一)
}
return date.plusDays(daysToAdd);
});
LocalDate date = LocalDate.of(2024, 1, 5); // 周五
LocalDate nextWorkDay = date.with(nextWorkingDay); // 2024-01-08(周一)🎯 五、新旧API转换
5.1 Date和LocalDateTime转换
Date转LocalDateTime:
java
Date date = new Date();
// 方式1:通过Instant
Instant instant = date.toInstant();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// 方式2:通过Instant和ZoneId
LocalDateTime localDateTime2 = date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();LocalDateTime转Date:
java
LocalDateTime localDateTime = LocalDateTime.now();
// 通过Instant转换
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
Date date = Date.from(instant);5.2 Calendar转换
Calendar转LocalDateTime:
java
Calendar calendar = Calendar.getInstance();
LocalDateTime localDateTime = LocalDateTime.ofInstant(
calendar.toInstant(),
calendar.getTimeZone().toZoneId()
);LocalDateTime转Calendar:
java
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
Calendar calendar = GregorianCalendar.from(zonedDateTime);🎯 六、常用日期工具类
6.1 日期工具类示例
工具类封装:
java
public class DateUtils {
// 格式化日期
public static String format(LocalDateTime dateTime, String pattern) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
return dateTime.format(formatter);
}
// 解析日期
public static LocalDateTime parse(String dateStr, String pattern) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
return LocalDateTime.parse(dateStr, formatter);
}
// 获取当天的开始时间
public static LocalDateTime startOfDay(LocalDate date) {
return date.atStartOfDay();
}
// 获取当天的结束时间
public static LocalDateTime endOfDay(LocalDate date) {
return date.atTime(LocalTime.MAX);
}
// 获取本周一
public static LocalDate startOfWeek(LocalDate date) {
return date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
}
// 获取本周日
public static LocalDate endOfWeek(LocalDate date) {
return date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
}
// 获取月初
public static LocalDate startOfMonth(LocalDate date) {
return date.with(TemporalAdjusters.firstDayOfMonth());
}
// 获取月末
public static LocalDate endOfMonth(LocalDate date) {
return date.with(TemporalAdjusters.lastDayOfMonth());
}
// 计算两个日期的天数差
public static long daysBetween(LocalDate start, LocalDate end) {
return ChronoUnit.DAYS.between(start, end);
}
// 判断是否为同一天
public static boolean isSameDay(LocalDate date1, LocalDate date2) {
return date1.isEqual(date2);
}
// 判断是否为工作日
public static boolean isWorkingDay(LocalDate date) {
DayOfWeek dayOfWeek = date.getDayOfWeek();
return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;
}
}📖 学习资源
官方文档
书籍推荐
- 《Java 8实战》 - Raoul-Gabriel Urma
✅ 学习检查清单
- [ ] 已掌握Java 8时间API的使用
- [ ] 已掌握日期格式化方法
- [ ] 已了解时区处理
- [ ] 已掌握日期计算方法
- [ ] 已熟悉新旧API转换