哪些Java案例展示了时间处理?

wen java案例 1

本文目录导读:

哪些Java案例展示了时间处理?

  1. 核心案例:新旧 API 对比与基础操作
  2. 时间计算与操作
  3. 时区处理
  4. 与数据库/系统交互
  5. 实际业务案例:日历与时间范围
  6. 常见陷阱与注意事项

Java 中时间处理的案例非常丰富,涵盖了从早期的 java.util.DateCalendar 到现代的 java.time(JSR-310)包,现代 Java 开发强烈推荐使用 java.time 包,因为它解决了旧 API 的线程安全、设计混乱等问题。

以下是一些典型的 Java 时间处理案例,按功能分类展示:


核心案例:新旧 API 对比与基础操作

场景:获取当前时间、格式化、解析。

旧 API(不推荐)

// 1. 获取当前时间
Date now = new Date();
System.out.println(now); // 输出:Tue Oct 24 10:30:00 CST 2023
// 2. 格式化(线程不安全)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = sdf.format(now);
System.out.println(formatted); // 输出:2023-10-24 10:30:00
// 3. 解析
String dateStr = "2023-10-24 10:30:00";
try {
    Date parsed = sdf.parse(dateStr);
} catch (ParseException e) {
    e.printStackTrace();
}

新 API(推荐)

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
// 1. 获取当前时间(不可变、线程安全)
LocalDateTime now = LocalDateTime.now();
System.out.println(now); // 输出:2023-10-24T10:30:00
// 2. 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(formatter);
System.out.println(formatted); // 输出:2023-10-24 10:30:00
// 3. 解析
String dateStr = "2023-10-24 10:30:00";
LocalDateTime parsed = LocalDateTime.parse(dateStr, formatter);

关键点:新 API 的 LocalDateLocalTimeLocalDateTime 是不可变对象,所有操作返回新实例,天然线程安全。


时间计算与操作

场景:加减天数、月份,获取前后日期,计算两个时间的差值。

import java.time.LocalDate;
import java.time.Period;
import java.time.Duration;
import java.time.LocalDateTime;
public class TimeCalculationExample {
    public static void main(String[] args) {
        // 1. 日期加减
        LocalDate today = LocalDate.now();
        LocalDate nextWeek = today.plusDays(7);
        LocalDate lastMonth = today.minusMonths(1);
        LocalDate nextYear = today.plusYears(1);
        System.out.println(" " + today);
        System.out.println("一周后: " + nextWeek);
        // 2. 计算两个日期之间的天数差
        LocalDate start = LocalDate.of(2023, 1, 1);
        LocalDate end = LocalDate.of(2023, 12, 31);
        Period period = Period.between(start, end);
        System.out.println("间隔: " + period.getYears() + "年, " 
                           + period.getMonths() + "月, " 
                           + period.getDays() + "天");
        // 3. 计算两个时间之间的精确秒/毫秒差
        LocalDateTime time1 = LocalDateTime.of(2023, 10, 24, 10, 0, 0);
        LocalDateTime time2 = LocalDateTime.of(2023, 10, 24, 12, 30, 0);
        Duration duration = Duration.between(time1, time2);
        System.out.println("时间差: " + duration.toHours() + "小时, " 
                           + duration.toMinutes() + "分钟");
    }
}

关键点Period 适用于日期(年月日),Duration 适用于时间(时分秒纳秒)。


时区处理

场景:不同时区的时间转换、获取时区时间。

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class TimeZoneExample {
    public static void main(String[] args) {
        // 1. 获取当前时区时间(系统默认时区)
        ZonedDateTime nowInLocal = ZonedDateTime.now();
        System.out.println("本地时区: " + nowInLocal);
        // 2. 获取指定时区时间
        ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");
        ZonedDateTime nowInTokyo = ZonedDateTime.now(tokyoZone);
        System.out.println("东京时间: " + nowInTokyo);
        // 3. 时区转换(从北京时间转为纽约时间)
        ZoneId beijingZone = ZoneId.of("Asia/Shanghai");
        ZoneId newYorkZone = ZoneId.of("America/New_York");
        ZonedDateTime beijingTime = ZonedDateTime.of(
            LocalDateTime.now(), beijingZone
        );
        ZonedDateTime newYorkTime = beijingTime.withZoneSameInstant(newYorkZone);
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV");
        System.out.println("北京: " + beijingTime.format(format));
        System.out.println("纽约: " + newYorkTime.format(format));
    }
}

