Pegando o ultimo dia do mês de uma determinada data

Vez ou outra em psql precisamos de uma função que retorne o primeiro e o último dia do mês de uma determinada data. Isso parece simples, afinal sabemos que o inicio do mês será sempre será o dia ’01’, muito diferente do último dia do mês que pode variar conforme o mês e o ano. Na função abaixo criamos uma função que retornará o ultimo dia do mês de uma determinada data e retorne em formato do tipo timestamp. Essa função trabalhará em conjunto com a função também explicada em outro artigo chamada de GET_FIRST_DAY_OF_MONTH.

Se já teve uma necessidade assim, a função psql abaixo irá resolver seu problema:

create or alter function GET_LAST_DAY_OF_MONTH (
    P_DATE_REF timestamp)
returns timestamp
as
declare variable LCALC_DATE timestamp;
declare variable LCALC_NEXT_MONTH timestamp;
begin
  -- Calcula o próximo mês
  LCALC_NEXT_MONTH=dateadd(month, 1, :P_DATE_REF);
  -- Pega o inicio do próximo mes
  select cast(:LCALC_NEXT_MONTH as date) - extract(day from cast(:LCALC_NEXT_MONTH as date)) + 1
  from RDB$DATABASE
  into :lcalc_date;

  -- agora subtrai 1 segundo
  lcalc_date=dateadd(second, -1, :lcalc_date);
  return :lcalc_date;
end

Modo de usar

select
  GET_LAST_DAY_OF_MONTH(current_timestamp) as primeiro_dia_do_mes 
from RDB$DATABASE

Imagine pesquisar um período de fechamento do mês atual:

select * from tabela a
where 
  a.dt_lancamento between 
    GET_FIRST_DAY_OF_MONTH(current_timestamp)
      and 
    GET_LAST_DAY_OF_MONTH(current_timestamp) 

Conclusion

Funções para pegar o inicio e o fim do mês podem parecer bobagem no inicio, mas confie em mim, programando com psql você terá momentos em que precisará dessas datas para processar algo importante que deva ser contado a partir do inicio do mês, até o término dele ou ambos. Por exemplo, considere a possibilidade de consultar lançamentos de um período mensal, onde irá do dia 01 até o final do mês incluindo o sufixo de hora 23:59:59 para não perder os movimentos desde ultimo dia. O fato da função retornar um timestamp vai te ajudar inclusive com o indice que não precisará dum cast de timestamp para date.