数据库实现计算工作日时间差--去除节假日及周末

由于统计需求,要求计算2个时间差,并且要求去除节假日和周末的时间。

说一下需求规则:

1、如果开始时间和结束时间在一个休假时间段内,时间差为0,比如10.2到10.4这种。

2、其他情况,只计算在休假时间外的。

首先说一下思路:

1、我在t_rest_day表中存入了每一年的休假数据(节假日+周末),这样免得去判断节假日和周末重复的情况。

2、针对开始时间进行加1天循环,直到大于结束时间为止。

我是使用数据库postgresql 的函数实现的,其实也可以按照这个思路使用java实现。

废话有点儿多,直接上代码。

a、下表是t_rest_day表的数据,存储的是休假开始结束时间段。

数据库实现计算工作日时间差--去除节假日及周末_第1张图片

b、函数

--删除函数
drop function count_work_day(startTime timestamp,endTime timestamp);


--创建函数
create or replace function count_work_day(startTime timestamp,endTime timestamp)
returns interval as $hour$
declare
	start_date timestamp := date_trunc('day',startTime);
	end_date timestamp := date_trunc('day',endTime);
	rest_cost interval := '0 day';
	count_day int := 0;
  count_day_temp int :=0;
	start_time_temp timestamp := startTime;
	end_time_temp timestamp := endTime;
begin 
	--同一天
	if(start_date = end_date) then 
		select count(1) into count_day from t_rest_day t where t.start_time <= startTime and t.end_time > endTime;
		if(count_day > 0) then 
			return '0 day';
		else 
			return endTime - startTime;
		end if;
	end if;
	--开始和结束时间都在一个休假时间段内
	select count(t.id) into count_day_temp from t_rest_day t where t.start_time <= startTime and t.end_time > endTime;
	if(count_day_temp = 1) then 
		return '0 day';
	end if;
	--不是同一天
	while date_trunc('day',start_time_temp) <= end_time_temp loop
		select count(1) into count_day from t_rest_day t where t.start_time <= start_time_temp and t.end_time > start_time_temp;
		if(count_day > 0) then 
			if(date_trunc('day',start_time_temp) = start_date) then 
				rest_cost = rest_cost + (start_date + '1 day' - startTime);
			elseif(date_trunc('day',start_time_temp) = end_date) then
				rest_cost = rest_cost + (endTime - end_date);
			else
				rest_cost = rest_cost + '1 day';
			end if;
			--raise notice 'rest_cost :%',rest_cost;
		end if;
		start_time_temp = start_time_temp + '1 day';
		--raise notice 'start_time_temp :%',start_time_temp;
	end loop;
	return age(endTime,startTime) - rest_cost;
end 
$hour$ LANGUAGE plpgsql;


--测试函数
select extract(epoch from count_work_day('2018-01-02 02:00:00.0','2018-01-02 14:01:00.0'))/3600;
目前暂时还没有测试出来这个函数有什么问题,各位有什么高见,也欢迎一起交流。

你可能感兴趣的:(数据库)