## Forum Stats

• 3,768,656 Users
• 2,252,827 Discussions

Discussions

# Rounding Time to nearest 30 minutes

Member Posts: 20
edited Jan 2, 2010 7:03AM
Good day,

I'm looking for a way to round the time portion of a date value. My query needs to return the time of day, rounded to the nearest 30 minutes - top of the hour or bottom of the hour.

If sysdate is: 12/28/2009 11:08:19 AM
I need to see: 12/28/2009 11:00:00 AM

If sysdate returns: 12/28/2009 11:18:19 AM
I need to see: 12/28/2009 11:30:00 AM

Any help is appreciated.

Regards,

Gary F.

• Member, Moderator Posts: 41,212 Red Diamond
edited Dec 28, 2009 12:00PM Accepted Answer
Hi,

For rounding to a half-hour (or any inteval that TRUNC does not handle) you can figure out the number of such periods since midnight (or some other convenient base point), round that number, and then add that many periods to midnight, like this:
```ALTER SESSION	SET NLS_DATE_FORMAT = 'DD-Mon-YYYY HH24:MI:SS';

SELECT	SYSDATE
,	TRUNC (SYSDATE) + ( ROUND ( (SYSDATE - TRUNC (SYSDATE))
* 48
)
/ 48
)
FROM    dual;```
In this case, there are 48 periods in a day.
Multiplying by 48 converts days to periods, dividing by 48 converts periods to days.
«1

• Member, Moderator Posts: 41,212 Red Diamond
edited Dec 28, 2009 11:31AM
Hi, Gary,
```SELECT	SYSDATE
,	TRUNC (SYSDATE) + ( ROUND ( (SYSDATE - TRUNC (SYSDATE))
* 48
)
/ 48
)
FROM    dual;```
Edited by: Frank Kulash on Dec 28, 2009 11:18 AM
The original answer was for a different question , as OP noted.
• Member Posts: 20
Frank,

Thanks for the quick response. I do appreciate it.

However, I need to round to the nearest half hour. At 1 minute past the hour I need to go back one minute to the top of the hour. At 25 past the hour, I need to go forward 5 minutes to the bottom of the hour.

Thanks,

Gary F.
• Member, Moderator Posts: 41,212 Red Diamond
edited Dec 28, 2009 12:00PM Accepted Answer
Hi,

For rounding to a half-hour (or any inteval that TRUNC does not handle) you can figure out the number of such periods since midnight (or some other convenient base point), round that number, and then add that many periods to midnight, like this:
```ALTER SESSION	SET NLS_DATE_FORMAT = 'DD-Mon-YYYY HH24:MI:SS';

SELECT	SYSDATE
,	TRUNC (SYSDATE) + ( ROUND ( (SYSDATE - TRUNC (SYSDATE))
* 48
)
/ 48
)
FROM    dual;```
In this case, there are 48 periods in a day.
Multiplying by 48 converts days to periods, dividing by 48 converts periods to days.
• Member Posts: 16,076 Gold Crown
Does this work for you:
```with dates as ( -- generating sample data
select to_date('12/28/2009 11:08:19 AM', 'mm/dd/yyyy hh:mi:ss AM') dt from dual union all
select to_date('12/28/2009 11:18:19 AM', 'mm/dd/yyyy hh:mi:ss AM') from dual
)
--
-- actual query
--
select to_char(dt, 'mm/dd/yyyy hh:')
||
to_char(round(to_number(to_char(dt, 'mi'))/30)*30, 'fm00')
||
':00'
from   dates;```
?
• Member Posts: 20
Frank & Hoek,

Thanks to both of you for helping me solve this simple query.

I may use either or both of your solutions.

Regards,

