

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[HorasHabilesNOCFES]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[HorasHabilesNOCFES]
go
CREATE function [dbo].[HorasHabilesNOCFES](@fecha1 as datetime, @fecha2 as datetime,@fes as bit,@noc as bit) returns  float 
as 
begin
declare @f1 datetime
declare @f2 datetime
declare @f1pro_temp datetime
declare @f2pro_temp datetime
declare @f1noc_temp datetime
declare @f2noc_temp datetime
declare @horaIni_pro nvarchar(10)
declare @horaFin_pro nvarchar(10)
declare @horaIni_noc nvarchar(10)
declare @horaFin_noc nvarchar(10)
declare @horasTotales float
declare @noct as bit
set @horasTotales=0
select @horaIni_pro=valor from gen_config where config='horaInicioProgramacion'
select @horaFin_pro=valor from gen_config where config='horaFinProgramacion'
select @horaIni_noc=valor from gen_config where config='HoraInicioNocturno'
select @horaFin_noc=valor from gen_config where config='HoraFinNocturno'
set @f1=@fecha1
set @f2=@fecha2
set @noct =0



while @f1<@fecha2--inicio while
begin --inicio while
if (datediff(minute,@f1, @fecha2)/60.0) > 1 
begin 
 set @f2=dateadd(hh,1,@f1)
end 
else
begin
set @f2=@fecha2
end 

set @noct =0
if @noc=0 and @fes=0
begin--inicio dias ordinales
	if not exists(  select id from gen_diaFestivo where active=1 and fecha_ff=convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar),103) )
	begin--inicio de dias normales
					set @f1pro_temp= convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar)+' '+@horaIni_pro,103)
					set @f2pro_temp= convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar)+' '+@horaFin_pro,103)
					if @f1 >= @f1pro_temp and  @f2 <= @f2pro_temp begin--la fecha esta dentro del rango de la programacion
						set @f1= @f1
					end --la fecha esta dentro del rango de la programacion
					if @f1 < @f1pro_temp and  @f2 > @f2pro_temp begin--la fecha esta fuera del rango de la programacion
						set @f1=@f1pro_temp 
						set @f2=@f2pro_temp 
					end --la fecha esta fuera del rango de la programacion
					if @f1 > @f1pro_temp and @f1<@f2pro_temp  and   @f2 > @f2pro_temp   begin--la fecha ini esta dentro del rango
    					set @f2=@f2pro_temp 
					end --la fecha ini esta dentro del rango
					  if @f1 < @f1pro_temp and @f2>@f1pro_temp  and   @f2 < @f2pro_temp   begin--la fecha fin esta dentro del rango
    					set @f1=@f1pro_temp 
					end --la fecha ini esta dentro del rango
					if not(@f1>=@f1pro_temp and @f1<=@f2pro_temp and @f2>=@f1pro_temp and @f2<=@f2pro_temp)  begin  set @noct=1 end
	end-- fin de dias normales
	else begin set @noct=1 end
