Skip to content
Advertisement

How to convert decimal to time in Oracle SQL?

In a certain table I’m querying, time is stored like this:
09:30 is stored as 9,3
14:25 is stored as 14,25

How can I, using SQL, convert 9,3 to 09:30 (hh:mm format)? So far, the only thing I could find in other questions are people who need to convert 9,5 to 09:30 (in my case, 9,5 means 09:50).

Right now, I’m using PHP to convert this. But my DB server is better than my application server. Since I need to get a lot of data, it would be better to solve this using SQL.

Sorry if this is a stupid question, but I’m new to SQL. Feel free to ask for more questions if you need to.

Advertisement

Answer

Assuming those are numeric values, you can get the hour part with trunc(your_column) and the minutes part with 100 * mod(your_column, 1). That gives you two numbers; you can format those and concatenate them, again assuming you want a string result, e.g.:

to_char(trunc(your_column), 'FM00') ||':' || to_char(100 * mod(your_column, 1), 'FM00')

Or more simply, format the whole number as a single string in one step, by telling it to use a colon as the decimal separator (with anything as the group separator – that isn’t used):

to_char(your_column, 'FM00D00', 'NLS_NUMERIC_CHARACTERS=:,')

Demo with sample data in a CTE:

-- CTE for sample data
with your_table (time) as (
  select 9.3 from dual
  union all select 9.03 from dual
  union all select 14.25 from dual
)
-- actual query
select time,
  to_char(trunc(time), 'FM00') ||':' || to_char(100 * mod(time, 1), 'FM00') as new_time1,
  to_char(time, 'FM00D00', 'NLS_NUMERIC_CHARACTERS=:,') as new_time2
from your_table;

      TIME NEW_TIME1 NEW_TIME2
---------- --------- ---------
       9.3 09:30     09:30    
      9.03 09:03     09:03    
     14.25 14:25     14:25    

If you actually want an interval data type result then you can use the same split with trunc/mod but handle the two numbers differently:

select time,
  numtodsinterval(trunc(time), 'HOUR')
    + numtodsinterval(100 * mod(time, 1), 'MINUTE') as new_time
from your_table;

      TIME NEW_TIME           
---------- -------------------
       9.3 +00 09:30:00.000000
      9.03 +00 09:03:00.000000
     14.25 +00 14:25:00.000000

Or you can convert to that time on a nominal date if you prefer, e.g.:

date '2000-01-01'
  + trunc(your_column), 'HOUR')
  + numtodsinterval(100 * mod(your_column, 1), 'MINUTE')

At some point you’ll run into problems if you have values that don’t really represent valid times – for example, 9.60 or 25.3. Either of the queries above will handle that to some extent – at least, up to 99.99 for the first one – but won’t necessarily give useful results. The string would give you ’09:60′ and ’25:30′, while the interval would give you ‘0 10:00:00’ and ‘1 01:30:00’, which is slightly more sensible perhaps. That’s the danger of using an inappropriate data type though.


Preserving a comment from @BobJarvis, if you actually want a date data type result then you can convert the number to a string without any separator and then convert from that to a date:

to_date(to_char(your_column, '00V00'), 'HH24MI')

which will give you that time on the first day of the current month. However, that will error with 9.60 or 25.3.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement