首页 > 其他分享 >满勤天数如何计算

满勤天数如何计算

时间:2022-12-20 17:15:29浏览次数:33  
标签:满勤 天数 rest 计算 双休 day 周日

每月满勤天数如何计算

1 原始版本

1.1 需求

  • 通过系统判断某月份的满勤天数,然后继续后续操作

1.2 解决方案

  • 创建一张表(setting_month_rest_day),将每个月上班天数提前设置好即可(每年的假期不同,所以一年需要设置一次)

2 变更版本二

2.1 需求

  • 出现了特殊情况,每个月的满勤天数各不相同 有的人是周日休,有的人是双休还有的是周六休

2.2 解决方案

  • 在原有表的基础上新增一张表(setting_rest_type),主要对休班方式的不同进行保存
  • 原有表(setting_month_rest_day)新增一个字段用于关联setting_rest_type,因为每个人只可能有一种休班方式,因此不需要一对多关系

3 变更版本三

3.1 需求

  • 在每个月会出现一个人在某个时间段周日休,某个时间段双休的情况,需要根据实际情况来获得满勤天数

3.2 处理难点

  • 每年都会有调休的情况发生(法定休假)
  • 如果把周日,周六和节假日都存到表里,感觉录入的工作量会很大,一旦临时发生变故(例如过年不按照法定的来),还要进行修改,本来人力就不够,还好耗费人力,最后活还是自己的
  • 满勤天数主要用于计算工资

3.3 解决方案

  • 将满勤天数去掉,将工资计算从按月计算改为按天计算,上一天班发一天工资(有日报和考勤),最后相加之和就是当月工资

3.4 逻辑遗漏

  • 没有考虑加班的情况,每个月工资=当月应发/当月满勤*当月出勤天数,当满勤小于出勤时,就会出现多发工资的情况(出勤大于满勤,工资不应该继续发放了)

4 变更版本四

4.1 需求

  • 加班情况出现,且需要考虑真实的出勤天数

4.2 场景

4.2.1 2023年1月满勤天数

4.2.1.1 先单后双
  1. 已知条件

    1. 张三 1号到12号周日休息
    2. 张三 13号到月底都是双休
  2. 获得当月满勤天数

    起止日期 满勤天数 休班方式 说明
    1号-12号 9 周日休 2个周日+1天休假
    13号-31号 9 双休 2个周末(去掉1个周末)+7天休假

    共计18天满勤

4.2.1.2 先双后单
  1. 已知条件

    1. 张三 1号到12号双休
    2. 张三 13号到月底都是周日休息
  2. 获得当月满勤天数

    起止日期 满勤天数 休班方式 说明
    1号-12号 8 双休 2个周日(3天)+1天休假
    13号-31号 10 周日休 三个周日(去掉1个周日)+7天休假

    共计18天满勤

2.2.1.3 结论
  1. 主要判断的日期
    1. 28,29是否上班-------对于双休的来说
    2. 29是否上班-------------对于周日休班的来说
    3. 28是否上班-------------对于周六休班的来说
  2. 周末上班表和节假日表,并且休班类型的都要区分开

4.2.2 2023年4月满勤天数

4.2.2.1 先单后双
  1. 已知条件

    1. 张三 1号到12号周日休息
    2. 张三 13号到月底都是双休
  2. 获得当月满勤天数

    起止日期 满勤天数 休班方式 说明
    1号-12号 9 周日休 2个周日+1天休假
    13号-31号 13 双休 3个周末(去掉1个周日)+ 2天休假(重合不算)

    共计21天满勤

4.2.2.2 先双后单
  1. 已知条件

    1. 张三 1号到12号双休
    2. 张三 13号到月底都是周日休息
  2. 获得当月满勤天数

    起止日期 满勤天数 休班方式 说明
    1号-12号 7 双休 2个周日(4天)+1天休假
    13号-31号 15 周日休 三个周日(去掉1个周日)+2天的假期(只算一天)

    共计22天满勤

4.2.2.3 结论
  1. 主要判断的日期
    1. 23是否上班-------------对于双休的来说
    2. 29是否上班-------------对于周日休班的来说
    3. 28是否上班-------------对于周六休班的来说

4.2.3 2023年5月份满勤天数

4.2.3.1 先单后双
  1. 已知条件

    1. 张三 1号到15号周日休息
    2. 张三 16号到月底都是双休
  2. 获得当月满勤天数

    起止日期 满勤天数 休班方式 说明
    1号-15号 10 周日休 2个周日+3天休假
    16号-31号 12 双休 2个周末

    共计22天满勤

4.2.3.2 先双后单
  1. 已知条件

    1. 张三 1号到15号双休
    2. 张三 16号到月底都是周日休息
  2. 获得当月满勤天数

    起止日期 满勤天数 休班方式 说明
    1号-15号 9 双休 2个周末(去掉1个周六)+3天休假
    16号-31号 14 周日休 2个周日

    共计23天满勤

4.2.3.3 结论
  1. 主要判断的日期
    1. 6号是否上班-------------对于双休的来说
    2. 6号是否上班-------------对于周六休班的来说
  2. 休假会有重合的地方

4.3 思路想法

  1. 还是不想过多的录入信息
  2. 先通过代码计算出某个时间段有几个周六或周日,然后通过查询上班和加班的天数来计算出勤天数
  3. 目前不考虑周一到周五休假的可能性(暂时不验证)

4.4 设计实现

4.4.1 前期准备

  1. 在变更版本三的前提添加一个表setting_month_day_calculate,主要用于存储休班日期和加班日期

