sql-server-2005 - ddmmyyyy - sql server datetime format
Convierta.NET Ticks a SQL Server DateTime (7)
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.
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.
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'')
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.
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()
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.
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?