当前位置: 首页 > news >正文

Java 8 LocalDate 日期操作全攻略

Java 中的 java.time.LocalDate 类是 Java 8 引入的新日期时间 API (JSR 310) 的核心类型之一。它代表一个不带时区信息日期,通常格式为 年-月-日(例如:2023-10-27)。它只包含日期部分(年、月、日),不包含时间(时、分、秒、纳秒)和时区信息

核心特性

  1. 不可变性 (Immutable): LocalDate 的所有实例都是不可变的。任何修改操作(如加天数、减月份)都会返回一个新的 LocalDate 对象,原对象保持不变。这是线程安全的关键。
  2. 无时区 (Time-Zone Agnostic): 它只表示日历日期(如生日、节假日、事件日期),与一天中的具体时间和地球上的哪个位置无关。如果需要表示特定的时刻或考虑时区,应使用 Instant, ZonedDateTimeOffsetDateTime
  3. ISO-8601 标准: 默认遵循 ISO-8601 日历系统(即公历/格里高利历)。这是国际通用的标准日期格式 YYYY-MM-DD
  4. 丰富的 API: 提供了大量便捷、直观的方法用于日期的计算、比较、解析和格式化。

主要用途

  • 表示生日、纪念日、事件日期、截止日期等仅需日期信息的场景。
  • 进行日期计算(如加/减天数、周数、月数、年数)。
  • 比较两个日期的先后。
  • 获取日期的组成部分(年、月、日、星期几)。
  • 格式化日期输出或解析字符串为日期。

常用创建方式

  1. 获取当前日期:

    LocalDate today = LocalDate.now(); // 使用系统默认时区的当前日期
    
  2. 指定年、月、日:

    LocalDate specificDate1 = LocalDate.of(2023, 10, 27); // 2023年10月27日
    LocalDate specificDate2 = LocalDate.of(2023, Month.OCTOBER, 27); // 使用 Month 枚举更清晰
    
  3. 解析 ISO 格式字符串 (YYYY-MM-DD):

    LocalDate parsedDate = LocalDate.parse("2023-10-27"); // 直接解析标准格式
    
  4. 解析自定义格式字符串: 使用 DateTimeFormatter

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    LocalDate customParsedDate = LocalDate.parse("27/10/2023", formatter);
    
  5. 从纪元日开始计算:

    LocalDate epochDay = LocalDate.ofEpochDay(365); // 1970-01-01 + 365天 = 1971-01-01
    
  6. 获取指定年份的第几天:

    LocalDate dayOfYear = LocalDate.ofYearDay(2023, 300); // 2023年的第300天
    

常用操作与方法

  1. 获取日期组成部分:

    int year = today.getYear(); // 获取年份 (e.g., 2023)
    Month month = today.getMonth(); // 获取月份枚举 (e.g., Month.OCTOBER)
    int monthValue = today.getMonthValue(); // 获取月份数字 (1-12) (e.g., 10)
    int dayOfMonth = today.getDayOfMonth(); // 获取月份中的第几天 (1-31) (e.g., 27)
    DayOfWeek dayOfWeek = today.getDayOfWeek(); // 获取星期几枚举 (e.g., DayOfWeek.FRIDAY)
    int dayOfYear = today.getDayOfYear(); // 获取年份中的第几天 (1-366) (e.g., 300)
    
  2. 日期比较:

    boolean isBefore = date1.isBefore(date2); // date1 是否在 date2 之前
    boolean isAfter = date1.isAfter(date2); // date1 是否在 date2 之后
    boolean isEqual = date1.isEqual(date2); // date1 是否等于 date2
    int comparison = date1.compareTo(date2); // 比较: 负(前), 零(等), 正(后)
    
  3. 日期计算 (加减):

    LocalDate tomorrow = today.plusDays(1); // 加1天
    LocalDate nextWeek = today.plusWeeks(1); // 加1周
    LocalDate nextMonth = today.plusMonths(1); // 加1月 (智能处理月末)
    LocalDate nextYear = today.plusYears(1); // 加1年LocalDate yesterday = today.minusDays(1); // 减1天
    LocalDate lastMonth = today.minusMonths(1); // 减1月
    // 其他 minusWeeks, minusYears 类似
    
  4. 调整日期 (TemporalAdjusters): 更复杂的调整,如获取本月第一天、最后一天、下一个星期一等。

    LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
    LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
    LocalDate nextMonday = today.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
    LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
    
  5. 计算日期差:

    • 使用 Period (适合年、月、日差):
      Period period = Period.between(startDate, endDate);
      int years = period.getYears();
      int months = period.getMonths();
      int days = period.getDays(); // 注意:这个差不是总天数,是“年/月”之后剩余的天数差
      
    • 使用 ChronoUnit (适合特定单位的总差):
      long daysBetween = ChronoUnit.DAYS.between(startDate, endDate); // 总天数差
      long monthsBetween = ChronoUnit.MONTHS.between(startDate, endDate); // 总月数差
      long yearsBetween = ChronoUnit.YEARS.between(startDate, endDate); // 总年数差
      
  6. 日期判断:

    boolean isLeapYear = today.isLeapYear(); // 是否是闰年
    int lengthOfMonth = today.lengthOfMonth(); // 该月有多少天 (28, 29, 30, 31)
    int lengthOfYear = today.lengthOfYear(); // 该年有多少天 (365 or 366)
    
  7. 格式化输出:

    String isoDate = today.toString(); // "2023-10-27" (ISO-8601)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 EEEE");
    String formattedDate = today.format(formatter); // e.g., "2023年10月27日 星期五"
    

