October 7th, 2009

Día hábil anterior/próximo en PostgreSQL

base de datos, by admin.

Unos “conocidos” reclamaron que no solamente deseaban sacar el proximo día hábil, sino también deseaban saber cuales eran los N anteriores días habiles. Ademas se reportaron fallos con fecha sabado y/o domingo.

Por lo anterior y otras razones más, publico la v2 que ahora se llama dia_habil y se utiliza de la siguiente forma:

  • Para el/los próximo(s) día(s):
1
SELECT utilidades.dia_habil(15, current_date);
  • Para el/los anterior(es) día(s):
1
SELECT utilidades.dia_habil(-15, current_date);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
--DROP FUNCTION utilidades.dia_habil (IN in_dias int4, IN in_desde date) CASCADE;
/**
* Funcion que calcula el ANTERIOR o PROXIMO dia habil
*
* @date 2009-10-07
* @author MANUEL DIEGO PAILLAFIL GAMBOA
* @email manuel@radiohead.cl
* @url http://manuel.radiohead.cl/
*
* @param INT
* @param DATE
*/

CREATE OR REPLACE FUNCTION utilidades.dia_habil(in_dias integer, in_desde date)
  RETURNS date AS
$BODY$
    DECLARE
    fecha_actual date := in_desde;
    fecha_limite date;
    retorno date;
    dias_extras int4 := 0;
    dias_extras_alt int4 := 0;
    dia int4;
    generate_digit1 int4;
    generate_digit2 int4;
    row_fechas record;
    row_fechas_alt record;
    BEGIN
    IF(in_dias < 0)THEN
        generate_digit1 := in_dias;
        generate_digit2 := -1;
        SELECT EXTRACT(DOW FROM fecha_actual) INTO dia;
        IF(dia = 0)THEN
            fecha_actual := fecha_actual - '1 days'::interval;
        ELSE IF(dia = 6)THEN
            fecha_actual := fecha_actual - '0 days'::interval;
        END IF;
        END IF;
        fecha_limite := fecha_actual;
    ELSE
        generate_digit1 := 1;
        generate_digit2 := in_dias;
        SELECT EXTRACT(DOW FROM fecha_actual) INTO dia;
        IF(dia = 0)THEN
            fecha_actual := fecha_actual - '2 day'::interval;
        ELSE IF(dia = 6)THEN
            fecha_actual := fecha_actual - '1 days'::interval;
        END IF;
        END IF;
        fecha_limite := fecha_actual;
    END IF;
   
    FOR row_fechas IN SELECT fecha_actual + s.a AS fecha FROM generate_series(generate_digit1,generate_digit2,1) AS s(a) LOOP
        SELECT EXTRACT(DOW FROM row_fechas.fecha) INTO dia;
            IF(dia = 6 AND in_dias > 0)THEN
                dias_extras := dias_extras + 2;
            ELSE IF(dia = 0 AND in_dias < 0)THEN
                dias_extras := dias_extras - 2;
            END IF;
            END IF;
    END LOOP;

    IF(in_dias < 0)THEN
        generate_digit1 := in_dias + dias_extras;
        generate_digit2 := -1;
    ELSE
        generate_digit1 := 1;
        generate_digit2 := in_dias + dias_extras;
    END IF;

    FOR row_fechas_alt IN SELECT fecha_actual + s.a AS fecha FROM generate_series(generate_digit1,generate_digit2,1) AS s(a) LOOP
        SELECT EXTRACT(DOW FROM row_fechas_alt.fecha) INTO dia;
        IF(dia = 6)THEN
            IF(in_dias < 0)THEN
                dias_extras_alt := dias_extras_alt - 2;
            ELSE
                dias_extras_alt := dias_extras_alt + 2;
            END IF;
        /**
         * Las siguientes 7 lineas se descomentan si se desea utilizar una tabla que mantenga los feriados
         * con fecha absoluta(25 de Diciembre es 25/12/2009(Formato SQL, EURUPEO))
         */

        --ELSE IF(row_fechas_alt.fecha IN (SELECT fecha FROM utilidades.feriados WHERE fecha = row_fechas_alt.fecha AND EXTRACT(dow FROM fecha) NOT IN (0,6)))THEN
        --  IF(in_dias < 0)THEN
        --      dias_extras_alt := dias_extras_alt - 1;
        --  ELSE
        --      dias_extras_alt := dias_extras_alt + 1;
        --  END IF;
        --END IF;
        END IF;
    END LOOP;

    retorno := fecha_limite + ((in_dias + dias_extras_alt)::varchar || ' days')::interval;
    RETURN retorno;
    END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

Back Top

Responses to “Día hábil anterior/próximo en PostgreSQL”

  1. No comments yet.
  1. Próximo día hábil en PostgreSQL | Manuel | empty (,December 7, 2009)

    [...] Próximo día hábil en PostgreSQL base de datos, by admin. Funcion obsoleta y con errores. Favor ver versión 2 en: http://manuel.radiohead.cl/2009/dia-habil-anterior-proximo-en-postgresql/ [...]

Leave a Reply

Back Top