martes, 15 de enero de 2013

Crear una tabla de días festivos de Colombia

He visto la necesidad de tener una tabla de datos de fechas, donde indique atributos de cada una de las fechas e indique si es o no un día sábado, domingo o festivo en Colombia.

A continuación les mostrare como crear una estructura de datos (tabla) en el motor SQL Server para poder identificar si una fecha en particular es o no un día festivo en Colombia.

1. Crear tablas

Lo primero que se debe hacer es crear las tablas que se necesitaran para este proceso, para esto descargue el archivo Script Tablas.sql

Este script crea dos tablas.

  • Tiempo: esta tabla es el resultado final, en esta se mostraran las fechas y si es un día hábil (incluidos los festivos) o no.
  • Fechas: Son las fechas del 01 de enero de 2005 al 31 de diciembre de 2030.


Una vez creadas las tablas en la base de datos, descargue y ejecute el script de inserción de días festivos del archivo InsercionDiasFestivos.sql

2. Insertar registros en la tabla tiempo

A continuación ejecute el siguiente script o descarguelo, este insertará las fechas desde el 01 de enero de 2005 hasta el 31 de diciembre de 2030, y marcará los días sábados, domingos y festivos de Colombia como días no hábiles.


--Asignacion de lenguage de la sesion de base de datos
SET LANGUAGE SPANISH

--Fecha inicial desde la cual se va a crear la tabla con los dias festivos
DECLARE @fecha AS DATETIME
SET @fecha = '2005-01-01 00:00:00.000'

--Se eliminan datos de la tabla de Fechas
TRUNCATE TABLE Tiempo

IF EXISTS(SELECT name FROM sysobjects WHERE name = N'Fechas' AND xtype='U')
      DROP TABLE Fechas
create table Fechas
( fecha datetime )

-- Se inserta las fechas desde 2005-01-01 hasta 2018-12-31
while (@fecha < '2031-01-01 00:00:00.000')
begin
      INSERT      INTO fechas
      SELECT      @fecha
      SELECT      @fecha = @fecha +1
END

--Se declara cursor para generar la insercion de datos en la tabla tiempo
DECLARE fechas_cursor CURSOR FOR
SELECT      Fecha 
FROM  Fechas

OPEN fechas_cursor

FETCH NEXT FROM fechas_cursor
INTO @fecha

WHILE @@FETCH_STATUS = 0
BEGIN
      INSERT      INTO tiempo
      SELECT      @fecha Fecha,
                  YEAR(@fecha) as Año,
                  month(@fecha) as Mes,
                  day(@fecha) as Dia,
                  DATENAME(mm, @FECHA) MesNombre,
                  DATENAME(dw, @FECHA) DiaNombre,
                  datepart(dy,@fecha) as DiaAño,
                  convert(varchar(10),datepart(wk,@fecha)) SemanaAño,
                  CASE WHEN MONTH(@fecha)<=THEN '1' ELSE '2' END Semestre,
                  CASE WHEN MONTH(@fecha)<=THEN '1'
                         WHEN MONTH(@fecha)<=THEN '2'
                         WHEN MONTH(@fecha)<=THEN '3'
                         WHEN MONTH(@fecha)<= 12 THEN '4' END Trimestre,
                  case WHEN MONTH(@fecha)<=THEN '1'
                         WHEN MONTH(@fecha)<=THEN '2'
                         WHEN MONTH(@fecha)<= 12  THEN '3'END Cuatrimestre,
                  CASE WHEN DATEPART(DW, @fecha) = 6 THEN 0 -- Se marca el dia sabado como dia no habil
                         WHEN DATEPART(DW, @fecha) = 7 THEN 0 -- Se marca el dia domingo como dia no habil
                         ELSE 1 END DiaHabil

      FETCH NEXT FROM fechas_cursor
      INTO @fecha
END
CLOSE fechas_cursor;
DEALLOCATE fechas_cursor;


-- Se marcan los dias festivos como dias no habiles
UPDATE      tiempo SET diahabil = 0
FROM  TIEMPO T
            INNER JOIN FESTIVOS F ON Convert(varchar(10),T.fecha,101) = Convert(varchar(10),F.[Fecha],101)


--Eliminar tabla temporal
IF EXISTS(SELECT name FROM sysobjects WHERE name = N'Fechas' AND xtype='U')
      DROP TABLE Fechas

3. Resultado final

Ahora podrá realizar la selección de los registros de la tabla creada.

--Resultado final
select * from tiempo


Tabla tiempo
Tabla Tiempo

