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.
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:
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.
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:
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#:
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
Bahhh show! Obrigado Giacomelli!