I think this is what you are trying to do.
PROBLEM: given a global start timestamp GL_START_TS, a global end timestamp GL_END_TS and an interval length INT_LEN with GL_START_TS < GL_END_TS and INT_LEN > 0, generate random timestamps between GL_START_TS and GL_END_TS so that in each interval of length INT_LEN, starting from GL_START_TS, there is a
random number of values, with the count in each interval between N1 and N2 (where N1 and N2 are positive integers, N1 <= N2, also given as inputs). It is not clear if you assume that the difference GL_END_TS - GL_START_TS is an integer multiple of INT_LEN, and if it isn't, what should happen in the last, incomplete interval (imagine 15 minute intervals starting at 10:10 and ending at 12:20, for example - what should happen between 12:10 and 12:20?) In the solution I propose below, I assume there will be 0 values in that last, incomplete interval. If the total interval is an integer multiple of INT_LEN then the question is moot.
The inputs are hardcoded below; you can provide bind variables instead, or any other mechanism - that isn't what your question is about.
with
inputs (gl_start_ts, gl_end_ts, int_len, n1, n2) as (
select timestamp '2023-01-25 09:00:00', timestamp '2023-01-25 12:00:00', interval '15' minute, 3, 10
from dual
)
, intervals (start_ts, int_len, n) as (
select gl_start_ts + (level - 1) * int_len, int_len, trunc(dbms_random.value(n1, n2 + 1))
from inputs
connect by level * int_len <= gl_end_ts - gl_start_ts
start with int_len <= gl_end_ts - gl_start_ts
)
select ts
from intervals cross join lateral
( select start_ts + dbms_random.value() * int_len as ts
from dual
connect by level <= n
)
;