为了账号安全,请及时绑定邮箱和手机立即绑定

如何排除非工作日计算时间-如何统计工作日

标签:
Java 设计

https://img1.sycdn.imooc.com//615e5e960001e9e816001062.jpg

新进入一家公司,工资涨了一点点,忙了起来,自己也遇到很多事情,现在算是刚刚处理完,有心情开始写点博客了。现在的公司算是我前前任公司,我都怀疑我会不会在两家公司反复横跳,现在算是以开发的身份在公司做项目,很不幸,我又加入了一家以项目主的公司,当问起我接不接受出差的时候,我还是接受了出差,所以我现在是经常在出差。

新项目有个需求,以接收“单子”时间起,倒计时十五个工作日,做计算提醒,也就是说,这个数字每天都会减小,还要排除工作日,计算很好解决,如何排除非工作日?

1、调用外部接口获取非工作日的日期

2、本地数据库存储非工作日

我想都没想,就使用的第二个方案,因为我们的项目都不会联网,所以调用外部接口是不现实的。

解决思路:接收时间加15天-当前时间=还剩多少时间

其中接收时间加15天的时候,要判断在这15天里,有多少天是非工作日,有几天则加几天,也就是说,接收时间+15+N天才是最终时间。

我新建了一张表,用于存储非工作日,其实法定节假日就那么几天,所以我的想法是,存所有的周六日,然后手动修改法定节假日,也就是手动“维护”当年的劳动节、国庆节、中秋节等等

MySQL

