Está compuesto por 5 funciones de las cuales tres son para acciones auxiliares y las dos restantes permiten listar los festivos de un año determinado o verificar si una fecha es festivo.
Espero sea de utilidad.
1. Función que nos permite crear una fecha a partir del día, mes y año. Para evitar problemas con la configuración regional.
DROP FUNCTION F_CREAR_FECHA GO CREATE FUNCTION F_CREAR_FECHA(@ANIO INT, @MES INT, @DIA INT) RETURNS DATE AS BEGIN RETURN DATEADD(mm, (@ANIO - 1900) * 12 + @MES - 1 , @DIA - 1) END2. Función que a partir de una fecha obtiene el siguiente lunes.
DROP FUNCTION F_OBTENER_SIGUIENTE_LUNES GO CREATE FUNCTION F_OBTENER_SIGUIENTE_LUNES(@FECHA DATE) RETURNS DATE AS BEGIN DECLARE @LUNES INT = 1 IF @@DATEFIRST = 7 BEGIN SET @LUNES = 2 END IF @@DATEFIRST = 1 BEGIN SET @LUNES = 1 END IF @@DATEFIRST = 2 BEGIN SET @LUNES = 7 END IF @@DATEFIRST = 3 BEGIN SET @LUNES = 6 END IF @@DATEFIRST = 4 BEGIN SET @LUNES = 5 END IF @@DATEFIRST = 5 BEGIN SET @LUNES = 4 END IF @@DATEFIRST = 6 BEGIN SET @LUNES = 3 END DECLARE @FECHA_DEVOLVER DATE IF DATEPART(DW, @FECHA) = @LUNES BEGIN SET @FECHA_DEVOLVER = @FECHA END ELSE BEGIN SET @FECHA_DEVOLVER = DATEADD([day], ((DATEDIFF([day], '19000101', @FECHA) / 7) * 7) + 7, '19000101'); END RETURN @FECHA_DEVOLVER END3. Función que calcula el domingo de pascua para un año en particular.
DROP FUNCTION F_CALCULA_DOMINGO_PASCUA GO CREATE FUNCTION F_CALCULA_DOMINGO_PASCUA(@A_ANO INT) RETURNS DATE AS BEGIN DECLARE @M INT = 25 DECLARE @N INT = 5 DECLARE @A INT DECLARE @B INT DECLARE @C INT DECLARE @D INT DECLARE @E INT DECLARE @DIA INT DECLARE @MES INT IF (@A_ANO >= 1583 AND @A_ANO <= 1699) BEGIN SET @M = 22 SET @N = 2 END ELSE IF (@A_ANO >= 1700 AND @A_ANO <= 1799) BEGIN SET @M = 23 SET @N = 3 END ELSE IF (@A_ANO >= 1800 AND @A_ANO <= 1899) BEGIN SET @M = 23 SET @N = 4 END ELSE IF (@A_ANO >= 1900 AND @A_ANO <= 2099) BEGIN SET @M = 24 SET @N = 5 END ELSE IF (@A_ANO >= 2100 AND @A_ANO <= 2199) BEGIN SET @M = 24 SET @N = 6; END ELSE IF (@A_ANO >= 2200 AND @A_ANO <= 2299) BEGIN SET @M = 25 SET @N = 0 END SET @A = @A_ANO % 19 SET @B = @A_ANO % 4 SET @C = @A_ANO % 7 SET @D = (19 * @A + @M) % 30; SET @E = (2 * @B + 4 * @C + 6 * @D + @N) % 7; IF (@D + @E < 10) BEGIN SET @DIA = @D + @E + 22 SET @MES = 3 END ELSE BEGIN SET @DIA = @D + @E - 9 SET @MES = 4 END IF (@DIA = 26 AND @MES = 4) BEGIN SET @DIA = 19 END IF (@DIA = 25 AND @MES = 4 AND @D = 28 AND @E = 6 AND @A > 10) BEGIN SET @DIA = 18 END RETURN dbo.F_CREAR_FECHA(@A_ANO, @MES, @DIA); END4. Función Recibe un año y retorna el listado de los festivos para ese año.
DROP FUNCTION F_LISTA_FESTIVOS GO CREATE FUNCTION F_LISTA_FESTIVOS(@ANIO INT) RETURNS @ListaFestivos TABLE(FechaFestivo DATE, Descripcion VARCHAR(50)) AS BEGIN DECLARE @PASCUA DATE = dbo.F_CALCULA_DOMINGO_PASCUA(@ANIO) DECLARE @ES_FESTIVO BIT = 0 -- Festivos Fecha Fija INSERT INTO @ListaFestivos VALUES(dbo.F_CREAR_FECHA(@ANIO, 1, 1), 'Año Nuevo') INSERT INTO @ListaFestivos VALUES(dbo.F_CREAR_FECHA(@ANIO, 5, 1), 'Día del Trabajo') INSERT INTO @ListaFestivos VALUES(dbo.F_CREAR_FECHA(@ANIO, 7, 20), 'Grito de la Independencia') INSERT INTO @ListaFestivos VALUES(dbo.F_CREAR_FECHA(@ANIO, 8, 7), 'Batalla de Boyacá') INSERT INTO @ListaFestivos VALUES(dbo.F_CREAR_FECHA(@ANIO, 12, 8), 'Inmaculada Concepción') INSERT INTO @ListaFestivos VALUES(dbo.F_CREAR_FECHA(@ANIO, 12, 25), 'Navidad') -- Festivos Siguiente Lunes INSERT INTO @ListaFestivos VALUES(dbo.F_OBTENER_SIGUIENTE_LUNES(dbo.F_CREAR_FECHA(@ANIO, 1, 6)), 'Epifanía (Reyes Magos)') INSERT INTO @ListaFestivos VALUES(dbo.F_OBTENER_SIGUIENTE_LUNES(dbo.F_CREAR_FECHA(@ANIO, 3, 19)), 'San José esposo de la virgen María') INSERT INTO @ListaFestivos VALUES(dbo.F_OBTENER_SIGUIENTE_LUNES(dbo.F_CREAR_FECHA(@ANIO, 6, 29)), 'San Pedro y San Pablo') INSERT INTO @ListaFestivos VALUES(dbo.F_OBTENER_SIGUIENTE_LUNES(dbo.F_CREAR_FECHA(@ANIO, 8, 15)), 'Asunción de la Virgen') INSERT INTO @ListaFestivos VALUES(dbo.F_OBTENER_SIGUIENTE_LUNES(dbo.F_CREAR_FECHA(@ANIO, 10, 12)), 'Día de la Raza') INSERT INTO @ListaFestivos VALUES(dbo.F_OBTENER_SIGUIENTE_LUNES(dbo.F_CREAR_FECHA(@ANIO, 11, 1)), 'Todos los Santos') INSERT INTO @ListaFestivos VALUES(dbo.F_OBTENER_SIGUIENTE_LUNES(dbo.F_CREAR_FECHA(@ANIO, 11, 11)), 'Independencia de Cartagena') -- Festivos Dependientes de la pascua INSERT INTO @ListaFestivos VALUES(DATEADD(DAY,-7,@PASCUA), 'Domingo De Ramos') INSERT INTO @ListaFestivos VALUES(DATEADD(DAY,-3,@PASCUA), 'Jueves Santo') INSERT INTO @ListaFestivos VALUES(DATEADD(DAY,-2,@PASCUA), 'Viernes Santo') INSERT INTO @ListaFestivos VALUES(@PASCUA, 'Domingo De Pascua') INSERT INTO @ListaFestivos VALUES(DATEADD(DAY,43,@PASCUA), 'Ascensión de Jesús') INSERT INTO @ListaFestivos VALUES(DATEADD(DAY,64,@PASCUA), 'Corpus Christi') INSERT INTO @ListaFestivos VALUES(DATEADD(DAY,71,@PASCUA), 'Sagrado Corazón de Jesús') RETURN; END5.Función Recibe una fecha y retorna un Booleano indicando si es festivo o no
DROP FUNCTION F_CALCULA_ES_FESTIVO GO CREATE FUNCTION F_CALCULA_ES_FESTIVO(@FECHA DATE) RETURNS BIT AS BEGIN DECLARE @ES_FESTIVO BIT = 0 IF EXISTS (SELECT * FROM dbo.F_LISTA_FESTIVOS(YEAR(@FECHA)) WHERE FechaFestivo = @FECHA) BEGIN SET @ES_FESTIVO = 1 END RETURN (@ES_FESTIVO); ENDPor último la manera de verificar las funciones:
SELECT dbo.F_CALCULA_ES_FESTIVO(CONVERT(DATE, '01/01/2016')) EsFestivo SELECT * FROM dbo.F_LISTA_FESTIVOS(2016) ORDER BY FechaFestivo
Y el resultado de las consultas seria el siguiente:
