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:

Excelente algoritmo y explicaciones ¡¡¡
ResponderEliminarHola, saca mucho errores, no ha sido posible probarla:
ResponderEliminarMens 156, Nivel 15, Estado 1, Procedimiento F_CREAR_FECHA, Línea 13
Sintaxis incorrecta cerca de la palabra clave 'CREATE'.
Mens 111, Nivel 15, Estado 1, Procedimiento F_CREAR_FECHA, Línea 13
'CREATE FUNCTION' debe ser la primera instrucción en un lote de consultas.
Mens 137, Nivel 15, Estado 2, Procedimiento F_CREAR_FECHA, Línea 48
Debe declarar la variable escalar "@FECHA".
Mens 137, Nivel 15, Estado 2, Procedimiento F_CREAR_FECHA, Línea 50
Debe declarar la variable escalar "@FECHA".
Mens 137, Nivel 15, Estado 2, Procedimiento F_CREAR_FECHA, Línea 54
Debe declarar la variable escalar "@FECHA".
Mens 156, Nivel 15, Estado 1, Procedimiento F_CALCULA_DOMINGO_PASCUA, Línea 138
Sintaxis incorrecta cerca de la palabra clave 'DROP'.
Mens 156, Nivel 15, Estado 1, Procedimiento F_LISTA_FESTIVOS, Línea 175
Sintaxis incorrecta cerca de la palabra clave 'DROP'.
Mens 156, Nivel 15, Estado 1, Procedimiento F_CALCULA_ES_FESTIVO, Línea 189
Sintaxis incorrecta cerca de la palabra clave 'SELECT'.
Mens 195, Nivel 15, Estado 10, Procedimiento F_CALCULA_ES_FESTIVO, Línea 189
'F_CALCULA_ES_FESTIVO' no es un nombre de función integrada reconocido.
muchas gracia por sus aportes me has ayudado, lo modifique para sql server 2005.
ResponderEliminarExcelente!!!, no entendí la verdad por que se calculan de esa forma, tengo entendido que es basado en el método de gauss con algebra modular, lo que me pareció mas difícil fue lo del domingo de pascua.
ResponderEliminarLo implemente y corre de maravilla has hecho un excelente trabajo, muuuchas gracias!!!.