Campo para manipular o tipo de dados INTERVAL

Bom dia!
No banco de dados, tenho um campo do tipo INTERVAL, ele receber qualquer valor em hora, ex:01:30:10, 32:20:10…
No Latromi, qual campo devo utilizar para ele? Pensei em usar DateTimePicker, com valor Hora, mas ele aceita ate 23 (o que não está errado).
Então fiquei com essa dúvida, que campo utilizar.Daniel 2 Daniel

Bom dia @Deia!

Não tempos um campo específico para manipular o tipo de dados INTERVAL justamente por ele ultrapassar as 24h ou até mesmo chegar a dias, meses e etc.

No entanto, existem algumas abordagens que podem ser utilizadas. Vou apresentá-las a seguir usando o banco de dados PostgreSQL como exemplo.

NumericTextBox

Usar um campo do tipo NumericTextBox é a solução mais simples e precisa para expressar um intervalo de tempo.

A técnica consiste em obter o total de segundos do intervalo, e a partir deste valor, converter para uma fração de minutos ou horas.

Para obter o total de segundos de um valor INTERVAL no PostgreSQL, é preciso extrair o campo epoch usando a função EXTRACT:

SELECT 
   EXTRACT(epoch from '32:20:10'::interval) AS segundos,
   EXTRACT(epoch from '32:20:10'::interval) / 60 AS minutos,
   EXTRACT(epoch from '32:20:10'::interval) / 60 / 60 AS horas

O resultado do comando SQL acima é este:

segundos minutos horas
116410 1940.16666666667 32.3361111111111

Usando campos do tipo NumericTextBox com 2 casas decimais para apresentar estes valores, temos este resultado:

image

Para fazer o processo inverso, ou seja, converter os valores da tela em INTERVAL novamente, basta formatar o valor usando o campo de tempo correspondente:

SELECT 
   Format('%s seconds', {?INPUT segundos})::interval AS intervalo_segundos,
   Format('%s minutes', {?INPUT minutos})::interval AS intervalo_minutos,
   Format('%s hours', {?INPUT horas})::interval AS intervalo_horas

NumericTextBox + ComboBox

Uma maneira de tornar a abordagem anterior mais dinâmica, é adicionar um campo do tipo ComboBox para o usuário selecionar o tipo de tempo desejado.

image

Cada opção de intervalo possui um valor que é a potência pelo qual os segundos precisam ser multiplicados ou divididos para se obter minutos ou segundos:

image

Antes de preencher estes campos com os dados do banco, será necessário:

  • Descobrir a precisão do tempo (segundos, minutos ou horas).
  • Converter o campo INTERVAL para a precisão encontrada.

A conversão para preencher o campo ser feita por SQL ou C#.

Popular usando SQL

Abaixo o comando SQL usado para preencher os campos:

SELECT 
   -- Precisão do intervalo (segundos, minutos, horas)
   CASE 
      WHEN EXTRACT(epoch from '32:20:10'::interval) < 60 THEN 0
      WHEN EXTRACT(epoch from '32:20:10'::interval) / 60 < 60 THEN 1
      ELSE 2
   END AS intervalo,

   -- Valor convertido no intervalo encontrado
   EXTRACT(epoch from '32:20:10'::interval) / POW(60,
      (CASE -- repete o case when da coluna "intervalo"
         WHEN EXTRACT(epoch from '32:20:10'::interval) < 60 THEN 0
         WHEN EXTRACT(epoch from '32:20:10'::interval) / 60 < 60 THEN 1
         ELSE 2
      END)) AS tempo

O resultado do comando SQL é este. Veja que o intervalo encontrado foi 2 (horas):

intervalo tempo
2 32.3361111111111

Popular usando C#

Usando C#, seria necessário uma Record para carregar o valor INTERVAL, sem nenhuma conversão, e na ação Popular Campos e Variáveis, clicar no botão para adicionar uma expressão C#:

image

Abaixo o comando SQL da Record, cujo nome neste exemplo será rDados.

SELECT '32:20:10'::interval as intervalo

Expressão C# para popular o campo intervalo:

var t = (TimeSpan)GetRecord("rDados")["intervalo"];
return t.TotalHours > 0 ? 2 : t.TotalMinutes > 0 ? 1 : 0;

Expressão C# para popular o campo tempo:

var t = (TimeSpan)GetRecord("rDados")["intervalo"];
return t.TotalHours > 0 ? t.TotalHours: t.TotalMinutes > 0 ? t.TotalMinutes : t.TotalSeconds;

Recuperando o INTERVAL

Para converter o valor dos campos da tela em INTERVAL, basta multiplicar por 60 na potência de N, onde N é o intervalo selecionado pelo usuário:

SELECT 
    {?INPUT tempo} * POW(60, {?INPUT intervalo}) AS intervalo
2 curtidas

Bahhh show! Obrigado Giacomelli! :star_struck:

1 curtida