其中use_model保存setting_rest_type中唯一标识的内容,多个可按照逗号分隔

  1. 通过java代码获得周六或者周日的个数

    	/**
    	 * 查询日期间有几天一周中的某一天
    	 * 日期格式 yyyy-MM-dd yyyy-MM-dd 1-7(表示周一到周日)
    	 * @param startDate 准备查询的起始日期
    	 * @param endDate 准备查询的结束日期
    	 * @param dayOfWeek 准备查的一周中的某一天(准备查周几?)
    	 * @return 包含所查周几的天数
    	 * @throws ParseException 不支持跨年查询、不支持结束日期早于起始日期、周几输入错误等
    	 */
    	public static int getMondayNumber(Date startDate,Date endDate,int dayOfWeek) throws ParseException{
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    		int differenceDay = 0;
    		//实例化起始和结束Calendar对象
    		Calendar startCalendar = Calendar.getInstance();
    		Calendar endCalendar = Calendar.getInstance();
    		//分别设置Calendar对象的时间
    		startCalendar.setTime(startDate);
    		endCalendar.setTime(endDate);
    
    		//定义起始日期和结束日期分别属于第几周
    		int startWeek = startCalendar.get(Calendar.WEEK_OF_YEAR);
    		int endWeek = endCalendar.get(Calendar.WEEK_OF_YEAR);
    
    		//拿到起始日期是星期几
    		int startDayOfWeek = startCalendar.get(Calendar.DAY_OF_WEEK);
    		if(startDayOfWeek == 1)    {
    			startDayOfWeek = 7;
    			startWeek--;
    		}else startDayOfWeek--;
    
    		//拿到结束日期是星期几
    		int endDayOfWeek = endCalendar.get(Calendar.DAY_OF_WEEK);
    		if(endDayOfWeek == 1) {
    			endDayOfWeek = 7;
    			endWeek--;
    		}else endDayOfWeek--;
    
    		//计算相差的周数
    		int differenceWeek = endWeek - startWeek;
    
    		//开始计算
    		if(startDayOfWeek <= dayOfWeek) {
    			if(endDayOfWeek >= dayOfWeek)
    				differenceDay = differenceWeek + 1;
    		}else if(startDayOfWeek > dayOfWeek) {
    			if(endDayOfWeek < dayOfWeek)
    				differenceDay = differenceWeek-1;
    		}else {
    			differenceDay = differenceWeek;
    		}
    		return differenceDay;
    	}
    

4.4.2 实现(以2023年1月为例)

4.4.2.1 模拟场景
  1. 张三 1号到12号周日休息
  2. 张三 13号到月底都是双休
4.4.2.2 数据准备(根据模拟场景设置)
  1. setting_month_day_calculate (id等非关键字段忽略)数据

    select_date/name use_model calculate
    2023-01-02 双休,周日休,周六休 1
    2023-01-23 双休,周日休,周六休 5
    2023-01-28 双休,周六休 -1
    2023-01-29 双休,周日休 -1
  2. setting_rest_type (id等非关键字段忽略)数据

    name
    双休
    周六休
    周日休
  3. setting_month_rest_day (id等非关键字段忽略)数据

    person_name use_begin_time use_end_time rest_type_name
    张三 2022-12-20 2023-01-12 周日休
    张三 2023-01-13 null 双休
4.4.2.3 获得1月份满勤天数
  1. 通过sql获得当月的setting_month_rest_day的条数(当大于两条才进行计算,并适用map存放,判断map的key值如果不存在,则证明setting_month_rest_day中最多只有一条,可直接查询出来)。

    -- start_day: 2023-01-01
    -- end_day  : 2023-01-31
    SELECT
    	t1.person_name,
    	t1.use_begin_time,
    	t1.use_end_time,
    	t1.rest_type_name 
    FROM
    	setting_month_rest_day t1
    	INNER JOIN (
    		SELECT
    			person_name 
    		FROM
    			setting_month_rest_day 
    		WHERE
    			( use_begin_time BETWEEN #{start_day} AND #{end_day} OR use_end_time BETWEEN #{start_day} AND #{end_day} ) 
    	GROUP BY
    		rest_type_name 
    	HAVING
    		count( rest_type_name ) > 1
    	) t2 ON t1.person_name=t2.person_name
    	WHERE
    	(t1.use_begin_time BETWEEN #{start_day} AND #{end_day} OR t1.use_end_time BETWEEN #{start_day} AND #{end_day} )
    	ORDER BY t1.use_begin_time DESC
    
  2. 通过在循环判断rest_type_name值,如果是双休则需要加周六和周日的天数,如果是单休只需要添加周日或周六即可

    if(rest_type_name.index("双") != -1){
    	return getMondayNumber(use_begin_time, use_end_time, 7)+getMondayNumber(use_begin_time, use_end_time, 6);
    }else if(rest_type_name.index("日") != -1){
    	return getMondayNumber(use_begin_time, use_end_time, 7);
    }else if(rest_type_name.index("六") != -1){
    	return getMondayNumber(use_begin_time, use_end_time, 6);
    }
    
  3. 通过获得setting_month_day_calculate的天数来加上法定的休班和调休

    -- startDate  setting_month_rest_day的use_begin_time字段
    -- endDate    setting_month_rest_day的use_end_time字段
    -- model      setting_month_rest_day的rest_type_name字段
    select SUM(t1.calculate) from wr_month_day_statistics_calculate t1 where (t1.select_date BETWEEN #{startDate} and #{endDate}) and FIND_IN_SET(#{model}',t1.use_model)
    
  4. 通过2和3的数值相加,即可获得当月满勤天数

标签:满勤,天数,rest,计算,双休,day,周日
From: https://www.cnblogs.com/wanghun315/p/16994640.html

相关文章