CREATE TABLE `non_or_working_day`  (  
`DAY_TITLE` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '今日命题',   
`NON_WORKING_DATE` datetime NULL DEFAULT NULL COMMENT '非工作日期',  
`REMARK` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注',   
`CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间',  
`UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间',  
`ID` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',  
PRIMARY KEY (`ID`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;


使用 Java 生成当年所有的周六日

public static void main(String[] args) {
    int year = 2021;
    List<String> dateList=new ArrayList<String>();
    SimpleDateFormat simdf = new SimpleDateFormat("yyyy-MM-dd");
    Calendar calendar = new GregorianCalendar(year, 0, 1);
    int i = 1;
    while (calendar.get(Calendar.YEAR) < year + 1) {
        calendar.set(Calendar.WEEK_OF_YEAR, i++);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        if (calendar.get(Calendar.YEAR) == year) {
            System.out.println("周日:"+simdf.format(calendar.getTime()));
            dateList.add(simdf.format(calendar.getTime()));
        }
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
        if (calendar.get(Calendar.YEAR) == year) {
            System.out.println("周六:"+simdf.format(calendar.getTime()));
            dateList.add(simdf.format(calendar.getTime()));
        }
    }

    System.out.println(dateList.size());
}

将 System.out.println 里的内容替换为插入数据库的代码即可

我使用了 element-UI 做了可视化界面手动修改节假日,如下图

https://img1.sycdn.imooc.com//615e53640001f4fc12540886.jpg

首先我写了个方法,判断两个日期直接有几天非工作

/**
 * @desc 查找区间内有几天非工作日
 */
public long isExistNonWorkingDayCount(List<NonOrWorkingDayDO> nonOrWorkingDayDTOList, Date startTime, Date endTime) {
    long count = 0;
    for (NonOrWorkingDayDO nonworkdo :
            nonOrWorkingDayDTOList) {
        if (isEffectiveDate(nonworkdo.getNonWorkingDate(), startTime, endTime)) {
            count++;
        }
    }
    return count;
}

/**
 *
 */
public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
    if (nowTime.getTime() == startTime.getTime()
            || nowTime.getTime() == endTime.getTime()) {
        return true;
    }

    Calendar date = Calendar.getInstance();
    date.setTime(nowTime);

    Calendar begin = Calendar.getInstance();
    begin.setTime(startTime);

    Calendar end = Calendar.getInstance();
    end.setTime(endTime);

    if (date.after(begin) && date.before(end)) {
        return true;
    } else {
        return false;
    }
}

判断“单子”List 距离15个工作日还剩多少天

/**
 * @author caeser
 * @date 2021-10-7 09:47:07
 * @desc 只判断距离当前item创建时间15个工作日期限还剩多少天
 */
List<ItemDTO> judgeOutDeadLineReminderTotalFifteenCreateTime(List<ItemDTO> itemDTOList) {
    List<ItemDTO> itemDTOresult = null;
    List<NonOrWorkingDayDO> nonOrWorkingDayDTOList = nonOrWorkingDayDAO.selectList(null);
    Date nowDate = new Date();
    long nd = 1000 * 24 * 60 * 60;
    for (ItemDTO dto :
            itemDTOList) {
        // 获取当前item的创建时间
        Date createTimeDate = dto.getCrterTime();
        // item创建时间增加十五天
        Date fifteenDeadLineDate = timeProcess(createTimeDate, 15);
        // 和当前日期做对比还剩多少天
        // 计算当前时间差值(单位:天)
        long diff = fifteenDeadLineDate.getTime() - nowDate.getTime();
        // 当前距离15天期限的日期有多少天
        long day = diff / nd;
        // 判断当前时间和 到期15期限时间之间有几天非工作日
        long nonworkCount = isExistNonWorkingDayCount(nonOrWorkingDayDTOList, nowDate, fifteenDeadLineDate);
        // 日期增加非工作日
        day = day + nonworkCount;
        // 如果超过15天则只返回15天,不超过15天则显示正常
        if (day > 15) {
            day = 15;
        }
        if (day < 1) {
            dto.setCompareNowDateAndCrterTime("1|" + day);
        } else {
            BigDecimal longToBigDel=new BigDecimal(day);
            dto.setDeadLineCount(longToBigDel);
            dto.setCompareNowDateAndCrterTime("0|" + day);
        }

    }
    itemDTOresult = itemDTOList;
    return itemDTOresult;
}

我暂时没有维护春节那几天,这个工作日统计算是解决了,我在这里分享一下经验,我是这样处理的,不知道别人是怎么样解决的,我的项目不能联网,所以离线的处理办法,我只能想到这里了,至少现在是满足当前项目需求了。

有个代码需要说一下 

nonOrWorkingDayDAO.selectList(null)

这一句其实就是查询所有的非工作日,并且保存到 List 里。

此次项目我们有个基本概念就是减少数据库的查询次数,越少越好。

我们还有一个需求就是查询剩余1天的单子有哪些,于是这个剩余天数,其实是需要保存起来的,我上面的代码只是每次查询都会计算一次,只是计算的数量不多,因为分页查询每次查询的数据量不多,所以我就动态计算,保证每次计算的都是最新的到期时间。

但是如果保存这个数据,就会有一个问题,第二天如何更新这个数据呢?这个时候定时任务就是必要的了,但是我在这个项目里不想加入定时任务,因为项目节假日可能会关机,这个项目完全离线,不过有个好消息是,查询剩余1天的单子有哪些是在另一个页面(姑且成为B页面),所以我在B页面的查询按钮里,加入了这样一个逻辑,我使用了单独的一张表,记录当前计算的日期,而且只记录年月日,没有具体时间,当计算过一次之后,这个日期就与当前日期相等了,只要相等则不重新计算,减少查询数据库次数,只是我新建的表只使用了一行

https://img1.sycdn.imooc.com//615e583900010ed804290052.jpg

判断代码如下:

/// 判断日期,1、如果DATE_UPDATE日期小于当前日期则更新一次item的到期时间
if(ToolUtil.isNotEmpty(dateTargetDTOS)&&dateTargetDTOS.size()>0){
    Date getNowDate=new Date();
    Date dateUpdateDe=dateTargetDTOS.get(0).getDateUpdate();
    DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
    try {
        getNowDate=dateFormat2.parse(dateFormat2.format(getNowDate));
        dateUpdateDe=dateFormat2.parse(dateFormat2.format(dateUpdateDe));
    }catch (Exception e){
        throw new ExceptionManager(500,e.getMessage());
    }
    if(getNowDate.compareTo(dateUpdateDe)<0||getNowDate.compareTo(dateUpdateDe)==0){
        // 当前日期在dateUpdate之前
        // System.out.println("不更新");
    }else{
        // 当前日期在dateBefore之后 更新到期时间
        // System.out.println("更新到期时间");

    }
}

也就是说第二天点击查询第一次,才会更新一次数据库,第二次就不进行更新了,B页面查询的肯定是计算之后的到期时间。

https://img1.sycdn.imooc.com//615e5c2800013ab316001066.jpg

以上就是我对统计工作日或者非工作日的解决方案。

工作不算多,可总是觉得挺忙的,大部分时间我们都在CRUD,普通的程序员大概如此吧。很久很久都没写博客了,要忙的事情确实不少,在公司的业务代码里,大部分内容我觉得没什么可以分享的,所以一直都没动笔写博客,希望以上内容对你有用。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
29
获赞与收藏
154

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消