Domanda

I have this code here:

create or replace FUNCTION calc_length(
    START_TIME IN number, FINISH_TIME IN number)
RETURN NUMBER IS
BEGIN
   DECLARE 
    lhs_start number(2):= LEFT(START_TIME,2);
    lhs_finish number(2):=LEFT(FINISH_TIME,2);
    rhs_start number(2):=RIGHT(START_TIME,2);
    rhs_finish number(2):=RIGHT(FINISH_TIME,2);
    RETURN lhs_finish-lhs_start||'hours'||
           rhs_finish-rhs_start||'minutes'||;
END;​

I am trying to split the numbers given in the function and take the left hand side (lhs) 2 numbers and the right hand side 2 numbers. The format of the passed numbers from the function is always a 4 digit number.

e.g. "1245"

Can you give me hand here?

È stato utile?

Soluzione

Fast and dirty hack:

create or replace FUNCTION calc_length(START_TIME number,
                                       FINISH_TIME number)
RETURN VARCHAR2 IS
    result varchar2(30);
    lhs_start number(2) := FLOOR(START_TIME / 100);
    lhs_finish number(2) := FLOOR(FINISH_TIME / 100);
    rhs_start number(2) := (START_TIME / 100 - FLOOR(START_TIME / 100)) * 100;
    rhs_finish number(2) := (FINISH_TIME / 100 - FLOOR(FINISH_TIME / 100)) * 100;

BEGIN    
    if (rhs_finish - rhs_start) > 0 then
      result := to_char(lhs_finish - lhs_start) || ' hours ' ||
                to_char(rhs_finish - rhs_start) || ' minutes';
    else
      result := to_char(lhs_finish - lhs_start - 1) || ' hours ' ||
                to_char(rhs_finish - rhs_start + 60) || ' minutes';
    end if;
    return result;
END calc_length;

NOTE: I updated the code to handle negative minute intervals, but I have to warn that the whole approach is totally wrong. To calculate time intervals it is better to use appropriate datatypes (datetime or interval).

Altri suggerimenti

Convert the input format to Oracle date data type and only then do the math:

create or replace function calc_length(
  start_time in number,
  finish_time in number
) return varchar2 is
  v_start_hours constant pls_integer :=
    floor(start_time / 100);
  v_start_minutes constant pls_integer :=
    start_time - (v_start_hours * 100);

  v_finish_hours constant pls_integer :=
    floor(finish_time / 100);
  v_finish_minutes constant pls_integer :=
    finish_time - (v_finish_hours * 100);

  v_start_time constant date :=
    to_date(v_start_hours, 'HH24') + (v_start_minutes / 1440);
  v_finish_time constant date :=
    to_date(v_finish_hours, 'HH24') + (v_finish_minutes / 1440);

  v_len_hours constant pls_integer :=
    extract(hour from (v_finish_time - v_start_time) day to second);
  v_len_minutes constant pls_integer :=
    extract(minute from (v_finish_time - v_start_time) day to second); 
begin
  return v_len_hours || ':' || v_len_minutes;
end;
/
show errors

col start_ for 99999
col finish for 99999
col length for a10

with data_ as (
  select 0000 as start_, 0127 finish from dual union
  select 0800,           1000        from dual union
  select 1000,           1000        from dual union
  select 1000,           1100        from dual union
  select 1000,           1145        from dual union
  select 2345,           0115        from dual
)
select start_, finish, calc_length(start_, finish) as length from data_;

Results:

START_ FINISH LENGTH
------ ------ ----------
     0    127 1:27
   800   1000 2:0
  1000   1000 0:0
  1000   1100 1:0
  1000   1145 1:45
  2345    115 -22:-30

6 rows selected.

Note that condition start_time > finish_time is not considered and thus the formatting is not correct. Fixing that is left as an exercise to OP !

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top