Como converter e formatar a exibição de horas decimais com SQL Server - parte 1
Autor: Vladimir Rech | Publicado: 2015-08-07T11:28:00-03:00





Esta publicação demonstra como converter números decimais usados para armazenar duração de tempo
 para a representação no formato de horas e minutos usando as funções do SQL Server 2008.
O objetivo é permitir representar números armazenados no formato decimal no banco de dados
 para facilitar o cálculo usando-se o formato padrão para horas e minutos, HH:MM, assim, por
 exemplo, 1,5 que refere-se à duração de uma hora e meia poderá ser representado como 01:30.
Como a proposta deste blog é manter as coisas simples e principalmente, atender a um público que
 está iniciando na programação, não serão considerados nos cálculos a duração em segundos e
 centésimos para que os cálculos fiquem simples. A versão mínima do SQL Server para poder executar
 este exemplo é a 2008 R2 sendo que é possível usar a sua versão gratuita (SQL EXPRESS EDITION).

Nesta primeira parte serão demonstrados os passos necessários para realizar as conversões de 
 base numérica. Na segunda, será dado o exemplo de uma função definida pelo usuário (UDF)
 no banco SQL Server para ser usada com as consultas.
Os códigos que estão demonstrados funcionam e foram testados apenas para o banco de dados
 SQL Server. Cada gerenciador de banco de dados possui uma maneira diferente para tratamento de
 armazenamento em variáveis e criação de funções do usuário.

Uma questão de base
É muito comum nas tarefas dos programadores ter de fazer cálculos com horas em algum momento. 
Pode ser para cálculo de valores em moeda baseado na quantidade do tempo trabalhado ou estimativas 
de custos baseados em horas, não importa. O que todos os cálculos envolvendo tempo corrido terão 
em comum é o fato de que as horas precisarão ser convertidas da base sexagimal para a decimal para
que os cálculos sejam feitos.
É mais comum que todas as horas sejam representadas na base sexagimal. Os múltiplos e submúltiplos são obtidos
 multiplicando ou dividindo por sessenta. Assim, uma hora é igual a sessenta minutos e cada minuto
 corresponde à sessenta segundos. Se é necessário calcular-se o número total de minutos de uma 
 hora, basta multiplicar o número por sessenta.
Porém para os cálculos de base financeira não é possível usar números com base sessenta diretamente.
 Se for necessário calcular o valor final de um serviço que durou, por exemplo, 01h30m, este número
 precisa ser convertido para a base decimal obtendo-se o valor 1,5 que pode então ser multiplicado
 pelo valor unitário.
Conversão de base sexagimal para base decimal
Esta conversão consiste em transformar o tempo representado no formato tradicional HH:MM para um
 número decimal para que possa ser armazenado e se façam cálculos.
Tomando o exemplo de 01:30 de duração deve-se armazenar cada parte do tempo em uma variável
 inteira em um primeiro passo, assim teremos uma variável inteira para hora e outra para os minutos, considerando
 o uso da linguagem SQL:

 declare @horas as decimal(6, 2) = 1;
 declare @minutos as decimal(6, 2) = 30;


 Atenção
 
  
 Um ponto importante que deve ser observado se ao desenvolver o exemplo se estiver usando
 o SQL Server é que as variáveis precisam ser declaradas do tipo DECIMAL com pelo menos duas
 casas após o ponto. O motivo disto é que se não for feito desta forma, a conversão não será
 feita corretamente.
 
 

Para se ter o número completo na base decimal deve se dividir os minutos por sessenta (60) e 
 somar o valor encontrado com as horas, assim, obtendo-se a duração final em base decimal.
 Novamente, se for fazer este cálculo com a linguagem SQL teremos este código:

 declare @minutos_sexagimais as decimal(6,2) = @minutos / 60;
 declare @tempo as decimal(6,2) = @horas + @minutos_sexagimais;

Conversão de base decimal para base sexagimal
Esta tarefa consiste em obter o valor que está armazenado em base decimal e poder converter
 para a sua representação no formato sexagimal (HH:MM). Para fazer isto é necessário que alguns passos
 sejam seguidos, o primeiro é armazenar apenas o valor correspondente às horas Isto é feito
 lendo o valor do tempo e atribuindo para uma variável do tipo inteiro. O resultado é que a parte
 decimal será desprezada:

declare @h as int = 1.50;

O segundo passo é obter os minutos convertidos para a base sexagimal. Isto envolve dois passos:

 Multiplicar o valor total do tempo por sessenta para se obter o valor total em minutos.
 Armazenar em uma variável do tipo inteiro o resto da divisão do valor do tempo em minutos
  por sessenta usando o operador de resto de divisão (módulo)
O exemplo abaixo demonstra como isto pode ser feito.

declare @minutos as int = 1.50 * 60 % 60; -- resultado: 30

O operador de módulo no SQL Server é o sinal de percentagem "%" seguido do divisor.
Com os passos expostos até aqui já é possível considerar como fazer para se obter os valores.
   Falta agora fazer as formatações corretas e tornar tudo isto utilizável facilmente através da
   definição de uma UDF. Isto será tratado no próximo post. Até lá!