PL / SQL Выражение для получения разницы между часами - PullRequest
0 голосов
/ 04 августа 2020

У меня есть приложение в Apex, где пользователь выбирает время начала F1 события и время окончания F2, а результат должен отображаться в третьем текстовом поле F3.

Как я могу выполнить операцию вычитания F1 и F2 с помощью функции PL / SQL?

Например, 7:00 и 7:30, и результат будет 30 мин.

Время вводится как текст, поэтому я использую to_date для преобразования двух полей в дату.

Ответы [ 3 ]

0 голосов
/ 04 августа 2020

Как было сказано ранее в oracle, у нас нет предопределенных функций для определения разницы во времени, и нам нужно сделать это самостоятельно

Однако у меня есть альтернативы с моим опытом работы, которые отличаются только сроки читаемости по сравнению с уже имеющимся ответом

/*
   with fields having already in timestamp format
*/
WITH time_difference AS
 (SELECT timestamp'2020-08-04 07:00:00' start_dt
        ,timestamp'2020-08-04 07:30:00' end_dt
  FROM   dual)
SELECT EXTRACT(HOUR FROM(end_dt - start_dt)) hrs
      ,EXTRACT(MINUTE FROM(end_dt - start_dt)) mins
      ,EXTRACT(SECOND FROM(end_dt - start_dt)) secs
      ,end_dt - start_dt diff_interval
FROM   time_difference;
/*
  with fields having date, subtracting them results in a number,
  so we can case them to timestamps and do as above
*/
WITH field_in_dates AS
 (SELECT to_date('04.08.2020 07:00:00','dd.mm.yyyy hh24:mi:ss') start_dt
        ,to_date('04.08.2020 07:30:00','dd.mm.yyyy hh24:mi:ss')end_dt
  FROM   dual),
time_difference AS
 (SELECT to_timestamp(to_char(start_dt,'yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss') start_dt
        ,to_timestamp(to_char(end_dt,'yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss') end_dt
  FROM   field_in_dates)
SELECT EXTRACT(HOUR FROM(end_dt - start_dt)) hrs
      ,EXTRACT(MINUTE FROM(end_dt - start_dt)) mins
      ,EXTRACT(SECOND FROM(end_dt - start_dt)) secs
      ,end_dt - start_dt diff_interval
FROM   time_difference;
0 голосов
/ 04 августа 2020

Позвольте мне предложить небольшую альтернативу. Вместо того, чтобы преобразовывать входные строки в дату, преобразуйте их в метки времени. Метки времени, как и даты, можно вычитать напрямую. Однако вычитание дат приводит к значению с плавающей запятой, которое никогда не может быть идеально представлено в двоичном формате, поэтому 30 может оказаться как 29,99999 ...), где вычитание временных меток всегда приводит к точному интервалу. Итак (при условии, что форматы времени не включают секунды, просто «гггг-мм-дд чч24: ми»). См. Полный пример .

create or replace 
function event_duration (p_start_date varchar, p_end_date varchar)
  return varchar2
is
    v_time_diff interval day to second;
    v_time_seg  integer;
    v_result    varchar2(40) := ' ';    
begin
    v_time_diff := to_timestamp(p_end_date,'yyyy-mm-dd hh24:mi') 
                 - to_timestamp(p_start_date,'yyyy-mm-dd hh24:mi') ; 
    
    v_time_seg :=  extract(day from v_time_diff);         
    if v_time_seg > 0 
    then 
       v_result := to_char(v_time_seg, 'FM999') || ' days' || ' ';
    end if ; 
    
    v_time_seg :=  extract(hour from v_time_diff);         
    if v_time_seg > 0 
    then 
       v_result :=  v_result || to_char(v_time_seg, 'FM999') || ' hours' || ' ';
    end if ; 
    
    v_time_seg := extract(minute from v_time_diff);
    if v_time_seg  > 0 
    then 
       v_result := v_result || to_char(v_time_seg,'FM99' ) || ' minutes' ;
    end if ;  
   
   return trim(v_result) ;  
end event_duration; 
0 голосов
/ 04 августа 2020

В Oracle нет функции timediff, но вы можете легко вычислить разницу, применив обычные операции арифметики c.

Я использую этот пример, где я использую две входные переменные, которые вы должны заменить с вашими элементами APEX и используйте маску даты, которую хотите. В моем примере я использую YYYYMMDDHH24MISS.

Вместо этого вы можете преобразовать это в функцию и поместить элемент P3 как результат функции.

declare 
v_start_date varchar2(40) := ':P1_START_DATE';
v_end_date   varchar2(40) := ':P1_END_DATE';
v_result     number;
begin
   select ( to_date(':P1_END_DATE','yyyymmddhh24miss') - 
            to_date(':P1_START_DATE','yyyymmddhh24miss') ) * 24 * 60 
   into v_result from dual;
   dbms_output.put_line ( v_result );
end;
/
   from dual ;

С функцией

create or replace function my_date_diff ( p_end_date in varchar2 , p_start_date in varchar2 ) return number 
is 
 v_result number;
begin
  select ( to_date(p_end_date ,'yyyymmddhh24miss') - 
            to_date(p_star_date,'yyyymmddhh24miss') ) * 24 * 60 
   into v_result from dual;
  return v_result ;
end;

Не забудьте применить маску даты, соответствующую вашему ПУНКТУ в Apex

...