生成报表时计算报表的截止上报时间

背景

每张报表有个截止上报时间,截止时间的计算稍微复杂,下面记录一下自己的写作成果。当月月报截止时间下月xx号,当季季报截止时间下季第一个月。。。

数据结构

public enum ReportFrequencyEnum {

    YEAR("year", "年"),

    MONTH("month", "月"),

    HALF_YEAR("half_year", "半年"),

    SEASON("season", "季");

    ReportFrequencyEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }

    private String code;
    private String name;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取指定code的报表频率
     *
     * @param code 报表频率code
     * @return
     */
    public static ReportFrequencyEnum codeOf(String code) {
        for (ReportFrequencyEnum reportFrequencyEnum : ReportFrequencyEnum.values()) {
            if (reportFrequencyEnum.getCode().equals(code)) {
                return reportFrequencyEnum;
            }
        }
        log.warn("找不到指定code的报表频率,code={}", code);
        return null;
    }
}
@Data
@ApiModel("报表时间")
public class ReportTime {

    @NotNull
    @ApiModelProperty("年")
    private Integer year;

    @ApiModelProperty("月(1-12)")
    private Integer month;

    @ApiModelProperty("季(1-4)")
    private Integer season;

    @ApiModelProperty("半年(上/下)")
    private String halfYear;
}
/**
 * 报表上报截止时间配置
 * <p>
 * 示例:配置月报上报截止时间为下月18号
 * [{
 * "frequency":"month",
 * "monthAdd":0,
 * "day":18
 * }]
 *
 * @author wanghuidong
 * @date 2022/5/21 21:29
 */
@Data
public class ReportDeadlineTimeConfig {

    /**
     * 频度
     */
    private String frequency;

    /**
     * 月度增量
     */
    private Integer monthAdd;

    /**
     * 几号
     */
    private Integer day;
}

 

算法

 /**
     * 计算报表上报截止时间
     *
     * @param reportFrequencyEnum       报表频度
     * @param reportTime                报表时间
     * @param reportDeadlineTimeConfigs 报表截止时间配置
     * @return 截止时间
     */
    private Date calculateReportDeadlineTime(ReportFrequencyEnum reportFrequencyEnum, ReportTime reportTime, List<ReportDeadlineTimeConfig> reportDeadlineTimeConfigs) {
        //当前时间
        DateTime dateTime = DateTime.now();
        if (reportTime != null) {
            //指定报表时间计算截止时间
            switch (reportFrequencyEnum) {
                case YEAR:
                    //当年年报下年截止
                    dateTime.setField(DateField.YEAR, reportTime.getYear() + 1);
                    dateTime = DateUtil.truncate(dateTime, DateField.YEAR);
                    break;
                case MONTH:
                    //当月月报下月截止
                    dateTime.setField(DateField.YEAR, reportTime.getYear());
                    dateTime.setField(DateField.MONTH, reportTime.getMonth() - 1);
                    dateTime.offset(DateField.MONTH, 1);
                    dateTime = DateUtil.truncate(dateTime, DateField.MONTH);
                    break;
                case SEASON:
                    //当季季报下季截止
                    dateTime.setField(DateField.YEAR, reportTime.getYear());
                    switch (reportTime.getSeason()) {
                        case 1:
                            //1季报,2季度截止
                            dateTime.setField(DateField.MONTH, 3);
                            break;
                        case 2:
                            //2季报,3季度截止
                            dateTime.setField(DateField.MONTH, 6);
                            break;
                        case 3:
                            //3季报,4季度截止
                            dateTime.setField(DateField.MONTH, 9);
                            break;
                        case 4:
                            //4季报,下一年1季度截止
                            dateTime.offset(DateField.YEAR, 1);
                            dateTime.setField(DateField.MONTH, 0);
                            break;
                        default:
                            break;
                    }
                    dateTime = DateUtil.truncate(dateTime, DateField.MONTH);
                    break;
                case HALF_YEAR:
                    dateTime.setField(DateField.YEAR, reportTime.getYear());
                    switch (reportTime.getHalfYear()) {
                        case "上":
                            //上半年报,下半年第一个月截止
                            dateTime.setField(DateField.MONTH, 6);
                            break;
                        case "下":
                            //下半年报,下一年1月份截止
                            dateTime.offset(DateField.YEAR, 1);
                            dateTime.setField(DateField.MONTH, 0);
                            break;
                        default:
                            break;
                    }
                    dateTime = DateUtil.truncate(dateTime, DateField.MONTH);
                    break;
                default:
                    break;
            }
        }

        //默认上报截止时间设置未15号,补报时间不超过28号
        dateTime.setField(DateField.DAY_OF_MONTH, 15);

        //采用配置的时间
        if (CollUtil.isNotEmpty(reportDeadlineTimeConfigs)) {
            ReportDeadlineTimeConfig reportDeadlineTimeConfig = reportDeadlineTimeConfigs.stream()
                    .filter(x -> x.getFrequency()
                            .equals(reportFrequencyEnum.getCode()))
                    .findFirst()
                    .orElse(null);
            if (reportDeadlineTimeConfig != null) {
                if (reportDeadlineTimeConfig.getMonthAdd() != null) {
                    dateTime.offset(DateField.MONTH, reportDeadlineTimeConfig.getMonthAdd());
                }
                if (reportDeadlineTimeConfig.getDay() != null) {
                    int configDay = reportDeadlineTimeConfig.getDay();
                    //如果配置的天 大于 本月最后一天,则设置为最后一天(如31,2月则有可能是28号或29号,小月是30号,大月才是31号)
                    if (configDay > dateTime.getLastDayOfMonth()) {
                        configDay = dateTime.getLastDayOfMonth();
                    }
                    dateTime.setField(DateField.DAY_OF_MONTH, configDay);
                }
            }
        }
        //设置时间为:23:59:59
        dateTime = DateUtil.ceiling(dateTime, DateField.DAY_OF_MONTH, true);
        return dateTime.toJdkDate();
    }

 

posted @ 2022-08-23 20:37  追极  阅读(102)  评论(0编辑  收藏  举报