数据分析:同比-环比

同比-环比

在数据统计方面,涉及到日期的时候,通常会出现同比、环比的分析(以2021年度为例),两者放一起能够更加立体化地反映变化速度,不过由于两者的比较方式不同,所以一般不会用两者进行比较。

同比

  • 定义:与历史同时期比较,通常指不同年份相同时间或时间段的比较,一般为上一年度与当前年度的比较

  • 计算方式:

    • 本期同比增长(下降)率(%) = (本期价格/上年同期价格 -1) × 100%
    • 为正,则为增长率;为负,则为下降率
  • 示例

    2020年 2021年
    月度 1月 1月
    季度 一季度(1-3月) 一季度(1-3月)
    年度 2020年总计 2021年总计

环比

  • 定义:与上一个统计周期比较,通常指相同年份不同时间或时间段的比较

  • 计算方式:

    • 本期环比增长(下降)率(%) = (本期价格/上期价格 - 1 )× 100%
    • 为正,则为增长率;为负,则为下降率
  • 示例

    2021年 2021年
    月度 1月 2月
    季度 一季度(1-3月) 二季度(4-6月)
    年度 2020年总计 2021年总计

日期获取:上月-本季-本年

类设计

CaseConsts:时间类型常量(本月、本季、本年)

/** * @author xuzhou * @date 2020-09-03 */
public interface CaseConsts {
   

    /** * 本月 */
    String TIMETYPY_BY = "by";
    /** * 本季 */
    String TIMETYPY_BJ = "bj";
    /** * 本年 */
    String TIMETYPY_BN = "bn";
}

DateListBean:时间Bean

/** * DateListBean * 同比环比时间 * @author xuzhou * @date 2020/9/10 18:11 * @version 1.0.0 */

public class DateListBean {
   
    /** * 开始时间 */
    Date startDate;
    /** * 结束时间 */
    Date endDate;
    /** * 环比开始时间 */
    Date startDateMoM;
    /** * 环比结束时间 */
    Date endDateMoM;
    /** * 同比开始时间 */
    Date startDateYoY;
    /** * 同比结束时间 */
    Date endDateYoY;

    public Date getStartDate() {
   
        return startDate;
    }

    public void setStartDate(Date startDate) {
   
        this.startDate = startDate;
    }

    public Date getEndDate() {
   
        return endDate;
    }

    public void setEndDate(Date endDate) {
   
        this.endDate = endDate;
    }

    public Date getStartDateMoM() {
   
        return startDateMoM;
    }

    public void setStartDateMoM(Date startDateMoM) {
   
        this.startDateMoM = startDateMoM;
    }

    public Date getEndDateMoM() {
   
        return endDateMoM;
    }

    public void setEndDateMoM(Date endDateMoM) {
   
        this.endDateMoM = endDateMoM;
    }

    public Date getStartDateYoY() {
   
        return startDateYoY;
    }

    public void setStartDateYoY(Date startDateYoY) {
   
        this.startDateYoY = startDateYoY;
    }

    public Date getEndDateYoY() {
   
        return endDateYoY;
    }

    public void setEndDateYoY(Date endDateYoY) {
   
        this.endDateYoY = endDateYoY;
    }
}

方法设计

getDateList:根据时间类型获取时间

