Question

Je l'enregistrement d'une TimeSpan (de .NET) valeur dans mon db comme BIGINT dans SQL Server (sauvegarde de la propriété Tiques). Je veux savoir comment convertir cette valeur BIGINT à une valeur DATETIME dans SQL Server (pas .NET). Toutes les idées?

Vive

EDIT:

J'utilise NHibernate pour mapper une propriété TimeSpan je, et il persiste la propriété Tiques. Je l'utilise pour le contrôle des heures relatives (ou minutes) sur une date.

interne dans le système tout va bien, cette conversion n'est pas nécessaire. Cependant, lors de l'exécution des requêtes aléatoires dans SQL Server, il est difficile de comprendre la forme d'un persisté TimeSpan. Ainsi, une fonction où je passe la valeur Ticks et un DateTime est retourné donnerait le montant en heures, minutes et secondes que TimeSpan représente.

Était-ce utile?

La solution

Je ne sais pas comment ce sera précis avec les secondes, mais vous pouvez essayer quelque chose comme:

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)

En fait, une autre façon qui fonctionnerait dans SQL 2005 est de noter que le nombre de tiques de 0001-01-01 à 1900-01-01 est 599266080000000000. Avec que vous pourriez faire:

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')

Autres conseils

Je ne sais pas vraiment SQL Server, mais aujourd'hui un de mes collègues a eu le même problème et je pense J'ai trouvé une solution comme ceci:

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

où 599266080000000000 est la valeur pour les tiques 01.01.1900 00:00:00.

Vous pouvez utiliser cette fonction prise sur le blog de Pavel Gatilov pour convertir un nombre entier de 64 bits à une valeur de date-heure avec une précision d'une milliseconde dans le serveur local time:

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

Code alternatif approprié pour une utilisation en ligne:

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()

A TimeSpan est pas une date, et l'enregistrer en tant que telle peut causer de la confusion à l'avenir.

Y at-il une raison que vous ne pouvez pas simplement enregistrer les tiques à un champ entier et ne pas changer le sens?

Obtenir la valeur de TimeSpan.TicksPerSecond dans .NET (juste écrire).

Ensuite, dans votre SQL, vous pouvez diviser le nombre de tics par ce nombre, pour donner le nombre de secondes.

Vous pouvez ensuite diviser par 60 pour obtenir des minutes, etc.

Vous devriez pouvoir utiliser le CAST fonction intégrée Serveur SQL.

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

vous obtenez 2010-02-02 00: 00: 00.000

Je l'ai pensé à elle sur mon propre:

288,000,000,000 tiques représente 8 heures, de sorte que le SELECT suivant retourne une date fictive avec le ammount d'heures spécifié ...

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

Merci à everyones efforts.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top