Eu debati se deveria postar isso porque depende de como as datas são armazenadas no nível binário no SQL Server e, portanto, é uma solução muito frágil. Para qualquer coisa que não seja uma conversão única, eu usaria algo como a resposta que @Solution Evangelist postou. Ainda assim, você pode achar isso interessante de uma maneira acadêmica, então vou postar de qualquer maneira.
Fazendo uso do fato de que a precisão de
DateTime2
corresponde à duração do tick no .NET e que ambos são baseados em datas de início de 01-01-0001 00:00:00.0000000
, você pode converter o DateTime
para DateTime2
, e depois converta-o para binary(9)
:0x07F06C999F3CB7340B
As informações de data e hora são armazenadas em RTL, portanto, invertendo, obteremos
0x0B34B73C9F996CF007
. Os primeiros três bytes armazenam o número de dias desde
01-01-0001
e os próximos 5 bytes armazenam os 100ns de tiques desde a meia-noite daquele dia, então podemos pegar o número de dias, multiplicar pelos tiques em um dia e somar os tiques que representam o tempo decorrido para o dia. Executando o seguinte código:
set @date = getdate()
set @ticksPerDay = 864000000000
declare @date2 datetime2 = @date
declare @dateBinary binary(9) = cast(reverse(cast(@date2 as binary(9))) as binary(9))
declare @days bigint = cast(substring(@dateBinary, 1, 3) as bigint)
declare @time bigint = cast(substring(@dateBinary, 4, 5) as bigint)
select @date as [DateTime], @date2 as [DateTime2], @days * @ticksPerDay + @time as [Ticks]
retorna os seguintes resultados:
DateTime DateTime2 Ticks
----------------------- ---------------------- --------------------
2011-09-12 07:20:32.587 2011-09-12 07:20:32.58 634514088325870000
Pegando o número retornado de Ticks e convertendo de volta para um DateTime em .NET:
DateTime dt = new DateTime(634514088325870000);
dt.ToString("yyyy-MM-dd HH:mm:ss.fffffff").Dump();
Retorna a data do sql server:
2011-09-12 07:20:32.5870000