标记每年的工作日


一、背景描述

数据库中存储节假日,其数据库存储节假日内容为:①周一到周5放假的节假日日期(isweek=false) ②周六、周日补假的节假日日期(isweek = true)。现有需求,给定一个日期和工作日,返回工作日之后的日期。(注意:有不能把数据库中所有数据一次性全部读入的情况限制)
isweek:数据库中的一个字段,标识是周一至周五,还是周六周日

二、代码说明

1.根据日期,返回days个工作日后的日期与现在日期的差值,此过程不考虑,节假日

代码如下(示例):


/**
     * 根据日期,返回days个工作日后的日期,此过程不考虑,节假日
     * @param date
     * @param days
     * @return
     */
    private int getRollWeekDays(Date date,int days){
        int realRollDay = 0;
        //判断第一天是不是周末或周日
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //先判断是否为周末
        int currentWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (currentWeek == Calendar.SUNDAY || currentWeek == Calendar.SATURDAY) {
            //如果是周六则滚到周日,每周的开始
            realRollDay = currentWeek / 7;
            //将日期滚到到周一
            currentWeek = Calendar.SUNDAY;
        }
        //获取当前距离周一的时间差(2=1+1,第一个1是平衡系统的,第二个1是减去今天的)
        int diffValue = currentWeek - Calendar.MONDAY;
        //只有周末情况 (周末 + days)     第一个表示几个工作日;第二个计算会跨过的周末
        realRollDay += days + (days + diffValue) / 5 * 2;
        return realRollDay;
    }

2.给定一个数字days(表示天数) 返回从现在开始的days以后的那天日期

代码如下(示例):


```java
    /**
     * 给定一个数字days(表示天数)
     * 返回从现在开始的days以后的那天日期
     *
     * @param date
     * @param days
     * @return
     */
    @Override
    public Date getAfterDate(Date date, Integer days) {

        //设计一个标识,需要滚动的日期数
        int realRollDay = 0;
        //获取days工作日后的日期,不考虑days
        realRollDay = getRollWeekDays(date,days);
        
        //查询数据库,获取这段时间内的放假日期,和补假日期 (放假 - 补假)为需要补充的日期
        List<HolidayConfig> holidayConfigList = null;
        //得到起始时间---将时分秒不化为
        Date startDate = DateUtil.afterDateByDay(date,1);
        //结束时间(不含放假的日期和补假日期)---- 这个比较难确定,(可能会涉及到某年之后
        Date endDate = DateUtil.afterDateByDay(date, realRollDay);
        do {
            String startDateStr = TimeUtil.date2Str(startDate,TimeUtil.FORMAT_DATE);
            String endDateStr = TimeUtil.date2Str(endDate,TimeUtil.FORMAT_DATE);
            holidayConfigList = holidayConfigMapper.selectScopeByString(startDateStr, endDateStr);
            if (CollectionUtil.isNotEmpty(holidayConfigList)) {
                //对数据进行过滤,如果isweek等于0则加1,否则减1,---- tempCount 等价于工作日
                int tempWeekDayCount = 0;  
                //统计补假日期
                tempWeekDayCount = (int) holidayConfigList.stream().filter(v -> v.getIsWeekend()).count() * -1;
                tempWeekDayCount += (int) holidayConfigList.stream().filter(v -> !v.getIsWeekend()).count();

                 //先获得滚动realrollDay后的日期的,tempWeekDayCount 实质是与 days工作日是等量关系
                int tempRollDay = getRollWeekDays(DateUtil.afterDateByDay(date,realRollDay),tempWeekDayCount);
                
                //将放假日期加入(用正数表示放假,负数表示补假)
                realRollDay += tempRollDay;
                //确定下一个时间范围的起始时间和终止时间
                startDate = DateUtil.afterDateByDay(endDate,1);
                endDate = DateUtil.afterDateByDay(date, realRollDay);
            }
        } while (CollectionUtil.isNotEmpty(holidayConfigList));
        //求解总共需要后移多少天(周末 + 工作日 - 周末补假) 
        Date afterDate = DateUtil.afterDateByDay(date, realRollDay);
        return afterDate;
    }

总结

对于明显有规律的,并且数据量比较大的情况,可以考虑通过取余数,或除法等方法进行统计,计算,减少循环次数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值