Convierta .NET Ticks a SQL Server DateTime

Estoy guardando un valor TimeSpan (desde .NET) en mi db como BIGINT en SQL Server (guardando la propiedad Ticks). Quiero saber cómo convertir este valor BIGINT a un valor DATETIME en SQL Server (no en .NET). ¿Algunas ideas?

Aclamaciones

EDITAR:

Estoy usando NHibernate para mapear una propiedad TimeSpan que tengo, y persiste la propiedad Ticks. Lo uso durante horas relativas (o minutos) control sobre alguna fecha.

Internamente en el sistema todo está bien, esta conversión no es necesaria. Sin embargo, al realizar consultas aleatorias en SQL Server, es difícil entender la forma persistente de un TimeSpan . Entonces, una función donde paso el valor de Ticks y se devuelve DateTime daría la cantidad en horas, minutos y segundos que ese TimeSpan representa.

No estoy seguro de cuán exacto será con los segundos, pero podrías intentar algo como:

 Declare @TickValue bigint Declare @Days float Set @TickValue = 634024345696365272 Select @Days = @TickValue * POWER(10.00000000000,-7) / 60 / 60 / 24 Select DATEADD(d, Cast(@Days As int), Cast('0001-01-01' As DATE)) + Cast( (@Days - FLOOR(@Days)) As DateTime) 

De hecho, otra forma de que funcionaría en SQL 2005 es notar que el número de tics de 0001-01-01 a 1900-01-01 es 599266080000000000. Con eso, podrías hacer:

 Declare @TickOf19000101 bigint Declare @TickValue bigint Declare @Minutes float Set @TickOf19000101 = 599266080000000000 Set @TickValue = DATEDIFF(mi, 0 ,CURRENT_TIMESTAMP) * Cast(60 As BigInt) * POWER(10.00000000000,7) + @TickOf19000101 Select @TickValue Select @Minutes = (@TickValue - @TickOf19000101) * POWER(10.00000000000,-7) / 60 Select @Minutes Select DATEADD(MI, @Minutes, '1900-01-01') 

Realmente no conozco SQL Server, pero hoy un colega mío tuvo el mismo problema y creo que encontré una solución como esta:

 CAST(([ticks] - 599266080000000000) / 10000000 / 24 / 60 / 60 AS datetime) 

donde 599266080000000000 es el valor de las marcas para 01/01/1900 00:00:00.

Puede usar esta función tomada del blog de Pavel Gatilov para convertir un entero de 64 bits a un valor de fecha y hora con una precisión de milisegundos en la hora local del servidor:

 CREATE FUNCTION NetFxUtcTicksToDateTime ( @Ticks bigint ) RETURNS datetime AS BEGIN -- First, we will convert the ticks into a datetime value with UTC time DECLARE @BaseDate datetime; SET @BaseDate = '01/01/1900'; DECLARE @NetFxTicksFromBaseDate bigint; SET @NetFxTicksFromBaseDate = @Ticks - 599266080000000000; -- The numeric constant is the number of .Net Ticks between the System.DateTime.MinValue (01/01/0001) and the SQL Server datetime base date (01/01/1900) DECLARE @DaysFromBaseDate int; SET @DaysFromBaseDate = @NetFxTicksFromBaseDate / 864000000000; -- The numeric constant is the number of .Net Ticks in a single day. DECLARE @TimeOfDayInTicks bigint; SET @TimeOfDayInTicks = @NetFxTicksFromBaseDate - @DaysFromBaseDate * 864000000000; DECLARE @TimeOfDayInMilliseconds int; SET @TimeOfDayInMilliseconds = @TimeOfDayInTicks / 10000; -- A Tick equals to 100 nanoseconds which is 0.0001 milliseconds DECLARE @UtcDate datetime; SET @UtcDate = DATEADD(ms, @TimeOfDayInMilliseconds, DATEADD(d, @DaysFromBaseDate, @BaseDate)); -- The @UtcDate is already useful. If you need the time in UTC, just return this value. -- Now, some magic to get the local time RETURN @UtcDate + GETDATE() - GETUTCDATE(); END GO 

Código alternativo adecuado para el uso en línea:

 DECLARE @Ticks bigint set @Ticks = 634899090000000000 select DATEADD(ms, ((@Ticks - 599266080000000000) - FLOOR((@Ticks - 599266080000000000) / 864000000000) * 864000000000) / 10000, DATEADD(d, (@Ticks - 599266080000000000) / 864000000000, '01/01/1900')) + GETDATE() - GETUTCDATE() 

Un TimeSpan no es una fecha, y guardarlo como tal puede causar confusión en el futuro.

¿Hay alguna razón por la que no puedas simplemente guardar los tics en un campo entero y no cambiar su significado?

Obtenga el valor de TimeSpan.TicksPerSecond en .NET (solo escríbalo).

Luego, en su SQL, puede dividir el conteo de ticks por ese número, para dar la cantidad de segundos.

Puede dividir esto entre 60 para obtener minutos, etc.

Debería poder usar la función CAST integrada en SQL Server.

 SELECT(CAST(CAST(CAST ('02/02/10' AS datetime) AS BIGINT) AS datetime)) 

obtienes 2010-02-02 00: 00: 00.000

Lo he descubierto por mi cuenta:

288,000,000,000 de ticks representan 8 horas, por lo que el SELECT siguiente devuelve una fecha ficticia con la cantidad de horas especificada …

 SELECT DATEADD(millisecond, 288000000000/10000, CAST('1900-01-01' AS DATETIME)) 

Gracias a todos los esfuerzos.