18 comentarios:

  1. Excelente post...

    Me gustaria saber si la fecha hasta la que inserto los datos la puedo cambiar por ejemplo hasta 2030
    sin afectar el funcionamiento del script.

    Gracias!

    ResponderEliminar
    Respuestas
    1. Hola Maleja Valencia

      Actualice el post para que el script funcione hasta el año 2030.

      Ejecutalo y me cuentas como va todo...

      Slds!

      Eliminar
    2. Muchisimas gracias!!

      Me sirvió demasiado tu post!!

      Eliminar
  2. Hola tiene algo que ver la configuracion regional en mi maquina, puesto que toma todas las fechas mal, que formato tiene la fecha de los días festivos?

    ResponderEliminar
  3. Hola Edinson

    La fecha en el script esta en formato Hexadecimal y se hace un cast a DateTime, para que no suceda este tipo de inconvenientes.

    Mi configuración regional es "Español (Colombia)" y los formatos de fecha y hora son:
    Fecha corta: dd/MM/aaaa
    Fecha larga: dddd,dd' de 'MMMM' de 'aaaa
    Hora corta: hh:mm tt
    Hora larga: hh:mm:ss tt
    Primer día de la semana: domingo

    Intenta cambiar la configuración en tu maquina, si no funciona, ejecuta esta sentencia SQL antes de iniciar todo el proceso

    SET LANGUAGE SPANISH;

    Saludos!

    ResponderEliminar
    Respuestas
    1. Este comentario ha sido eliminado por el autor.

      Eliminar
    2. Eso mismo pense por aquello que son numeros las fechas internamente, con esto la presentación( formato ) no tendría nada que ver, pero encuentro que unas fechas me las ingresa mal, Ejem mira el 2014 como lo grabo; adiciono la sentencia de consulta con la cual observo lo que creo que esta mal:
      select *, Year(fecha) AÑO,Month(Fecha) MES,DAY(fecha) DIA from festivos where Year(fecha) = 2014 order by fecha

      ----Resultado Consulta-----
      Nombre Fecha AÑO MES DIA
      Año Nuevo (Colombia) 2014-01-01 00:00:00.000 2014 1 1
      Dia del Trabajo (Colombia) 2014-01-05 00:00:00.000 2014 1 5
      Asencion del señor (Colombia) 2014-02-06 00:00:00.000 2014 2 6
      Dia de Todos los Santos (Colombia) 2014-03-11 00:00:00.000 2014 3 11
      San Jose (Colombia) 2014-03-24 00:00:00.000 2014 3 24
      Jueves Santo (Colombia) 2014-04-17 00:00:00.000 2014 4 17
      Viernes Santo (Colombia) 2014-04-18 00:00:00.000 2014 4 18
      La Epifania (Colombia) 2014-06-01 00:00:00.000 2014 6 1
      Corpus Christi (Colombia) 2014-06-23 00:00:00.000 2014 6 23
      San Pedro y San Pablo (Colombia) 2014-06-30 00:00:00.000 2014 6 30
      Sagrado Corazon (Colombia) 2014-06-30 00:00:00.000 2014 6 30
      Batalla de Boyaca (Colombia) 2014-07-08 00:00:00.000 2014 7 8
      Dia de la Independencia (Colombia) 2014-07-20 00:00:00.000 2014 7 20
      La Inmaculada Concepcion (Colombia) 2014-08-12 00:00:00.000 2014 8 12
      Asuncion de la Virgen (Colombia) 2014-08-13 00:00:00.000 2014 8 13
      Independencia de Cartagena (Colombia) 2014-11-17 00:00:00.000 2014 11 17
      Dia de la raza (Colombia) 2014-12-10 00:00:00.000 2014 12 10
      Navidad (Colombia) 2014-12-25 00:00:00.000 2014 12 25

      Eliminar
  4. Amigo y si solo quisiera domingos y los dias festivos, osea sabado que cuente como dia laborable como haria?

    ResponderEliminar
  5. En la vida real algunos festivos que caen entre semana se mueven al lunes siguiente, ¿este script reajusta automáticamente las fechas en esas ocasiones?

    ResponderEliminar
  6. Excelente post. Lastima que tenga problemas con la fecha. En mi caso el día de trabajo aparece como Enero 05 y no como Mayo 01. He puesto la configuración en español, pero el problema permanece.

    ResponderEliminar
  7. Excelente!!! Mil gracias me sirvió muchísimo.

    ResponderEliminar
  8. Buenas noches gracias por su colaboracion, tengo la duda como usted obtiene los valores de las fechas en hexadecimal gracias.

    ResponderEliminar
    Respuestas
    1. Hola Omar

      Puedes lograrlo haciendo un export data a SqlScript desde el SqlManagementManagementStudio.

      Saludos!

      Eliminar
  9. Hola buenos dias, una pregunta me sale como error esto "El nombre de objeto 'tiempo' no es válido." Que debo hacer para q no me salga el error?

    ResponderEliminar
  10. Alguien podria hacer este codigo para mysql

    ResponderEliminar
  11. Hola chicos, para el codigo de la insercion de dias festivos, podria alguien realizarlo en MySQL, no comprendo ese valor Hexadecimal, ni tampoco la sintaxis que lleva!!

    ResponderEliminar
  12. No funciona, los festinos no coinciden con los festivos de colombia.

    ResponderEliminar
  13. no me aprecen los festivos del 2020

    ResponderEliminar