Кварц .Net - Значение BigInt DateTime - PullRequest
11 голосов
/ 19 ноября 2010

мы использовали sql server в качестве нашего постоянного хранилища данных для Quartz.net. Я хотел бы написать несколько запросов, глядя на значения времени. В частности - Qrtz_Fired_Triggers.Fired_Time, Qrtz_Triggers.Next_fire_time, Prev_fire_time.

За всю свою жизнь я не могу найти ничего, что говорит о том, что это за данные - тики, миллисекунды, микросекунды, наносекунды. Я догадался о нескольких вещах, но все они оказались неправы.

Лучший ответ будет включать в себя математику для преобразования большого int в дату и время и, возможно, даже ссылку (ссылки) на страницы / документацию, которые я должен был найти - объясняя значение данных в этих полях.

Если у вас есть конкретные инструкции по использованию библиотек Quartz .Net для просмотра этой информации, это было бы полезно, но у меня действительно есть две цели - понять значение сохраняемых данных даты и времени и сохранить их в T -SQL. Если я получу один, я могу разобраться с T-SQL или без него.

Ответы [ 3 ]

26 голосов
/ 13 марта 2013

На стороне SQL вы можете преобразовать времена Quartz.NET BIGINT в DateTime в UTC времени с помощью:

SELECT CAST(NEXT_FIRE_TIME/864000000000.0 - 693595.0 AS DATETIME) FROM QRTZ_TRIGGERS

Числа Объяснение

Значения, хранящиеся в столбце, являются числомтиков из .NET DateTime.MinValue по времени UTC.Есть 10000 тиков в миллисекунду.

864000000000.0 представляет количество тиков за один день.Вы можете проверить это с помощью

SELECT DATEDIFF(ms,'19000101','19000102')*10000.0

Теперь, если мы примем 13 марта 2013 года в полночь, .NET вернет 634987296000000000 в качестве числа тиков.

var ticks = new DateTime(2013, 3, 13).Ticks;

Чтобы получитьЧисло с плавающей запятой, где целые числа представляют дни, а десятичные числа представляют время, мы берем тики и делим их на количество тиков в день (в нашем примере это 734939.0)

SELECT 634987296000000000/(DATEDIFF(ms,'19000101','19000102')*10000.0)

Если мы получим путДата в SQL и преобразование в число с плавающей точкой, мы получаем другое число: 41344.0

SELECT CAST(CAST('March 13, 2013 0:00' AS DATETIME) AS FLOAT)

Итак, нам нужно сгенерировать коэффициент пересчета для дней .NET-к-SQL.Минимальная дата SQL - 1 января 1900 г., 0:00, поэтому поправочный коэффициент можно рассчитать, взяв число тиков за это время (599266080000000000) и разделив его на тики в день, получив нам 693595.0

SELECT 599266080000000000/(DATEDIFF(ms,'19000101','19000102')*10000.0)

Итак, чтобы вычислить DateTime для даты Quartz.NET:

  • возьмите значение в столбце
  • , деленное на количество тиков в день
  • вычесть поправочный коэффициент
  • преобразовать в DATETIME
SELECT CAST([Column]/864000000000.0 - 693595.0 AS DATETIME)
3 голосов
/ 20 ноября 2010

Значение, хранимое в базе данных, является значением DateTime.Ticks. Из MSDN:

Один тик представляет сто наносекунды или одна десятая миллионная часть второй. Есть 10000 тиков в миллисекунды.

Значение этого свойства представляет количество 100-наносекундных интервалов прошедшие с 12:00:00 полночь 1 января 0001 года, которая представляет DateTime.MinValue. Оно делает не включает количество тиков, которые относятся к високосным секундам.

1 голос
/ 24 ноября 2010

Итак, если я что-то упустил и не усложнил, я не смог заставить функции dateadd в Ms Sql Server 2008 обрабатывать такие большие значения, и я продолжал получать ошибки переполнения. Подход, который я использовал в Ms Sql Server, заключался в следующем: а) найти дату ближе к настоящему моменту, чем 0001.01.01 и ее значение в тиках б) использовать функцию, чтобы дать мне значение DateTime.

Примечания: * для моего приложения - секунды были достаточно хороши. * Я не проверял это подробно, но до сих пор он действовал довольно хорошо для меня.

Функция:

  CREATE FUNCTION [dbo].[net_ticks_to_date_time]
   (
      @net_ticks BIGINT
   )
   RETURNS DATETIME
   AS
   BEGIN

      DECLARE 
         @dt_2010_11_01 AS DATETIME = '2010-11-01'
      ,  @bi_ticks_for_2010_11_01 AS BIGINT = 634241664000000000
      ,  @bi_ticks_in_a_second AS BIGINT = 10000000

      RETURN
         (
            DATEADD(SECOND , ( ( @net_ticks - @bi_ticks_for_2010_11_01 ) / @bi_ticks_in_a_second ) , @dt_2010_11_01)
         );

   END
  GO

Вот как я пришел к количеству тиков на какой-то недавней дате:

DECLARE 
   @dt2_dot_net_min AS DATETIME2 = '01/01/0001'
   , @dt2_first_date AS DATETIME2
   , @dt2_next_date AS DATETIME2
   , @bi_seconds_since_0101001 BIGINT = 0


   SET @dt2_first_date = @dt2_dot_net_min;

   SET @dt2_next_date = DATEADD ( DAY, 1, @dt2_first_date )



WHILE ( @dt2_first_date < '11/01/2010' )
   BEGIN
      SELECT @bi_seconds_since_0101001 = DATEDIFF(SECOND, @dt2_first_date, @dt2_next_date ) + @bi_seconds_since_0101001

      PRINT 'seconds 01/01/0001 to ' + CONVERT ( VARCHAR, @dt2_next_date,  101) + ' = ' + CONVERT ( VARCHAR, CAST ( @bi_seconds_since_0101001 AS MONEY ), 1)

      SET @dt2_first_date = DATEADD ( DAY, 1, @dt2_first_date );
      SET @dt2_next_date = DATEADD ( DAY, 1, @dt2_first_date )      

   END
...