使用Oracle数据库,我需要知道任何两个日期之间的差异(以秒为单位),忽略从下午6点到早上8点的间隔。
因此,例如,01.11.2011 1pm和03.11.2011 1pm之间的差异相当于20小时(或分别为72000秒)。我还需要忽略周末和假期,但我已经有了PLSQL功能。
提前谢谢!
此致 亚历
的修改
与此同时,我自己提出了一个解决方案,老实说,这个解决方案并不是很复杂,但确实如此:
CREATE OR REPLACE FUNCTION "GET_WORKTIME"
(
startdate_in in date,
enddate_in in date
)
RETURN NUMBER
AS
days_between number(4);
duration number;
end_of_first_day date;
start_of_last_day date;
startdate date;
enddate date;
weekday number(1);
temp_date date;
holidays day_array;
is_holiday boolean;
BEGIN
duration := 0;
startdate := startdate_in;
enddate := enddate_in;
IF (startdate IS NULL OR enddate IS NULL OR startdate >= enddate) THEN
RETURN 0;
END IF;
days_between := trunc(enddate) - trunc(startdate);
end_of_first_day := to_date(concat(to_char(startdate, 'dd.mm.yyyy'), ' 18:00:00'), 'dd.mm.yyyy hh24:mi:ss');
start_of_last_day := to_date(concat(to_char(enddate, 'dd.mm.yyyy'), ' 08:00:00'), 'dd.mm.yyyy hh24:mi:ss');
temp_date := startdate;
FOR i IN 0..days_between LOOP
-- if it is the first day, just calculate the time until the end of that day
IF i = 0 THEN
duration := duration + greatest((end_of_first_day - startdate), 0) * 24 * 3600;
-- if it is the last day, just calculate the time until that point in time
ELSIF i = days_between THEN
duration := duration + greatest((enddate - start_of_last_day), 0) * 24 * 3600;
-- for every other day, simply add 10 hours (6pm - 8am) if it is neither
-- saturday or sunday nor a holiday
ELSE
weekday := to_number(to_char(temp_date, 'D'));
is_holiday := false;
-- weekend?
IF (NOT weekday IN (6,7)) THEN
-- holiday?
FOR j IN extract(year FROM startdate)..extract(year FROM enddate) LOOP
holidays := get_holidays_for_year(j);
FOR k IN 1..holidays.count LOOP
IF (holidays(k) = trunc(temp_date)) THEN
is_holiday := true;
END IF;
END LOOP;
END LOOP;
-- add 10 hours to the duration
IF (NOT is_holiday) THEN
duration := duration + 10 * 3600;
END IF;
END IF;
END IF;
temp_date := temp_date + 1;
END LOOP;
RETURN duration;
END;
该功能还忽略了周末和假期,因此它看起来比实际更全面。谢谢你的帮助!
此致 亚历
答案 0 :(得分:2)
将此分为3部分可能最容易:
第一个部分日是从(开始时间,上午8点)的后期(第一天的last_date,下午6点)开始,所以我们减去那些以获得第一天的时间:
greatest ( least ( trunc(first_date)+18/24
, last_date
) - greatest( first_date
, trunc(first_date)+8/24
)
, 0) * 24 as last_day_hours
外部greatest
功能可确保我们不会获得负值,例如如果开始时间是在下午6点之后。
如果最后一天与第一天不同,那么最后一个部分日是从最后一天的上午8点到(结束时间):
case when trunc(last_date) != trunc(first_date)
then greatest ( least( last_date
, trunc(last_date)+18/24
)
- (trunc(last_date)+8/24)
, 0) * 24
else 0 end as last_day_hours
整整几天(以小时为单位):
greatest ( (trunc(last_date) - (trunc(first_date)+1))
, 0
) * 10 as intervening_days_in_hours
10是上午8点到下午6点之间的小时数
因此,将这3个值加在一起得出该时段的总小时数,并将总数乘以3600得出秒数:
(
(greatest ( least ( trunc(first_date)+18/24
, last_date
) - greatest( first_date
, trunc(first_date)+8/24
)
, 0) * 24)
+ case when trunc(last_date) != trunc(first_date)
then greatest ( least( last_date
, trunc(last_date)+18/24
)
- (trunc(last_date)+8/24)
, 0) * 24
else 0 end
+ (greatest ( (trunc(last_date) - (trunc(first_date)+1))
, 0
) * 10)
) * 3600 as total_seconds
我不禁觉得它应该比这更容易!当然,这并不需要考虑周末。
答案 1 :(得分:0)
在Oracle中,您只需减去两个日期即可。 您可以通过将结果除以(24 * 60 * 60)
来计算秒数select (last_date - first_date) / (24*60*60) as seconds from table
格式化差异的一个技巧是:
select to_char(trunc(sysdate) + (last_date - first_date), 'hh24:mi:ss') as time_between from table