sql存储过程,获取请假时长(精确到⼩时),已排除周末,国家节假⽇。
说⼀下计算⽅式,
请假时长=【第⼀天的请假时长】+【最后⼀天的请假时长】+中间⽇期相差的天数*(⼀天的⼯作时长7.5)。
其中需要判断⽇期是否是节假⽇,我这⾥使⽤的是数据库节假⽇表对应判断。
第⼀步
创建⼀个数据库节假⽇表
id date type
数据来源:
全年⽇期对应的上班⽇、周末、节假⽇,
0代表上班 1周末休息 2节假⽇
操作json,导⼊数据库
下⾯贴出插⼊代码
public void doinsertdata()
{
using(StreamReader sr = File.OpenText("Toyear.json"))
{
string json = sr.ReadToEnd();
//List<Test> list = JsonConvert.DeserializeObject<List<Test>>(json);
bal.leave.bal_leave bal =new bal.leave.bal_leave();
int IndexofA = json.IndexOf("[");
int IndexofB = json.IndexOf("]");
string Ru = json.Substring(IndexofA, IndexofB - IndexofA +1);
JavaScriptSerializer Serializer =new JavaScriptSerializer();
List<Test> objs = Serializer.Deserialize<List<Test>>(Ru);
for(int i =0; i < objs.Count; i++)
{
//sql操作插⼊(⽇期,类型)
insert_toyearData(objs[i].dayStr, objs[i].type);
}
}
}
public class Test
{
public string dayStr {get;set;}
public string type {get;set;}
}
插⼊成功后得到以下节假⽇表
⾃增长编号⽇期类型
1202001012
2202001020
3202001030⾃增长编号⽇期类型4202001041
后⾯省略…
接下来是存储过程操作
USE[OA]
GO
/****** Object:  StoredProcedure [dbo].[get_leavehours]    Script Date: 2020/7/14 9:52:56 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
//此次⽤于测试
--declare @le_hours decimal(18,1)
--exec get_leavehours '2020-07-01 07:00:00','2020-07-04 11:00:00',@le_hours output
ALTER proc[dbo].[get_leavehours]
@startTime datetime,
@endTIme datetime,
@le_hours decimal(18,1)  output
as
begin
DECLARE@kday int
declare@stime date
declare@etime date
declare@fday decimal(18,1)
declare@sday decimal(18,1)
--初始化数据格式yyyy-mm-dd
set@stime=@startTime
set@etime=@endTime
set@kday=0
SET@le_hours=0.0
SET@fday=0.0
SET@sday=0.0
--如果起始时间在00:00 ⾄ 09:00    设置起始时间为09:00:00
IF@startTime>= dbo.fnConcatStr(@stime,'00:00:00')AND@startTime< dbo.fnConcatStr(@stime,'09:00:00')
begin
SET@startTime= cast(dbo.fnConcatStr(@stime,'09:00:00')as datetime);
end
--如果结束时间在17:30 ⾄ 23:59    设置结束时间为17:30:00
IF@endTime> dbo.fnConcatStr(@etime,'17:30:00')AND@endTime<= dbo.fnConcatStr(@etime,'23:59:00')
begin
SET@endTime= dbo.fnConcatStr(@etime,'17:30:00');
end
--如果起始时间在12:00 ⾄ 13:00  设置起始时间为13:00:00
IF@startTime> dbo.fnConcatStr(@stime,'12:00:00')AND@startTime< dbo.fnConcatStr(@stime,'13:00:00')
begin
SET@startTime= dbo.fnConcatStr(@stime,'13:00:00');
end
--如果结束时间在12:00 ⾄ 13:00    设置结束时间为12:00:00
--如果结束时间在12:00 ⾄ 13:00    设置结束时间为12:00:00
IF@endTime> dbo.fnConcatStr(@etime,'12:00:00')AND@endTime< dbo.fnConcatStr(@etime,'13:00:00')
begin
SET@endTime= dbo.fnConcatStr(@etime,'12:00:00');
end
--如果起始时间在17:30 ⾄ 23:59    设置起始时间为第⼆天09:00:00(⼀般不会出现这种情况防⽌万⼀)
IF@startTIme>= dbo.fnConcatStr(@stime,'17:30:00')AND@startTIme<= dbo.fnConcatStr(@stime,'23:59:00')
begin
SET@startTIme= dbo.fnConcatStr(dateadd(day,1,@stime),'09:00:00');
set@stime=dateadd(day,1,@stime);
end
--如果结束时间在00:00 ⾄ 09:00    设置结束时间为前⼀天17:30:00 (⼀般不会出现这种情况防⽌万⼀)
IF@endTime>= dbo.fnConcatStr(@etime,'00:00:00')AND@endTime<= dbo.fnConcatStr(@etime,'09:00:00')
begin
SET@endTime= dbo.fnConcatStr(dateadd(day,-1,@etime),'17:30:00');
set@etime=dateadd(day,-1,@etime);
end
--起始结束时间⼀样
if@startTime=@endTime
begin
SET@le_hours=0.0
end
--同⼀天
IF@stime=@etime
begin
--同⼀时段(同是上午或下午)
IF((@startTime>= dbo.fnConcatStr(@stime,'09:00:00')AND@endTime<= dbo.fnConcatStr(@etime,'12:00:00'))or(@startTime>= dbo.fnConcatStr (@stime,'13:00:00')AND@endTime<= dbo.fnConcatStr(@etime,'17:30:00')))
begin
SET@le_hours= datediff(MINUTE,@startTime,@endTime)/60.0
end
--不在同⼀时段
ELSE
begin
SET@le_hours=  datediff(MINUTE,@startTime,@endTime)/60.0-1
end
end
--跨天
ELSE
begin
--判断开始⽇期是否为⼯作⽇
-
-若存在则说明开始⽇期不是节假⽇,是⼯作⽇
if exists(select*from _rqv_letime_data WHERE t_type =0and CONVERT(varchar(100),@startTime,112)=t_data)
begin
--不是节假⽇,计算请假当天请假多少⼩时
--判断时段是上午或下午
if@startTime>= dbo.fnConcatStr(@stime,'09:00:00')AND@startTime<= dbo.fnConcatStr(@stime,'12:00:00')
begin
SET@fday=datediff(MINUTE,@startTime,dbo.fnConcatStr(@stime,'17:30:00'))/60.0-1
end
else if@startTime>= dbo.fnConcatStr(@stime,'13:00:00')AND@startTime<= dbo.fnConcatStr(@stim
e,'17:30:00')
begin
SET@fday=datediff(MINUTE,@startTime,dbo.fnConcatStr(@stime,'17:30:00'))/60.0
end
end
--判断结束⽇期是否是⼯作⽇
--若存在则说明结束⽇期不是节假⽇,是⼯作⽇
if exists(select*from _rqv_letime_data WHERE t_type =0and CONVERT(varchar(100),@endTime,112)=t_data)
begin
--不是节假⽇,计算请假最后⼀天请假多少⼩时
--判断时段是上午或下午
if@endTime>= dbo.fnConcatStr(@etime,'09:00:00')AND@endTime<= dbo.fnConcatStr(@etime,'12:00:00')
2020法定节假日时间表begin
SET@sday=datediff(MINUTE,dbo.fnConcatStr(@etime,'09:00:00'),@endTime)/60.0
end
else if@endTime>= dbo.fnConcatStr(@etime,'13:00:00')AND@endTime<= dbo.fnConcatStr(@etime,'17:30:00')
begin
SET@sday=datediff(MINUTE,dbo.fnConcatStr(@etime,'09:00:00'),@endTime)/60.0-1
end
end
declare@break int
declare@stepmax int
declare@step int
set@break=1
set@step=1
set@stepmax=1000
WHILE@break=1
begin
if exists(select*from _rqv_letime_data WHERE t_type =0and CONVERT(varchar(100), dateadd(DAY,1,@startTime),112)=t_data) --若存在则说明该天不是节假⽇,是⼯作⽇
begin
if dateadd(DAY,1,@stime)<@etime
begin
SET@kday=@kday+1;
SET@stime=dateadd(DAY,1,@stime)
SET@startTime=dateadd(DAY,1,@startTime)
end
end
if@stime=@etime
begin
set@break=0
end
else
begin
set@step=1+@step
if@step>@stepmax
begin
set@break=0
end
end
end
--计算总请假多少⼩时
SET@le_hours=@le_hours+@fday+@sday+@kday*7.5;
end
--print @stime
-
-print @etime
--print @etime
--print @startTime --print @endTime
--print @kday
--print @fday
--print @sday
--print @le_hours end