重要注意事项

  1. 时区无关性: LocalDate.now() 获取的是系统默认时区的当前日期。如果需要在特定时区获取当前日期,应使用:

    LocalDate todayInTokyo = LocalDate.now(ZoneId.of("Asia/Tokyo"));
    

    虽然 LocalDate 本身没有时区,但获取“当前日期”这个行为依赖于时区(因为不同时区进入新一天的时间不同)。

  2. 月末处理: plusMonths(), minusMonths(), withMonth() 等方法能智能处理月末日期。例如:

    LocalDate jan31 = LocalDate.of(2023, 1, 31);
    LocalDate feb28 = jan31.plusMonths(1); // 2023-02-28 (非闰年)
    LocalDate mar31 = feb28.plusMonths(1); // 2023-03-31
    
  3. 与旧 Date/Calendar 转换:

    • 虽然不推荐混用新旧API,但有时需要转换:
      // LocalDate -> java.util.Date (通过 Instant + ZoneId)
      Date oldDate = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
      // java.util.Date -> LocalDate (通过 Instant + ZoneId)
      LocalDate newDate = oldDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
      

总结

LocalDate 是 Java 现代日期时间 API 中用于表示纯日期(年-月-日)的核心类。它的不可变性、线程安全性、丰富的操作方法和清晰的语义使其成为处理日期相关逻辑的理想选择。在开发中,应优先使用 LocalDateLocalTimeLocalDateTimeZonedDateTimejava.time 包下的类,避免使用过时且易出错的 java.util.Datejava.util.Calendar

http://www.lryc.cn/news/587234.html

相关文章:

  • CS课程项目设计1:交互友好的井字棋游戏
  • 【多线程】 线程池设多大才合理?CPU 密集型和 I/O 密集型的终极公式
  • 深度学习图像分类数据集—七种树叶识别分类
  • AI生成单词消消乐游戏. HTML代码
  • LeetCode 2401.最长优雅子数组
  • Ampace厦门新能安科技Verify 测评演绎数字推理及四色测评考点分析、SHL真题题库
  • 【sql学习之拉链表】
  • 系规备考论文:论IT服务知识管理
  • MyBatis框架进阶指南:深入理解CRUD与参数映射
  • CVE-2022-0609
  • Oracle SQL - 使用行转列PIVOT减少表重复扫描(实例)
  • 常用的docker命令备份
  • Docker从环境配置到应用上云的极简路径
  • 《Google 软件工程》:如何写好文档?
  • Qt窗口:QToolBar、QStatusBar、QDockWidget、QDialog
  • QT 多线程 管理串口
  • Vue框架之计算属性与侦听器详解
  • 深入理解 LangChain:AI 应用开发的全新范式
  • openEuler欧拉系统重置密码
  • 标注识别 自己的数据集20张 roboflow 实例分割
  • 基于requests_html的爬虫实战
  • 【DVWA系列】——File Upload——low详细教程(webshell工具冰蝎)
  • Vue Router 完全指南:从入门到实战,高效管理前端路由
  • 12.I/O复用
  • 光盘处理难题不用愁,DVDFab 来救场
  • 博客项目 laravel vue mysql 第五章 标签功能
  • 从 Intel MacBook 迁移到 ARM MacBook 的完整指南
  • 【牛客刷题】四个选项:高考选择题方案统计(并查集+动态规划)
  • 【基于开源大模型(如deepseek)开发应用及其发展趋势的一点思考】
  • 时序预测 | Matlab代码实现VMD-TCN-GRU-MATT变分模态分解时间卷积门控循环单元多头注意力多变量时序预测