Skip to content

日期时间处理常用写法 ​

日期时间处理是开发中常见的需求。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-999999999

1.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.123

2.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转换

上一章节:字符串处理常用写法
下一章节:异常处理常用写法
返回目录:代码规范