Как преобразовать час DATEPART, который является военным временем для полуночи (00), в значение, которое я могу использовать, когда мне это нужно для расчета?

У меня есть этот код, который я пишу в хранимую процедуру:

declare @StartTime time
declare @EndTime time
declare @Temp_StartTime time

declare @temp_StartHour int
declare @temp_EndHour int
declare @temp_StartMinute int
declare @temp_EndMinute int

SET @StartTime='22:30:00'
SET @EndTime='00:52:00'
SET @Temp_StartTime=@StartTime

SET @temp_StartHour=DATEPART(HOUR, @StartTime)
SET @temp_EndHour=DATEPART(HOUR, @EndTime)
SET @temp_StartMinute=DATEPART(MI, @StartTime)
SET @temp_EndMinute=DATEPART(MI, @EndTime)

if(@temp_EndMinute>0)
    BEGIN
        SET @temp_EndHour=@temp_EndHour+1
    END

DECLARE @Temp_Table TABLE
(
  StartHour int,
  StartMinute int,
  EndHour int,
  EndMinute int,
  StartTime time,
  EndTime time
)

WHile((@temp_EndHour-@temp_StartHour>=1))
    BEGIN
        INSERT INTO @Temp_Table
        SELECT (DATEPART(HOUR, @Temp_StartTime)) AS StartHour,(DATEPART(MINUTE, @Temp_StartTime)) AS StartMinute,
        @temp_StartHour+1 AS EndHour, 
        0 AS EndMinute, @StartTime as StartTime, @EndTime as EndTime

        SET @temp_StartHour=@temp_StartHour+1
        SET @Temp_StartTime=DATEADD(HOUR,1,@Temp_StartTime)

        if(DATEPART(MI, @Temp_StartTime)!=0)
            BEGIN
                SET @Temp_StartTime=DATEADD(MI,-@temp_StartMinute,@Temp_StartTime)
            END
    END

SELECT * FROM @Temp_Table 

Это прекрасно работает, если вы используете любое значение времени, отличное от примера 00:52:00, который у меня есть. Например, если EndTime было 23:05, хранимая процедура работает отлично. Я провел некоторое исследование DATEPART, но не нашел ничего полезного в том, как заставить его правильно рассчитывать полночь по военному времени.

РЕДАКТИРОВАТЬ: Когда код работает правильно, он вычисляет время, за которое сколько часов между временем начала и окончания, и идея состоит в том, чтобы сохранять новые строки для каждого часа во временной таблице (в конечном итоге это будет сохранено в новую таблицу для отслеживания отключения по часам). Он работает, когда я запускаю его с 21:30 до 22:15. Я получаю две строки, отражающие период с 21:00 до 22:00 и с 22:00 до 23:00 (это та логика, которую я хочу). Но добавьте туда военную полночь, и я не получу никаких возвращенных строк, так как калькулятор не будет вычислять 00.

Я нашел примеры в своей базе данных, которые показывают время начала 22:00:0000 и время окончания 00:00:00.0000000, а затем наоборот. Таким образом, БУДЕТ вычисляться один из способов, где время начала равно 00, но если время начала равно 21:00:0000, а время окончания - 00:52:0000, то кубиков не будет. Я не возвращаю строки.


