很早之前的日期工具类,输入指定日期或者年月,获取月份最后一天,发现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;
}