Convertir .NET Tiques à SQL Server DateTime
-
22-09-2019 - |
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.
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.