person Lynn    schedule 26.04.2012    source источник
comment
В каком смысле 00:52 всегда больше, чем 23:05? Если бы вы перешли на полночь, то не запустил бы ли этот код бесконечный цикл?   -  person mellamokb    schedule 26.04.2012
comment
Вы не сказали, что не так с кодом как есть. Обратите внимание, что одно большое различие между EndTime, равным 23:05, и EndTime, равным 00:52, заключается в том, что в последнем случае EndTime предшествует StartTime (в пределах одного дня).   -  person Jon Skeet    schedule 26.04.2012
comment
Прости за это. Когда код работает правильно, он вычисляет время в часах между временем начала и окончания, и идея состоит в том, чтобы сохранять новые строки для каждого часа во временной таблице (в конечном итоге это будет сохранено в новой таблице для отслеживания простоев по час). Он работает, когда я запускаю его с 21:30 до 22:15. Я получаю две строки, отражающие период с 21:00 до 22:00 и с 22:00 до 23:00 (это та логика, которую я хочу). Но добавьте туда военную полночь, и я не получу никаких возвращенных строк, так как калькулятор не будет вычислять 00.   -  person Lynn    schedule 26.04.2012
comment
Может случиться так, что EndTime раньше StartTime за один день, и я просто недостаточно понимаю условности военного времени. В одной записи, которую я нашел в своей таблице, были StartTime и EndTime, которые мне нужно было рассчитать: Начало: 00:00:00.0000000 Конец: 11:28:00.0000000, но вычисление все равно не удалось из-за нулей....   -  person Lynn    schedule 26.04.2012
comment
Можете ли вы объяснить на простом английском языке, что именно вы пытаетесь вычислить здесь (вместо того, чтобы сказать нам, что вычисление не удается из-за нулей)? Каков фактический расчет, который вы пытаетесь достичь? Я не могу отличить конечную цель от простого SELECT * FROM @temp_table, но я подозреваю, что логика, которую вы используете выше, намного сложнее, чем должна быть. Кроме того, как код должен знать (если время начала — 22:30, а время окончания — 00:52), что была пересечена только одна полуночная граница? Что, если 22:30 было в прошлый четверг?   -  person Aaron Bertrand    schedule 26.04.2012
comment
У меня нет возможности узнать, сколько полуночных границ было пересечено, но в этих случаях можно с уверенностью предположить, что это так. Это простои сервера, которые необходимо разбить из диапазона на строку за вставкой строки (в конечном итоге) по часам возникновения.   -  person Lynn    schedule 26.04.2012


Ответы (1)


Если я ничего не упустил, это то, что вы можете попробовать вместо своего цикла:

DECLARE
  @StartTime time,
  @EndTime   time;

SET @StartTime = '22:30:00';
SET @EndTime   = '00:52:00';

WITH timerange AS (
  SELECT
    StartTime = CAST(@StartTime AS datetime),
    EndTime   = DATEADD(
      DAY,
      CASE WHEN @StartTime > @EndTime THEN 1 ELSE 0 END,
      CAST(@EndTime AS datetime)
    )
),
hourly AS (
  SELECT
    n.number,
    t.StartTime,
    t.EndTime,
    HStart = DATEADD(HOUR, DATEDIFF(HOUR, 0, t.StartTime) + n.number    , 0),
    HEnd   = DATEADD(HOUR, DATEDIFF(HOUR, 0, t.StartTime) + n.number + 1, 0)
  FROM timerange t
    INNER JOIN master..spt_values n
      ON n.number BETWEEN 0 AND DATEDIFF(HOUR, t.StartTime, t.EndTime)
  WHERE n.type = 'P'
),
hourly2 AS (
  SELECT
    number,
    HStart = CASE WHEN StartTime > HStart THEN StartTime ELSE HStart END,
    HEnd   = CASE WHEN EndTime   < HEnd   THEN EndTime   ELSE HEnd   END
  FROM hourly
)
SELECT
  StartHour   = DATEPART(HOUR  , HStart),
  StartMinute = DATEPART(MINUTE, HStart),
  EndHour     = DATEPART(HOUR  , HEnd  ),
  EndMinute   = DATEPART(MINUTE, HEnd  ),
  StartTime   = CAST(HStart AS time),
  EndTime     = CAST(HEnd   AS time)
FROM hourly2
ORDER BY number
;

Полученный результат таков:

StartHour   StartMinute EndHour     EndMinute   StartTime        EndTime
----------- ----------- ----------- ----------- ---------------- ----------------
22          30          23          0           22:30:00.0000000 23:00:00.0000000
23          0           0           0           23:00:00.0000000 00:00:00.0000000
0           0           0           52          00:00:00.0000000 00:52:00.0000000
person Andriy M    schedule 27.04.2012