/** * 获取同比、环比时间 * @param timeType 时间类型,上月,本季,本年 * @return DateListBean */
    private DateListBean getDateList(String timeType) {
   

        DateListBean dateListBean = new DateListBean();
        //当前时间,2020-09-10
        LocalDate nowDate = LocalDate.now();
        //本月1日,2020-09-01
        nowDate = nowDate.withDayOfMonth(1);

        //上月1日,2020-08-01
        LocalDate lastMonthStart = nowDate.plusMonths(-1);
        //上月最后一日,2020-08-31
        LocalDate lastMonthEnd = nowDate.plusDays(-1);

        if(timeType.equals(CaseConsts.TIMETYPY_BY)){
   
            //月度,上月
            //上月第一天,2020-08-01
            Date startDate = Date.valueOf(lastMonthStart);
            dateListBean.setStartDate(startDate);
            //上月最后一天,2020-08-31
            Date endDate = Date.valueOf(lastMonthEnd);
            dateListBean.setEndDate(endDate);

            //同比,去年相同月份
            //相同月份第一天,2019-08-01
            Date startDateYoY = Date.valueOf(lastMonthStart.plusYears(-1));
            dateListBean.setStartDateYoY(startDateYoY);
            //相同月份最后一天,2019-08-31
            LocalDate date = nowDate.plusYears(-1);
            Date endDateYoY = Date.valueOf(date.plusDays(-1));
            dateListBean.setEndDateYoY(endDateYoY);

            //环比,今年上个月
            //上个月第一天,2020-07-01
            Date startDateMoM = Date.valueOf(lastMonthStart.plusMonths(-1));
            dateListBean.setStartDateMoM(startDateMoM);
            //上个月最后一天,2020-07-30
            Date endDateMoM = Date.valueOf(lastMonthStart.plusDays(-1));
            dateListBean.setEndDateMoM(endDateMoM);

        }
        if(timeType.equals(CaseConsts.TIMETYPY_BJ)){
   
            //季度

            //当前季度
            //当前季度开始第一天,2020-07-01
            Date startDate = checkStartDate(nowDate,CaseConsts.TIMETYPY_BJ);
            dateListBean.setStartDate(startDate);
            //上月最后一天,2020-08-31
            Date endDate = Date.valueOf(lastMonthEnd);
            dateListBean.setEndDate(endDate);

            //同比,去年相同季度
            //相同季度第一天,2019-07-01
            Date startDateYoY = checkStartDate(nowDate.plusYears(-1),CaseConsts.TIMETYPY_BJ);
            dateListBean.setStartDateYoY(startDateYoY);
            //相同季度最后一天,2019-09-30
            Date endDateYoY = checkEndDate(nowDate.plusYears(-1),CaseConsts.TIMETYPY_BJ);
            dateListBean.setEndDateYoY(endDateYoY);

            //环比,今年上个月
            //上个季度第一天,2020-04-01
            Date startDateMoM = checkStartDate(nowDate.plusMonths(-3),CaseConsts.TIMETYPY_BJ);
            dateListBean.setStartDateMoM(startDateMoM);
            //上个季度最后一天,2020-06-30
            Date endDateMoM = checkEndDate(nowDate.plusMonths(-3),CaseConsts.TIMETYPY_BJ);
            dateListBean.setEndDateMoM(endDateMoM);

        }
        if(timeType.equals(CaseConsts.TIMETYPY_BN)){
   
            //年度

            //当前年度
            //当前年度开始第一天,2020-01-01
            Date startDate = checkStartDate(nowDate,CaseConsts.TIMETYPY_BN);
            dateListBean.setStartDate(startDate);
            //上月最后一天,2020-08-31
            Date endDate = Date.valueOf(lastMonthEnd);
            dateListBean.setEndDate(endDate);

            //同比,去年
            //去年第一天,2019-01-01
            Date startDateYoY = checkStartDate(nowDate.plusYears(-1),CaseConsts.TIMETYPY_BN);
            dateListBean.setStartDateYoY(startDateYoY);
            //去年最后一天,2019-12-31
            Date endDateYoY = checkEndDate(nowDate,CaseConsts.TIMETYPY_BN);
            dateListBean.setEndDateYoY(endDateYoY);

            //环比,今年上个月
            //上个季度第一天,2019-01-01
            Date startDateMoM = checkStartDate(nowDate.plusYears(-1),CaseConsts.TIMETYPY_BN);
            dateListBean.setStartDateMoM(startDateMoM);
            //上个季度最后一天,2019-12-31
            Date endDateMoM = checkEndDate(nowDate,CaseConsts.TIMETYPY_BN);
            dateListBean.setEndDateMoM(endDateMoM);

        }
        return dateListBean;

    }

checkStartDate:获取时间区间开始时间

 /** * 获取时间区间开始时间 * @param localDate 当前日期 * @param timeType 时间区间类型(月、季度、年度) * @return Date */
    private Date checkStartDate(LocalDate localDate,String timeType) {
   
        Date date = null;
        //开始为每月的1日
        localDate = localDate.withDayOfMonth(1);
        //判断区间
        switch (timeType){
   
            case CaseConsts.TIMETYPY_BY:
                //本月
                break;
            case CaseConsts.TIMETYPY_BJ:
                //本季
                localDate = checkMouth(localDate);
                break;
            case CaseConsts.TIMETYPY_BN:
                //本年
                localDate = localDate.withMonth(1);
                break;
            default:
        }
        //转为Date
        date = Date.valueOf(localDate);
        return date;
    }

checkEndDate:根据时间和类型获取时间区间结束时间

    /** * 获取时间区间结束时间 * @param localDate 当前日期 * @param timeType 时间区间类型(月、季度、年度) * @return Date */
    private Date checkEndDate(LocalDate localDate,String timeType) {
   
        Date date = null;
        //开始为每月的1日
        localDate = localDate.withDayOfMonth(1);

        //判断区间
        switch (timeType){
   
            case CaseConsts.TIMETYPY_BY:
                //往前一天,为上月月底
                localDate = localDate.plusDays(-1);
                break;
            case CaseConsts.TIMETYPY_BJ:
                //本季
                //季度第一个月的第一天
                localDate = checkMouth(localDate);
                //下个季度第一个月的第一天
                localDate = localDate.plusMonths(+3);
                //本季度最后一个月的最后一天
                localDate = localDate.plusDays(-1);
                break;
            case CaseConsts.TIMETYPY_BN:
                //本年
                //本年1月1日
                localDate = localDate.withMonth(1);
                //去年最后一天
                localDate = localDate.plusDays(-1);
                break;
            default:
        }
        //转为Date
        date = Date.valueOf(localDate);
        return date;
    }

checkMouth:更加日期判断季度,获取季度开始日期

/**
 * 判断季度
 * @param date 当前日期
 * @return 季度开始日期
 */
private LocalDate checkMouth(LocalDate date){
    LocalDate startDate = date;
    switch (date.getMonthValue()){
        case 1:
        case 2:
        case 3:
            startDate = date.withMonth(1);
            break;
        case 4:
        case 5:
        case 6:
            startDate = date.withMonth(4);
            break;
        case 7:
        case 8:
        case 9:
            startDate = date.withMonth(7);
            break;
        case 10:
        case 11:
        case 12:
            startDate = date.withMonth(10);
            break;
        default:
    }

    return startDate;
}