Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Mailing Lists -> Oracle-L -> RE: How to calculate the working hours?
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------_=_NextPart_001_01C2EE43.6E435080
Content-Type: text/plain
(re-sending because my e-mail from yesterday never made it to the list)
see answer below
> -----Original Message-----
> From: Andrea Oracle [mailto:andreaoracle_at_yahoo.com]
>
> We have open Time for every order, ef:
>
> Open Time
> ------------------
> 03/12/03 11:08:07
>
> How to calculate the working hours (8am - 5pm, no
> weekends) that a file remain open until now? (Sysdate
> - Open_Time) returns all the hours including weekend
> and <8am, >5pm hours. We only like to know the
> WORKING hours.
I couldn't resist the challenge. The formula below is clunky but it works.
Assume two dates, d1 and d2, with d1 <= d2. Find the number of working hours
between d1 and d2.
Oracle SQL formula:
(&&end_hour - &&start_hour)
+ decode (sign (to_number (to_char (d2, 'D')) - to_number (to_char (d1, 'D'))), -1, 1, 0 ) )
+ (decode (to_number (to_char (d2, 'D')),
&&saturday, &&end_seconds,
&&sunday, &&end_seconds,
greatest (least (to_number (to_char (d2, 'SSSSS')) - &&start_seconds, &&end_seconds), 0)
)
&&saturday, &&end_seconds,
&&sunday, &&end_seconds,
greatest (least (to_number (to_char (d1, 'SSSSS')) - &&start_seconds, &&end_seconds), 0)
)
) / 3600
where
&&saturday is to_date (..., 'D') for saturday (will depend on your
NLS_TERRITORY setting)
&&sunday is to_date (..., 'D') for sunday (will depend on your NLS_TERRITORY
setting)
&&start_hour is start of workday (in your case 8:00) &&end_hour is end of workday (in your case 17:00) &&start_seconds is number of seconds from midnight to &&start_hour &&end_seconds is number of seconds between &&start_hour and &&end_hour
Proof of concept for your specifications (workday from 8:00 to 17:00)
------_=_NextPart_001_01C2EE43.6E435080
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =charset=3DUS-ASCII">
<TITLE>RE: How to calculate the working hours?</TITLE> </HEAD> <BODY>
<P><FONT SIZE=3D2>(re-sending because my e-mail from yesterday never =
made it to the list)</FONT>
</P>
<P><FONT SIZE=3D2>see answer below</FONT> </P>
<P><FONT SIZE=3D2>> -----Original Message-----</FONT> <BR><FONT SIZE=3D2>> From: Andrea Oracle [<A = HREF=3D"mailto:andreaoracle_at_yahoo.com">mailto:andreaoracle_at_yahoo.com</A>= ]</FONT>
<BR><FONT SIZE=3D2>> </FONT> <BR><FONT SIZE=3D2>> We have open Time for every order, ef:</FONT> <BR><FONT SIZE=3D2>> </FONT> <BR><FONT SIZE=3D2>> Open Time</FONT> <BR><FONT SIZE=3D2>> ------------------</FONT> <BR><FONT SIZE=3D2>> 03/12/03 11:08:07</FONT> <BR><FONT SIZE=3D2>> </FONT> <BR><FONT SIZE=3D2>> How to calculate the working hours (8am - 5pm, =no</FONT>
<BR><FONT SIZE=3D2>> WORKING hours.</FONT> </P> <BR>
<P><FONT SIZE=3D2>I couldn't resist the challenge. The formula below is =
clunky but it works.</FONT>
<BR><FONT SIZE=3D2>Assume two dates, d1 and d2, with d1 <=3D d2. =
Find the number of working hours between d1 and d2.</FONT>
<BR><FONT SIZE=3D2>Oracle SQL formula:</FONT>
</P>
<P><FONT SIZE=3D2>(&&end_hour - =
&&start_hour) &nb= sp; &nb= sp; &nb= sp; &nb= sp; &nb= sp; &nb= sp; </FONT>
<BR><FONT SIZE=3D2> - trunc (decode (to_number = (to_char (d1, 'D')), &&saturday, d1 - 1, &&sunday, d1 - = 2, d1)) </FONT> <BR><FONT SIZE=3D2> = )  = ;  = ;  = ;  = ;  = ;  = ;  = ; =</FONT>
&&start_hour) &nb= sp; &nb= sp; &nb= sp; &nb= sp; &nb= sp; </FONT><BR><FONT SIZE=3D2> * (floor ((trunc (d2) - trunc = (d1)) / =
7) &nbs= p; &nbs= p; &nbs= p; &nbs= p; </FONT><BR><FONT SIZE=3D2> + decode = (sign (to_number (to_char (d2, 'D')) - to_number (to_char (d1, = 'D'))),  = ; </FONT>
0  = ;  = ;  = ;  = ;  = ;  = ; </FONT>
)  = ;  = ;  = ;  = ;  = ;  = ; </FONT> <BR><FONT SIZE=3D2> = )  = ;  = ;  = ;  = ;  = ;  =;  = ; </FONT> <BR><FONT SIZE=3D2>+ (decode (to_number (to_char (d2, =
'D')), = = = = =</FONT>
&&saturday, = &&end_seconds, &n= bsp; &n= bsp; &n= bsp; &n= bsp; &n= bsp; </FONT><BR><FONT =
&&sunday, = &&end_seconds, &n= bsp; &n= bsp; &n= bsp; &n= bsp; &n= bsp; </FONT><BR><FONT =
)  = ;  = ;  = ;  = ;  = ;  = ;  = ; </FONT>
'D')), = = = = </FONT><BR><FONT =
&&end_seconds, &n= bsp; &n= bsp; &n= bsp; &n= bsp; &n= bsp; </FONT>
&&end_seconds, &n= bsp; &n= bsp; &n= bsp; &n= bsp; &n= bsp; </FONT><BR><FONT =
)  = ;  = ;  = ;  = ;  = ;  = ;  = ; </FONT>
3600 &n= bsp; &n= bsp; &n= bsp; &n= bsp; &n= bsp; &n= bsp; &n= bsp; </FONT><BR><FONT =
SIZE=3D2> &nb= sp; &nb= sp; &nb= sp; &nb= sp; &nb= sp; &nb= sp; &nb= sp; &nb= sp; </FONT></P>
<P><FONT SIZE=3D2>where</FONT>
<BR><FONT SIZE=3D2>&&saturday is to_date (..., 'D') for =
saturday (will depend on your NLS_TERRITORY setting)</FONT>
<BR><FONT SIZE=3D2>&&sunday is to_date (..., 'D') for sunday =
(will depend on your NLS_TERRITORY setting)</FONT>
<BR><FONT SIZE=3D2>&&start_hour is start of workday (in your =
case 8:00)</FONT>
<BR><FONT SIZE=3D2>&&end_hour is end of workday (in your case =
17:00)</FONT>
<BR><FONT SIZE=3D2>&&start_seconds is number of seconds from =
midnight to &&start_hour</FONT>
<BR><FONT SIZE=3D2>&&end_seconds is number of seconds between =
&&start_hour and &&end_hour</FONT>
</P>
<P><FONT SIZE=3D2>Proof of concept for your specifications (workday =
from 8:00 to 17:00)</FONT>
</P>
<P><FONT SIZE=3D2>-- populate table with sample data</FONT> <BR><FONT SIZE=3D2>drop table t ;</FONT> <BR><FONT SIZE=3D2>create table t (d1 date, d2 date) ;</FONT> <BR><FONT SIZE=3D2>declare</FONT> <BR><FONT SIZE=3D2> start_date constant date :=3D to_date =('2003/03/01', 'YYYY/MM/DD') ;</FONT>
<BR><FONT SIZE=3D2>begin</FONT> <BR><FONT SIZE=3D2> for i in 1..7</FONT> <BR><FONT SIZE=3D2> loop</FONT> <BR><FONT SIZE=3D2> for j in 1..24</FONT> <BR><FONT SIZE=3D2> loop</FONT> <BR><FONT SIZE=3D2> for =k in 1..14</FONT>
<BR><FONT SIZE=3D2> = loop</FONT> <BR><FONT =
<BR><FONT SIZE=3D2> end loop ;</FONT> <BR><FONT SIZE=3D2> end loop ;</FONT> <BR><FONT SIZE=3D2> commit ;</FONT> <BR><FONT SIZE=3D2>end ;</FONT> <BR><FONT SIZE=3D2>/</FONT> <BR><FONT SIZE=3D2>--</FONT> <BR><FONT SIZE=3D2>-- calculate formula variables</FONT> <BR><FONT SIZE=3D2>undefine start_hour</FONT> <BR><FONT SIZE=3D2>undefine end_hour</FONT> <BR><FONT SIZE=3D2>undefine start_seconds</FONT> <BR><FONT SIZE=3D2>undefine end_seconds</FONT> <BR><FONT SIZE=3D2>undefine saturday</FONT> <BR><FONT SIZE=3D2>undefine sunday</FONT> <BR><FONT SIZE=3D2>define start_hour =3D "8"</FONT> <BR><FONT SIZE=3D2>define end_hour =3D "17"</FONT> <BR><FONT SIZE=3D2>column saturday_day_number noprint new_value =saturday</FONT>
<BR><FONT SIZE=3D2>from dual ;</FONT> <BR><FONT SIZE=3D2>clear columns</FONT> <BR><FONT SIZE=3D2>--</FONT> <BR><FONT SIZE=3D2>-- query test table to verify results.</FONT> <BR><FONT SIZE=3D2>-- change value in where clause to verify for =different begin dates</FONT>
![]() |
![]() |