end --fin de dia ordinales
else begin --else dia normal
--set @f1=0
if @noc=1 begin-- inicio de nocturnos
				if(not exists(  select id from gen_diaFestivo where active=1 and fecha_ff=convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar),103) ))
				begin--inicio nocturno1
					set @f1pro_temp= convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar)+' '+@horaIni_noc,103)
					set @f2pro_temp= convert(smalldatetime,cast(day(@f2) as nvarchar)+'/'+cast(month(@f2) as nvarchar)+'/'+cast(year(@f2) as nvarchar)+' '+@horaFin_noc,103)
					if @f2< @f2pro_temp and @f1< @f2pro_temp begin-- las dos fechas estan en la maņana nocturna 
					set @f1pro_temp= convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar)+' 00:00',103)
					
					if @f1 >= @f1pro_temp and  @f2 <= @f2pro_temp begin--la fecha esta dentro del rango de la programacion
					set @f1= @f1
					end --la fecha esta dentro del rango de la programacion
					if @f1 < @f1pro_temp and  @f2 > @f2pro_temp begin--la fecha esta fuera del rango de la programacion
					set @f1=@f1pro_temp 
					set @f2=@f2pro_temp 
					end --la fecha esta dentro del rango de la programacion
					if @f1 > @f1pro_temp and @f1<@f2pro_temp  and   @f2 > @f2pro_temp   begin--la fecha ini esta dentro del rango
					set @f2=@f2pro_temp 
					end --la fecha ini esta dentro del rango
					if @f1 < @f1pro_temp and @f2>@f1pro_temp  and   @f2 < @f2pro_temp   begin--la fecha fin esta dentro del rango
					set @f1=@f1pro_temp 
					end --la fecha ini esta dentro del rango
					if not(@f1>=@f1pro_temp and @f1<=@f2pro_temp and @f2>=@f1pro_temp and @f2<=@f2pro_temp)  begin  set @noct=1 end



					end --fin fechas maņana nocturno
					else begin
							if @f2>= @f1pro_temp or @f1>= @f1pro_temp begin-- nocturno tarde
					          set @f2pro_temp= convert(smalldatetime,cast(day(@f2) as nvarchar)+'/'+cast(month(@f2) as nvarchar)+'/'+cast(year(@f2) as nvarchar)+' 23:59',103)
								if @f1 >= @f1pro_temp and  @f2 <= @f2pro_temp begin--la fecha esta dentro del rango de la programacion
								set @f1= @f1
								end --la fecha esta dentro del rango de la programacion
								if @f1 < @f1pro_temp and  @f2 > @f2pro_temp begin--la fecha esta fuera del rango de la programacion
								set @f1=@f1pro_temp 
								set @f2=@f2pro_temp 
								end --la fecha esta dentro del rango de la programacion
								if @f1 > @f1pro_temp and @f1<@f2pro_temp  and   @f2 > @f2pro_temp   begin--la fecha ini esta dentro del rango
								set @f2=@f2pro_temp 
								end --la fecha ini esta dentro del rango
								if @f1 < @f1pro_temp and @f2>@f1pro_temp  and   @f2 < @f2pro_temp   begin--la fecha fin esta dentro del rango
							   -- set @result= @result +'-G'			
								set @f1=@f1pro_temp 
								end --la fecha fin esta dentro del rango
								if not(@f1>=@f1pro_temp and @f1<=@f2pro_temp and @f2>=@f1pro_temp and @f2<=@f2pro_temp)  begin  set @noct=1 end

							 end -- nocturno tarde e
							else begin set @noct=1 end
				    end 
						
										


				end -- fin nocturno1
				else begin set @noct=1 end
				
end -- fin de nocturnos
else
 begin 
  if @fes=1 begin -- inicio de festivos
			if( exists(  select id from gen_diaFestivo where active=1 and fecha_ff=convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar),103) ))
			begin--inicio festivos1
							set @f1pro_temp= convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar)+' 00:00',103)
							set @f2pro_temp= convert(smalldatetime,cast(day(@f1) as nvarchar)+'/'+cast(month(@f1) as nvarchar)+'/'+cast(year(@f1) as nvarchar)+' 23:59',103)
							if @f1 >= @f1pro_temp and  @f2 <= @f2pro_temp begin--la fecha esta dentro del rango de la programacion
							set @f1= @f1
							end --la fecha esta dentro del rango de la programacion
							if @f1 < @f1pro_temp and  @f2 > @f2pro_temp begin--la fecha esta fuera del rango de la programacion
							set @f1=@f1pro_temp 
							set @f2=@f2pro_temp 
							end --la fecha esta dentro del rango de la programacion
							if @f1 > @f1pro_temp and @f1<@f2pro_temp  and   @f2 > @f2pro_temp   begin--la fecha ini esta dentro del rango
							set @f2=@f2pro_temp 
							end --la fecha ini esta dentro del rango
							if @f1 < @f1pro_temp and @f2>@f1pro_temp  and   @f2 < @f2pro_temp  begin--la fecha fin esta dentro del rango
							set @f1=@f1pro_temp 
							end 
						    if not(@f1>=@f1pro_temp and @f1<=@f2pro_temp and @f2>=@f1pro_temp and @f2<=@f2pro_temp)  begin  set @noct=1 end
							
			end -- fin festivos 1
			else begin set @noct=1 end
  end-- fin de festivos 
end

 end -- fin else dia normal
if @noct=0 begin
	set @horasTotales=  @horasTotales+(cast(datediff(second,@f1, @f2) as float)/cast(3600 as float))  
end
set @f1=@f2
end --fin while
return @horasTotales 
end