Last active
June 27, 2017 18:46
-
-
Save vjnrv/2302190 to your computer and use it in GitHub Desktop.
Procedure para calcular data da Páscoa (PostgreSQL)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Retorna a data da Pascoa | |
-- @author Pedro Junior | |
-- @param ANO integer | |
-- @return Date | |
CREATE OR REPLACE FUNCTION getDataPascoa (ANO numeric(4) DEFAULT date_part('year', NOW())) | |
RETURNS DATE AS $$ | |
DECLARE | |
DIA numeric(2); -- Dia do Natal | |
MES numeric(2); -- Mês do Natal | |
X numeric(2); -- Valor de X de acordo com a faixa de anos | |
Y numeric(2); -- Valor de Y de acordo com a faixa de anos | |
aM numeric(2); -- Valor para MOD de A | |
bM numeric(2); -- Valor para MOD de B | |
cM numeric(2); -- Valor para MOD de C | |
dM numeric(2); -- Valor para MOD de D | |
A numeric(2); -- Ano MOD aM | |
B numeric(2); -- Ano MOD bM | |
C numeric(2); -- Ano MOD cM | |
D numeric(2); -- (aM * A + X) MOD dM | |
E numeric(2); -- (2 * B + bM * C + 6 * D + Y) MOD cM | |
DeE numeric(2); -- (D + E) | |
DATA date; -- Data da Pascoa Calculada | |
BEGIN | |
X = | |
CASE | |
WHEN ANO BETWEEN 1582 AND 1699 THEN 22 | |
WHEN ANO BETWEEN 1700 AND 1799 THEN 23 | |
WHEN ANO BETWEEN 1800 AND 2199 THEN 24 | |
WHEN ANO BETWEEN 2200 AND 2299 THEN 25 | |
END; | |
Y = | |
CASE | |
WHEN ANO BETWEEN 1582 AND 1699 THEN 2 | |
WHEN ANO BETWEEN 1700 AND 1799 THEN 3 | |
WHEN ANO BETWEEN 1800 AND 1899 THEN 4 | |
WHEN ANO BETWEEN 1900 AND 2099 THEN 5 | |
WHEN ANO BETWEEN 2100 AND 2199 THEN 6 | |
WHEN ANO BETWEEN 2200 AND 2299 THEN 7 | |
END; | |
aM = 19; | |
bM = 4; | |
cM = 7; | |
dM = 30; | |
A = mod(ANO, aM); | |
B = mod(ANO, bM); | |
C = mod(ANO, cM); | |
D = mod((aM * A + X), dM); | |
E = mod((2 * B + bM * C + 6 * D + Y), cM); | |
DeE = D + E; | |
IF (DeE > 9) THEN | |
DIA = DeE - 9; | |
MES = 4; | |
-- Casos que só ocorrem duas vezes por século: | |
-- Se o Dia for 26 então corrige para uma semana antes | |
IF (DIA = 26) THEN | |
DIA = DIA - cM; | |
END IF; | |
-- Se o Dia for 25 e D for 28 e A > 10 então corrige o dia pra 18 | |
IF (DIA = 25 AND D = 28 AND A > 10) THEN | |
DIA = 18; | |
END IF; | |
ELSE | |
DIA = DeE + 22; | |
MES = 3; | |
END IF; | |
DATA = to_date(ANO || '-' || MES || '-' || DIA, 'YYYY-MM-DD'); | |
RETURN DATA; | |
END | |
$$ LANGUAGE 'PLPGSQL'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment