-- Začátek aktuálního (+offset) 15min slotu v Europe/Prague jako timestamptz (UTC instants). -- Volitelné p_at (např. job po uzavření slotu); null = now(). drop function if exists ems.fn_planning_slot_boundary_prague(int); create or replace function ems.fn_planning_slot_boundary_prague( p_offset_slots int default 0, p_at timestamptz default null ) returns timestamptz language sql stable as $fn$ select ( (date_trunc('day', loc.ts) + make_interval( hours => extract(hour from loc.ts)::int, mins => (floor(extract(minute from loc.ts) / 15) * 15)::int ) )::timestamp at time zone 'Europe/Prague' ) + make_interval(mins => coalesce(p_offset_slots, 0) * 15) from ( select coalesce(p_at, now()) at time zone 'Europe/Prague' as ts ) loc; $fn$; comment on function ems.fn_planning_slot_boundary_prague(int, timestamptz) is 'Začátek 15min slotu (Europe/Prague floor); offset v násobcích 15 min; p_at volitelně místo now().';