Gary F.
• Member Posts: 8,424 Bronze Crown
Or
```SQL> alter session set nls_date_format='dd/mm/yyyy hh24:mi:ss'
/
Session altered.

SQL> with dates as (
select to_date('12/28/2009 11:14:59 AM', 'mm/dd/yyyy hh:mi:ss AM') dt from dual union all
select to_date('12/28/2009 11:15:00 AM', 'mm/dd/yyyy hh:mi:ss AM') from dual
)
--
--
select dt, trunc(dt) + round(to_char(dt,'sssss')/1800)/48 from dates
/
DT                    TRUNC(DT)+ROUND(TO_CHAR(DT,'SSSSS')/1800)/48
--------------------- --------------------------------------------
28/12/2009 11:14:59   28/12/2009 11:00:00
28/12/2009 11:15:00   28/12/2009 11:30:00

2 rows selected.```
• Member Posts: 18,910 Red Diamond
`your_date + 1/48 - mod(your_date - trunc(your_date),1/48)`
For eaxmple:
```SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'DD-Mon-YYYY HH24:MI:SS'
2  /

Session altered.

SQL> select sysdate dt,sysdate + 1/48 - mod(sysdate - trunc(sysdate),1/48) dt_rounded_to_half_hour
2    from dual
3  /

DT                   DT_ROUNDED_TO_HALF_H
-------------------- --------------------
28-Dec-2009 11:53:12 28-Dec-2009 12:00:00

SQL> ```
SY.
• Member Posts: 16,076 Gold Crown
edited Dec 28, 2009 11:57AM
Hi Gary,
I may use either or both of your solutions.
But from an 'elegance point of view', I suggest you should use Frank's or Michael's solution

edit
Add Solomon to the above as well.

Edited by: hoek on Dec 28, 2009 5:56 PM
• Member Posts: 1,072 Bronze Badge
edited Dec 29, 2009 12:07AM
I like case expression B-)
```ALTER SESSION   SET NLS_DATE_FORMAT = 'YYYY-mm-DD HH24:MI:SS';

with dates as ( -- generating sample data
select to_date('12/28/2009 11:08:19', 'mm/dd/yyyy hh:mi:ss') dt from dual union all
select to_date('12/28/2009 11:18:19', 'mm/dd/yyyy hh:mi:ss') from dual)
select dt,
case when to_char(dt,'mi') between '00' and '14'
then trunc(dt,'HH24')
when to_char(dt,'mi') between '15' and '44'
then trunc(dt,'HH24') + interVal '30' minute
when to_char(dt,'mi') between '45' and '59'
then trunc(dt,'HH24') + interVal '60' minute
end as new
from dates;

DT                   NEW
-------------------  -------------------
2009-12-28 11:08:19  2009-12-28 11:00:00
2009-12-28 11:18:19  2009-12-28 11:30:00```
• Member Posts: 18,910 Red Diamond
Aketi Jyuuzou wrote:
I like case expression B-)
Me too, but I like then simple B-) :
```with dates as ( -- generating sample data
select to_date('12/28/2009 11:08:19', 'mm/dd/yyyy hh:mi:ss') dt from dual union all
select to_date('12/28/2009 11:18:19', 'mm/dd/yyyy hh:mi:ss') dt from dual union all
select to_date('12/28/2009 11:38:19', 'mm/dd/yyyy hh:mi:ss') dt from dual union all
select to_date('12/28/2009 11:48:19', 'mm/dd/yyyy hh:mi:ss') from dual)
select dt,
case when to_char(dt,'mi') >= '45'
then trunc(dt,'hh') + interVal '60' minute
when to_char(dt,'mi') >= '15'
then trunc(dt,'hh') + interVal '30' minute
else trunc(dt,'hh')
end as new
from dates
/

DT                  NEW
------------------- -------------------
2009-12-28 11:08:19 2009-12-28 11:00:00
2009-12-28 11:18:19 2009-12-28 11:30:00
2009-12-28 11:38:19 2009-12-28 11:30:00
2009-12-28 11:48:19 2009-12-28 12:00:00

SQL> ```
SY.
This discussion has been closed.