Função que retorna a diferença entre 2 dias e horas no SQL Server

Olá pessoal…

Hoje vou mostrar uma função desenvolvida em SQL Server, que retorna a diferença entre duas datas em Dias, Horas, Minutos e Segundos.

Eu estava procurando uma forma de trazer a diferença entre duas datas e horas no SQL Server para montar um relatório para um usuário, e achei no Stack Overflow uma função interessante divulgada pelo Pedro Lorentz.

A função consiste em receber por parâmetro uma data inicial e uma final, e dentro dela é feito uma tratativa e retornado no formato texto a diferença entre ambas as datas.

Abaixo o código completo da função.

--Criação de Função para Calcular Tempo, que recebe dois parâmetros, a Data Hora Antes e Data Hora Depois
CREATE FUNCTION dbo.fnCalculaTempo 
(
	@antes DATETIME,
	@depois DATETIME
)
RETURNS VARCHAR(20)
AS
BEGIN
	
	--Declara variável temporária
    DECLARE @temp DATETIME;

	--Se o Antes for maior que o Depois, altera as variáveis
    IF (@antes > @depois)
    BEGIN
        SET @temp = @antes;
        SET @antes = @depois;
        SET @depois = @temp;
    END

	--Agora monta a expressão de retorna, se tiver temporária, quer dizer que o valor é negativo (Antes é maior que Depois), seguido por número de dias, horas, minutos  segundos
    RETURN  CASE WHEN @temp IS NULL THEN '' ELSE '-' END
            + CASE WHEN DATEDIFF(DAY, @antes, @depois) <> 0 THEN CONVERT(VARCHAR, DATEDIFF(DAY, @antes, @depois)) + 'd ' ELSE '' END
            + RIGHT('00' + CONVERT(VARCHAR, DATEDIFF(HOUR,   @antes, @depois) % 24), 2) + ':'
            + RIGHT('00' + CONVERT(VARCHAR, DATEDIFF(MINUTE, @antes, @depois) % 60), 2) + ':'
            + RIGHT('00' + CONVERT(VARCHAR, DATEDIFF(SECOND, @antes, @depois) % 60), 2);
END
GO

Após criar a função, basta chamar ela diretamente do seu SELECT, por exemplo, abaixo eu mostro 5 exemplos, com diferenças entre Data, hora, minutos, segundos e um com tudo:

SELECT 
	dbo.fnCalculaTempo(CONVERT(DATETIME, '20180513 08:00:00'), CONVERT(DATETIME, '20180520 08:00:00')) AS EXEMPLO_COM_DIAS,
	dbo.fnCalculaTempo(CONVERT(DATETIME, '20180520 08:00:00'), CONVERT(DATETIME, '20180520 10:00:00')) AS EXEMPLO_COM_HORAS,
	dbo.fnCalculaTempo(CONVERT(DATETIME, '20180520 08:30:00'), CONVERT(DATETIME, '20180520 08:45:00')) AS EXEMPLO_COM_MINUTOS,
	dbo.fnCalculaTempo(CONVERT(DATETIME, '20180520 08:00:19'), CONVERT(DATETIME, '20180520 08:00:49')) AS EXEMPLO_COM_SEGUNDOS,
	dbo.fnCalculaTempo(CONVERT(DATETIME, '20180513 08:30:19'), CONVERT(DATETIME, '20180520 10:45:49')) AS EXEMPLO_GERAL

Abaixo o print exemplificando o uso.

Exemplo de utilização da função

Referências:
pt.stackoverflow.com

Bom pessoal, por hoje é só.
Abraços e até a próxima.

Dan (Daniel Atilio)
Especialista em Engenharia de Software pela FIB. Entusiasta de soluções Open Source. E blogueiro nas horas vagas.

4 Responses

  1. Renan disse:

    Legal o exemplo porém se você utilizar uma data com uma diferença menor q um minuto ele retorna um minuto de diferença.
    Exemplo ‘2020-04-01 08:42:42.400’ e ‘2020-04-01 08:43:00.680’ existe uma diferença de 18 segundos e ela retorna 01:18
    Vlw

  2. Edson Novaes disse:

    Gostei do exemplo e se no caso for utilizar duas tabelas C5_EMISSÃO COM A F2_EMISSÃO como ficaria o exemplo ?

    • Obrigado pelo feedback Edson.

      Basicamente é necessário:
      1. Fazer o join entre a SC5 e SF2 com os campos chave
      2. Para não ficar lento, filtramos um pouco no Where, para trazer somente pedidos de setembro
      3. Ai no select, você aciona a função, e nos parâmetros passa a comparação entre C5_EMISSAO e F2_EMISSAO

      Preparei um exemplo aqui rapidinho, mas não consegui testar, porém a lógica esta prontinha:

      SELECT
          C5_NUM,
          C5_EMISSAO,
          F2_DOC,
          F2_EMISSAO,
          dbo.fnCalculaTempo(CONVERT(DATETIME, C5_EMISSAO + ' 00:00:00'), CONVERT(DATETIME, F2_EMISSAO + ' 00:00:00')) AS EXEMPLO
      FROM
          SC5010 SC5
          INNER JOIN SF2010 SF2 ON (
              F2_FILIAL = C5_FILIAL
              AND F2_DOC = C5_NOTA
              AND F2_SERIE = C5_SERIE
              AND F2_CLIENTE = C5_CLIENTE
              AND F2_LOJA = C5_LOJACLI
              AND SF2.D_E_L_E_T_ = ' '
          )
      WHERE
          C5_TIPO NOT IN ('B', 'D')
          AND C5_EMISSAO >= '20220901'
          AND C5_EMISSAO <= '20220918'
          AND SC5.D_E_L_E_T_ = ' '
      

      Um grande abraço.

Deixe uma resposta para Dan_Atilio Cancelar resposta