前置条件:需要维护一张节假日日期表。例如创建holiday表保存当年假期日期
CREATE TABLE `holiday` (
`id` BIGINT(10) ZEROFILL NOT NULL DEFAULT 0,
`day` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COMMENT='假期表'
COLLATE='utf8mb4_0900_ai_ci'
;
返回日期为xx日xx时xx分格式,可以在此基础上调整格式
-- FUNCTION: public.get_timedelay(timestamp with time zone, timestamp with time zone)
-- DROP FUNCTION IF EXISTS public.get_timedelay(timestamp with time zone, timestamp with time zone);
CREATE OR REPLACE FUNCTION public.get_timedelay(
starttime timestamp with time zone,
endtime timestamp with time zone)
RETURNS text
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
v_return varchar;--返回间隔时间 xx日xx时xx分
v_minute integer;--间隔分钟
v_hour integer;
v_temp_minute integer;
v_temp_hour integer;
v_day integer; --间隔天数
v_all numeric;
v_counter integer;
v_end_weekend integer;
v_weekend integer;--周一_周日 1_6_0
v_holiday numeric;--匹配节假日天数
v_is_weekend boolean; --是否周末
v_is_holiday boolean; --是否节假日
BEGIN
--计算时间间隔天数
select ceil(DATE_PART('epoch', endtime::timestamp - starttime::TIMESTAMP)/60/60/24) into v_all;
--减去周末、节假日
v_end_weekend := cast(EXTRACT(DOW FROM (endtime)) as int);
v_day := 0;
v_hour := 0;
v_minute := 0;
v_counter := 0;
while v_counter <= v_all loop
v_temp_minute := 0;
v_temp_hour := 0;
v_is_weekend := FALSE;
v_is_holiday := FALSE;
--判断该日期为周几
v_weekend := v_end_weekend-v_counter%7;
if v_weekend < 0 then
v_weekend := v_weekend + 7;
end if;
if v_weekend = 6 or v_weekend = 0 then
v_is_weekend := true;
end if;
--判断该日期是否为节假日
--日期表
SELECT COUNT(*) FROM holiday WHERE Date(endtime) - DATE(day) - v_counter = 0 INTO v_holiday;
if v_is_weekend = false and v_holiday > 0 then
v_is_holiday := true;
end if;
--累计时长
if v_is_weekend = false AND v_is_holiday = false then
if v_counter = 0 then
v_minute := cast(date_part('minute', endtime::TIMESTAMP) as int);
v_hour := cast(date_part('hour', endtime::TIMESTAMP) as int);
elseif v_counter = v_all then
v_temp_minute := 60 - cast(date_part('minute', endtime::TIMESTAMP) as int);
v_temp_hour := 23 - cast(date_part('hour', endtime::TIMESTAMP) as int);
v_minute := (v_minute+v_temp_minute) % 60;
v_temp_hour := v_temp_hour+FLOOR((v_minute+v_temp_minute)/60);
v_hour := (v_hour+v_temp_hour) % 24;
v_day := v_day + FLOOR((v_hour+v_temp_hour) / 24);
else
v_day := v_day + 1;
end if;
end if;
v_counter:= v_counter+1;
end loop;
--处理返回日期
v_return := '';
--返回日、时、分方案
if v_day > 0 then
v_return := concat(v_return, v_day,'日');
end if;
if v_hour > 0 then
v_return := concat(v_return, v_hour,'时');
end if;
if v_minute > 0 then
v_return := concat(v_return,v_minute,'分');
end if;
RETURN v_return;
EXCEPTION
WHEN OTHERS THEN
RETURN SQLERRM;
END;
$BODY$;
ALTER FUNCTION public.get_timedelay(timestamp with time zone, timestamp with time zone)
OWNER TO postgres;