You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Calendar生成指定格式日期遇异常:时分错误、日期不符求助

问题排查与修复方案

一、去年同月1日00:00:00.000生成错误

问题原因

代码里用了Calendar.HOUR,这是12小时制字段,取值范围0-11(对应12AM到11AM、12PM到11PM)。设置c.set(Calendar.HOUR, 0)时,实际是把时间设为当天的12点(上午/下午取决于原时间时段),所以才会出现12:00:00.000的错误结果。

修复代码

把Calendar.HOUR替换为Calendar.HOUR_OF_DAY(24小时制字段,取值0-23):

private String getLastYear() {
    DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    Calendar c = Calendar.getInstance();
    c.add(Calendar.YEAR, -1);
    c.set(Calendar.DAY_OF_MONTH, 1);
    c.set(Calendar.HOUR_OF_DAY, 0); // 替换为24小时制字段
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);
    return format.format(c.getTime());
}

二、上月最后一天23:59:59.999生成错误

问题原因

直接对当前日期执行c.add(Calendar.MONTH, -1)会触发Calendar的自动调整机制:比如当前是3月31日,减一个月后会变成2月31日,但2月没有31天,Calendar会自动把日期调整为3月3日(平年)或3月2日(闰年)。此时再设置DAY_OF_MONTH为当月最大天数,实际取的是调整后月份的最大天数,最终得到的不是上月最后一天。

修复代码

先把日期调整到当月第一天,再减一个月定位到上月第一天,最后设置为上月最大天数:

private String getPreviousMonth() {
    DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); // 匹配目标格式
    Calendar c = Calendar.getInstance();
    c.set(Calendar.DAY_OF_MONTH, 1); // 先切换到当月第一天
    c.add(Calendar.MONTH, -1); // 减一个月,得到上月第一天
    c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH)); // 设置为上月最后一天
    c.set(Calendar.HOUR_OF_DAY, 23); // 统一用24小时制字段
    c.set(Calendar.MINUTE, 59);
    c.set(Calendar.SECOND, 59);
    c.set(Calendar.MILLISECOND, 999);
    return format.format(c.getTime());
}

额外优化建议

如果是Java 8及以上版本,建议使用java.time新日期API,比Calendar更简洁不易出错:

// 生成去年同月1日00:00:00.000
private String getLastYear() {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    LocalDateTime lastYearFirstDay = LocalDateTime.now()
            .minusYears(1)
            .withDayOfMonth(1)
            .withHour(0)
            .withMinute(0)
            .withSecond(0)
            .withNano(0);
    return lastYearFirstDay.format(formatter);
}

// 生成上月最后一天23:59:59.999
private String getPreviousMonth() {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    YearMonth lastMonth = YearMonth.now().minusMonths(1);
    LocalDateTime lastDayOfLastMonth = lastMonth.atEndOfMonth()
            .atTime(23, 59, 59, 999_000_000);
    return lastDayOfLastMonth.format(formatter);
}

内容的提问来源于stack exchange,提问作者Marco Frag Delle Monache

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 03:42:49