Преобразование .NET Ticks в SQL Server DateTime

Я TimeSpan (из .NET) в своем db как BIGINT в SQL Server (сохраняя свойство Ticks). Я хочу знать, как преобразовать это значение BIGINT значение DATETIME в SQL Server (а не в .NET). Есть идеи?

ура

РЕДАКТИРОВАТЬ:

Я использую NHibernate для сопоставления свойства TimeSpan меня есть, и оно сохраняет свойство Ticks. Я использую его для относительных часов (или минут) контроля над какой-то датой.

Внутренне в системе все в порядке, это преобразование не требуется. Однако при выполнении случайных запросов в SQL Server трудно понять сохраненную форму TimeSpan . Таким образом, функция, в которой я Ticks значение Ticks и возвращает DateTime будет давать количество в часах, минутах и ​​секундах, которое представляет собой TimeSpan .

Я не уверен, насколько точно это будет с секундами, но вы можете попробовать что-то вроде:

 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) 

Фактически другой способ, который будет работать в SQL 2005, – отметить, что количество тиков от 0001-01-01 до 1900-01-01 составляет 599266080000000000. С этим вы могли бы сделать:

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

Я действительно не знаю SQL Server, но сегодня у моего коллеги была такая же проблема, и я думаю, что нашел такое решение:

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

где 599266080000000000 – значение тиков на 01/01/1900 00:00:00.

Вы можете использовать эту функцию, взятую из блога Павла Гатилова, чтобы преобразовать 64-битное целое число в значение datetime с точностью до миллисекунды в локальное время сервера:

 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 

Альтернативный код, подходящий для встроенного использования:

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

TimeSpan не является датой, и сохранение ее как таковой может вызвать путаницу в будущем.

Есть ли причина, по которой вы не можете просто сохранить тики в целочисленное поле и не изменить его значение?

Получите значение TimeSpan.TicksPerSecond в .NET (просто запишите его).

Затем в вашем SQL вы можете разделить количество тиков на это число, чтобы указать количество секунд.

Затем вы можете разделить это на 60, чтобы получить минуты и т. Д.

Вы должны иметь возможность использовать функцию CAST, встроенную в SQL Server.

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

вы получаете 2010-02-02 00: 00: 00.000

Я понял это самостоятельно:

288 000 000 000 тиков составляет 8 часов, поэтому следующий SELECT возвращает фиктивную дату с указанием количества часов …

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

Благодаря всем усилиям.

Давайте будем гением компьютера.