关键点ZonedDateTime 用于带时区的日期时间,ZoneId 用于标识时区,withZoneSameInstant 用于在不同时区间转换。


与数据库/系统交互

场景:与数据库中的 TIMESTAMPDATE 类型互转,与旧 java.util.Date 互转。

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
public class InteropExample {
    public static void main(String[] args) {
        // 1. LocalDateTime 转 java.util.Date
        LocalDateTime localDateTime = LocalDateTime.now();
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        Date date = Date.from(instant);
        System.out.println("LocalDateTime -> Date: " + date);
        // 2. java.util.Date 转 LocalDateTime
        Date legacyDate = new Date();
        Instant legacyInstant = legacyDate.toInstant();
        LocalDateTime localFromLegacy = LocalDateTime.ofInstant(
            legacyInstant, ZoneId.systemDefault()
        );
        System.out.println("Date -> LocalDateTime: " + localFromLegacy);
        // 3. 与数据库交互 (JDBC 4.2+)
        // 数据库插入: preparedStatement.setObject(1, LocalDate.now());
        // 数据库读取: LocalDate date = resultSet.getObject("column", LocalDate.class);
        System.out.println("Java 8+ JDBC 直接支持 LocalDate/LocalDateTime");
    }
}

关键点

  • Java 8+ 的 JDBC 驱动直接支持 LocalDateLocalTimeLocalDateTime 类型。
  • Instant 是一个时间线上的瞬时点,可用于与旧 API 互转。

实际业务案例:日历与时间范围

场景:计算某个月有多少天、判断闰年、获取工作日等。

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class CalendarExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        // 1. 当月第一天和最后一天
        LocalDate firstDay = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDay = today.with(TemporalAdjusters.lastDayOfMonth());
        System.out.println("当月第一天: " + firstDay + ", 最后一天: " + lastDay);
        // 2. 下个周五
        LocalDate nextFriday = today.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
        System.out.println("下周五: " + nextFriday);
        // 3. 判断闰年
        boolean isLeap = today.isLeapYear();
        System.out.println(today.getYear() + " 是闰年吗? " + isLeap);
        // 4. 获取当月天数
        int daysInMonth = today.lengthOfMonth();
        System.out.println("本月有 " + daysInMonth + " 天");
    }
}

关键点TemporalAdjusters 类提供了丰富的日期调整器,如 firstDayOfMonth()next(DayOfWeek) 等。


常见陷阱与注意事项

案例:线程安全问题(旧 API 失败案例)

// 错误做法(多线程环境下)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 多个线程同时调用 parse() 会抛出异常或产生错误结果
// 正确做法
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// DateTimeFormatter 是线程安全的

案例:时间精度问题

// java.util.Date 的精度是毫秒
// LocalDateTime 的精度是纳秒
LocalDateTime now = LocalDateTime.now();
System.out.println(now.getNano()); // 输出纳秒部分,如 123456789

功能分类 推荐使用类 旧类(不推荐) 主要优势
日期(无时间) LocalDate java.sql.Date 清晰、不可变
时间(无日期) LocalTime java.sql.Time 清晰、不可变
日期+时间 LocalDateTime java.util.Date 不可变、线程安全
带时区 ZonedDateTime CalendarTimeZone 更语义化、易用
格式化解析 DateTimeFormatter SimpleDateFormat 线程安全、不可变

推荐学习路径

  1. 掌握 LocalDateLocalTimeLocalDateTime 的创建与基础运算。
  2. 学会使用 DateTimeFormatter 进行格式化。
  3. 理解时区概念,使用 ZonedDateTime 处理跨时区问题。
  4. 熟悉 PeriodDuration 做时间差值计算。
  5. 了解与数据库和旧系统的互转方式。

抱歉,评论功能暂时关闭!