Converter datetime2 em datetime

      Nenhum comentário em Converter datetime2 em datetime

Vou tentar explicar de forma bem grosseira o cenário.

Até a versão do SQL Server 2005, havia apenas uma forma de trabalhar com dados do tipo de data: “datetime“. Sempre você armazenava data e hora no mesmo campo.

Com a evolução do SQL Server e com as novas necessidades de mercado, surgiram “date” e “datetime2” (tudo bem, inúmeras outras inovações também surgiram dentro do software). “Date“, como é óbvio, armazena apenas data, e não mais horas junto. Realmente é interessante, porque nem sempre é necessário armazenar a informação das horas. E “datetime2“? Oras, foi necessário aumentar a precisão de horário para nanosegundos e aproveitaram para ampliar os limites de datas.

Vou exemplificar.

Range de Limites:

  • DateTime2 trabalha no range: 01/01/0001 até 31/12/9999 (com precisão de 100 nano segundos)
  • DateTime trabalha no range: 01/01/1753 até 31/12/9999 (com precisão de 0.00333 segundos)
  • Date trabalha no range: 01/01/0001 até 31/12/9999 (e NÃO trabalha com tempo – horas, minutos e segundos).

 

O datatype “DateTime” foi mantido mesmo com as novas versões do sql server, justamente para garantir a compatibilidade nas migrações.

E a questão do armazenamento? Como fica?

No armazenamento:

  • “DateTime2” ocupa de 6 a 8 bytes.
  • “DateTime” ocupa 8 bytes.
  • “Date” ocupa apenas 3 bytes.

Se você precisa, por exemplo, armazenar a data de nascimento, porque precisa usar datetime ou datetime2?

Pode parecer um ganho insignificativo, mas, numa tabela de centenas de milhares de clientes, pode fazer alguma diferença. Em alguns casos, dependendo do tamanho da organização, a diferença pode ser enorme.

Não havendo necessidade de tamanha precisão ou se for parte da regra de negócio trabalhar com um range de datas que cabem dentro de um campo do tipo date ou datetime, minha recomendação é que não utilize o datetime2.

No software, faça a consistência dos dados no input! Não deixe a validação de lado.

 

Vamos imaginar que há uma necessidade de uma conversão “forçada”, onde deve ser necessário MIGRAR seus dados e que tenha sido feito um acordo formal onde as datas fora do range devam ser nulas, e sendo assim, converter um campo datetime2 para datetime ou, de datetime2 para apenas date, é possível criar uma função para a conversão.

Sim, uma função escalar, de usuário. Até o momento não é possível converter um datetime2 para datetime com as funções de sistema: cast e convert, porque são datatypes incompatíveis para esta conversão.

 

** ATENÇÃO: Em nosso papel dentro da tecnologia da informação, JAMAIS devemos tentar mascarar informações por mais erradas que elas possam parecer! Se houve um erro de digitação, se a aplicação não fez sua validação, NÃO devemos corrigir por conta própria a informação, a não ser se seja firmado um acordo formal e oficial desta operação, atendendo a regra de negócio! Tenha uma autorização da operação por escrito e assinado. Em projetos de ETL para fins de abastecimento de dados para um datawarehouse, a informação deve ser levada na íntegra, sem hard code, sem alterações de dados. Um datawarehouse NÃO deve ser usado para corrigir problemas em softwares.

 

No caso de problemas identificados como erro de digitação, tente fazer com que o responsável pela informação atualize os dados pelo software. Depois, implemente a correção via software. Quando tudo estiver correto, atualize o tipo de dado de sua tabela. Contribua com a qualidade dos dados.

 

Segue a função escalar que trata a conversão de datetime2 para datetime. Faça sua adaptação se necessário, mas lembre-se da observação acima: NÃO tente corrigir erros de digitação na origem de dados, como é feito neste exemplo (se fora do range, retorno nulo).

 

CREATE FUNCTION [dbo].[converte_datetime2] 
(
      @data DATETIME2
)
RETURNS datetime
AS
BEGIN
      DECLARE @Result datetime

      select @result =  case 
                                         when (year(@data) < 1754 or year(@data) > 9998)
                                         then null 
                                         when (month(@data) < 1 or month(@data) > 12)
                                         then null
                                         when (day(@data) < 1 or day(@data) > 31)
                                         then null
                                         else CAST(
                                               convert(varchar(4), month(@data)) + '/' +
                                               convert(varchar(4), day(@data)) + '/' +
                                               convert(varchar(4), year(@data) )
                                               as datetime)
                                   end
      return @result
END

 

Simples, e inclusive exagerada a forma como é tratada a conversão. Se houver alguma informação fora do range, note que o retorno é nulo. Se ao invés de nulo preferir algum valor especifico (um default), só acertar no script.

Ainda persiste alguma dúvida ou tem alguma sugestão diferente para tratar isto? Já passou por algo assim algum dia? Nunca se sabe o dia de amanhã. Fique a vontade para deixar seu comentário. Até a próxima!

 

Deixe uma resposta