java获取某个月最后一天

很早之前的日期工具类,输入指定日期或者年月,获取月份最后一天,发现2025年2月,返回的是2025年3月3日,经过网上资料查找,找到的正确的写法;

java 复制代码
       /**
     * 根据指定日期获取该日期所在月份最后一天
     * @param date 指定日期
     * @return 月份最后一天
     */
    public static Date getLastDateOfMonthByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        return getLastDayOfMonth(year, month);
    }

    /**
     * 获取指定年月的最后一天
     *
     * @param year 年
     * @param month 月
     * @return 月份最后一天
     */
    public static Date getLastDayOfMonth(int year, int month) {
        try {
            Calendar cal = Calendar.getInstance();
            //设置年份
            cal.set(Calendar.YEAR, year);
            //设置月份
            cal.set(Calendar.MONTH, month - 1);
            //获取某月最大天数
            int lastDay = cal.getActualMaximum(Calendar.DATE);
            //设置日历中月份的最大天数
            cal.set(Calendar.DAY_OF_MONTH, lastDay);
            //格式化日期
            SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_YYYYMMDD);
            Date date = sdf.parse(sdf.format(cal.getTime()));
            return date;
        } catch (ParseException e) {
            log.error("系统解析日期异常 : " + e.getMessage(), e);
        }
        return null;
    }

正确的写法。其实就是,把当月的第几天,先设置成1;第二步和错误代码是一样的

1、DAY_OF_MONTH 设置为 1;2.DATE设置日期中月份最大的天数,其中最大的天数通过:cal.getActualMaximum(Calendar.DATE) 获取;

参考的这篇文章:java获取某个月最后一天_java 查询当天12个月后的最后一天-CSDN博客

java 复制代码
/**
     * 获取指定年月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastDayOfMonth(int year, int month) {
        try {
            Calendar cal = Calendar.getInstance();
            //设置年份
            cal.set(Calendar.YEAR, year);
            //设置月份
            cal.set(Calendar.MONTH, month - 1);
            //设置月份中的第几天,即日期,范围是 1~31;变成2025-02-01
            //DAY_OF_MONTH和DATE效果完全是一样的(推荐用DAY_OF_MONTH)
            cal.set(Calendar.DAY_OF_MONTH, 1);
            //获取某月最大天数 (所以这里换成:DAY_OF_MONTH)
            int lastDay = cal.getActualMaximum(Calendar.DATE);
            //设置日历中月份的最大天数 (所以这里换成:DAY_OF_MONTH)变成2025-02-28
            cal.set(Calendar.DATE, lastDay);
            //格式化日期
            SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_YYYYMMDD);
            Date date = sdf.parse(sdf.format(cal.getTime()));
            return date;
        } catch (ParseException e) {
            log.error("系统解析日期异常 : " + e.getMessage(), e);
        }
        return null;
    }

那既然效果是一样的,为什么要设置两遍呢,主要是因为 Calendar 的字段未完全同步 或 月份未正确设置,所以先设置月份,再设置日期

cal.set(Calendar.DAY_OF_MONTH, 1); // 临时设为 1 日,确保月份生效

cal.set(Calendar.DAY_OF_MONTH, lastDay);

出现问题可能的原因:

1、Calendar 的字段未完全同步

Calendar 使用 字段缓存机制,修改一个字段(如 MONTH)后,其他字段(如 DAY_OF_MONTH)可能不会自动更新,导致计算错误。

而,getActualMaximum() 依赖于当前字段值,如果 MONTH 未完全生效,计算的最大天数可能错误。 所以要:先设置 MONTH,再设 DAY_OF_MONTH

2、月份从 0 开始

Calendar.FEBRUARY 的值是 1,但 Calendar 内部处理时可能会因字段未同步导致月份偏移。

3、时间溢出(Roll-over)

如果 DAY_OF_MONTH 设置的值超过当前月份的最大天数,Calendar 会自动 进位到下个月(例如 2 月 30 日 → 3 月 2 日)。2月28日-》3月3日

也可以使用clear;但是感觉还是上面的好一点,推荐上面的;

java 复制代码
/**
     * 获取指定年月的最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastDayOfMonth(int year, int month) {
        try {
            Calendar cal = Calendar.getInstance();
            cal.clear();
            //Thu Jan 01 00:00:00 CST 1970
            //System.out.println(cal.getTime()); 
            //设置年份
            cal.set(Calendar.YEAR, year);
            //设置月份
            cal.set(Calendar.MONTH, month - 1);
            //设置日历中月份的最大天数
            cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
            //格式化日期
            SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_YYYYMMDD);
            Date date = sdf.parse(sdf.format(cal.getTime()));
            return date;
        } catch (ParseException e) {
            log.error("系统解析日期异常 : " + e.getMessage(), e);
        }
        return null;
    }

在 Java 的 Calendar 类中,clear() 方法用于重置 Calendar 对象的字段值,将其恢复到默认状态(即未设置任何时间值)

并且,clear() 不会修改 Calendar 的时区(TimeZone)或语言环境(Locale),这些属性需要通过 setTimeZone() 或 setLocale() 单独设置。

终稿

java 复制代码
       /**
     * 根据指定日期获取该日期所在月份最后一天
     * @param date 指定日期
     * @return 月份最后一天
     */
    public static Date getLastDateOfMonthByDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        return getLastDayOfMonth(year, month);
    }

    /**
     * 获取指定年月的最后一天
     *
     * @param year 年
     * @param month 月
     * @return 月份最后一天
     */
    public static Date getLastDayOfMonth(int year, int month) {
        try {
            Calendar cal = Calendar.getInstance();
            //设置年份
            cal.set(Calendar.YEAR, year);
            //设置月份
            cal.set(Calendar.MONTH, month - 1); 
            cal.set(Calendar.DAY_OF_MONTH, 1); 
            //设置日历中月份的最大天数
            cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
            //格式化日期
            SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_YYYYMMDD);
            Date date = sdf.parse(sdf.format(cal.getTime()));
            return date;
        } catch (ParseException e) {
            log.error("系统解析日期异常 : " + e.getMessage(), e);
        }
        return null;
    }