Oracle - Calculate the difference between dates and extract days and hours only in Oracle - oracle

I have a query that calculates the difference between two dates and returns a decimal date. I would just like to extract days and hours from the final calculated date.
This is my query.
select sysdate - (to_date('24/AUG/2021 14:00:00', 'DD/MON/YYYY HH24:MI:SS')) as FinalDate from dual;
FinalDate
162.013252314814814814814814814814814815
How do I get my desired output:?
Desired output
| Days | Hours |
| -------- | ------|
|162 |0.24 |

A little bit of arithmetic.
SQL> with temp (finaldate) as
2 (select sysdate - (to_date('24/AUG/2021 14:00:00', 'DD/MON/YYYY HH24:MI:SS')) from dual)
3 select trunc(finaldate) as days,
4 round((finaldate - trunc(finaldate)) * 24, 2) as hours
5 from temp;
DAYS HOURS
---------- ----------
162 6,49
SQL>
Why your and my hours don't match? Because of time difference; it's
SQL> select sysdate from dual;
SYSDATE
-------------------
02.02.2022 20:30:04
SQL>
over here.

Related

Oracle - Extract Year from date result in 0 [duplicate]

This question already has an answer here:
Trying to export a Oracle via PL/SQL gives a date of 0000-00-00
(1 answer)
Closed 1 year ago.
Duplicate of Trying to export a Oracle via PL/SQL gives a date of 0000-00-00 as mentioned by #AlexPoole
I have a table with different dates in it, however, when I try to extract year, a single row returns an incorrect result.
This incorrect result happens when I execute the following (note that TO_DATE and FROM_DATE are both of data_type DATE):
select
TO_DATE
,EXTRACT(YEAR FROM TO_DATE) as "TO_YEAR"
,EXTRACT(MONTH FROM TO_DATE) as "TO_MONTH"
,EXTRACT(DAY FROM TO_DATE) as "TO_DAY"
,FROM_DATE
,EXTRACT(YEAR FROM FROM_DATE) as "FROM_YEAR"
,EXTRACT(MONTH FROM FROM_DATE) as "FROM_MONTH"
,EXTRACT(DAY FROM FROM_DATE) as "FROM_DAY"
,DUMP(FROM_DATE, 1016) as FROM_DUMP
,to_char(FROM_DATE, 'SYYYY-MM-DD HH24:MI:SS') FROM_STRING
from SomeTable
The incorrect result is (date format is YY-MM-DD):
TO_DATE TO_YEAR TO_MONTH TO_DAY FROM_DAT FROM_YEAR FROM_MONTH FROM_DAY FROM_DUMP FROM_STRING
-------- ---------- ---------- ---------- -------- ---------- ---------- ---------- ----------------------------- --------------------
00-02-01 2000 2 1 01-02-01 0 2 1 Typ=12 Len=7: 64,64,2,1,1,1,1 00000-00-00 00:00:00
My question is why does FROM_YEAR return a zero and not 2001?
A DATE is stored in 7-bytes using:
century + 100
year-of-century + 100
month + 0
day + 0
hour + 1
minute + 1
second + 1
Looking at the output of DUMP, which is Typ=12 Len=7: 64,64,2,1,1,1,1 then you have:
Century = -36
Year-of-century = -36
Month = February
Day = 1
Hour = 0
Minute = 0
Year = 0
Which would make your date midnight of 1st February 3636 BC.
Unless you intended to use dates from ancient history then it would suggest that somewhere in your application some corrupted data has been stored.
However, something else appears to be going on as that is a valid date that can be stored and TO_CHAR should work.
CREATE TABLE table_name ( dt ) AS
SELECT DATE '-3636-02-01'FROM DUAL;
SELECT TO_CHAR( dt, 'SYYYY-MM-DD HH24:MI:SS' ) AS dt_string,
DUMP( dt )
FROM table_name;
Outputs:
DT_STRING
DUMP(DT)
-3636-02-01 00:00:00
Typ=12 Len=7: 64,64,2,1,1,1,1
db<>fiddle here
and the DUMP matches your data but the TO_CHAR output is valid whereas yours is zeros.

DATE DIFF IN YEARS

How to find date diff in years in 'YYYY-MM-DD' format .
I am using below two querues:
SELECT TRUNC(TO_NUMBER(SYSDATE - TO_DATE('1994-08-13')) / 365.25) AS AGE FROM DUAL;
ORA-01861: literal does not match format string
SELECT (TO_DATE(SYSDATE, 'YYYY-MM-DD') - TO_NUMBER('1994-08-13', 'YYYY-MM-DD')) FROM DUAL;
O/P-: -727738
Desired o/p: 26
I suggest to use "months_between" function because it takes leap years into account (months_between wants 2 dates as parameters):
select months_between(sysdate, to_date('1994-08-13', 'YYYY-MM-DD'))/12 from dual;
26,4729751904122
of course, if you need to truncate:
select trunc(months_between(sysdate, to_date('1994-08-13', 'YYYY-MM-DD'))/12) from dual;
26
Just subtract one date from the other:
sysdate - date '1994-08-13'
Or
sysdate - to_date('1994-08-13', 'yyyy-mm-dd')
returns the number of days between the two dates.
So rewrite your first query to:
select (sysdate - date '1994-08-13') / 365.25 as age
from dual
So, extract years from these dates and subtract them:
SQL> select extract (year from sysdate) - extract(year from date '1994-08-13') diff
2 from dual;
DIFF
----------
27
SQL>
Because,
SQL> select 2021 - 1994 diff from dual;
DIFF
----------
27
SQL>

Use EPOCH time for timestamp to get records within 1 minute

I was curious to see how in Oracle 12c you can take a timestamp datatype and convert the records into EPOCH time to make them a number and then use that number to find any records within that date column that are within 1 minute of each other (assuming the same day if needed, or simply any calculations within 1 minute).
I tried the following but got an ORA-01873: the leading precision of the interval is too small error.
select (sold_date - to_date('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS'))*86400 as epoch_sold_date from test1;
What is SOLD_DATE? For e.g. SYSDATE (function that returns DATE datatype), your code works OK.
SQL> select (sysdate
2 - to_date('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS')
3 ) * 86400 as epoch_sold_date
4 from dual;
EPOCH_SOLD_DATE
---------------
1600807918
SQL>
As SOLD_DATE is a timestamp, but - it appears that fractions of a second aren't or special interest to you, cast it to DATE:
select (cast (systimestamp as date) --> this
- to_date('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS')
) * 86400 as epoch_sold_date
from dual;
Saying that you get the same result for all rows: well, I don't, and you shouldn't either if SOLD_DATE differs.
SQL> with test (sold_date) as
2 (select timestamp '2020-09-22 00:00:00.000000' from dual union all
3 select timestamp '2015-03-18 00:00:00.000000' from dual
4 )
5 select sold_date,
6 (cast (sold_date as date)
7 - to_date('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS')
8 ) * 86400 as epoch_sold_date
9 from test;
SOLD_DATE EPOCH_SOLD_DATE
------------------------------ ---------------
22.09.20 00:00:00,000000000 1600732800
18.03.15 00:00:00,000000000 1426636800
SQL>
One more edit: when you subtract two timestamps, result is interval day to second. If you extract minutes from it, you get what you wanted:
SQL> with test (sold_date) as
2 (select timestamp '2020-09-22 10:15:00.000000' from dual union all
3 select timestamp '2015-03-18 08:05:00.000000' from dual
4 )
5 select sold_date,
6 lead(sold_date) over (order by sold_date) next_sold_date,
7 --
8 lead(sold_date) over (order by sold_date) - sold_date diff,
9 --
10 extract(day from lead(sold_date) over (order by sold_date) - sold_date) diff_mins
11 from test
12 order by sold_date;
SOLD_DATE NEXT_SOLD_DATE DIFF DIFF_MINS
------------------------------ ------------------------------ ------------------------------ ----------
18.03.15 08:05:00,000000000 22.09.20 10:15:00,000000000 +000002015 02:10:00.000000000 2015
22.09.20 10:15:00,000000000
SQL>
In your case, you'd check whether extracted minutes value is larger than 1 (minute).
If you just want to see how many minutes are there between two timestamps, then
cast them to dates
subtract those dates (and you'll get number of days)
multiply it by 24 (as there are 24 hours in a day) and by 60 (as there are 60 minutes in an hour)
Something like this:
SQL> with test (date_1, date_2) as
2 (select timestamp '2020-09-22 10:15:00.000000',
3 timestamp '2020-09-22 08:05:00.000000' from dual
4 )
5 select (cast(date_1 as date) - cast(date_2 as date)) * 24 * 60 diff_minutes
6 from test;
DIFF_MINUTES
------------
130
SQL>
If you are just looking to compare dates and find rows that are within one minute of each other, you do not need to use epoch time. There are several solutions to this problem on this thread.

How to extract time from a column and subtract from a custom time in Oracle

I would like to compare two time values. The first time value is a custom time which reprsents the start time, for example the column name is Business_Start_time and set to 6:00:00 am. I would also like to extract the time only from a column in Oracle which is a date field that looks like '5/1/2019 12:57:19 PM' and is called 'Completed_Date_Time'. The purpose of this is to compare the businses start date to the time a file was completed. I've tried to convert the 'Completed_Date_Time' field to 'HH24:MI:SS' format which seems to change the datatype to a char(8) value which does not allow me to compare two timestamps.
CAST(TO_CHAR(Completed_Date_Time, 'HH:MI:SS AM') AS CHAR(8))
Convert the values to TIMESTAMP and then you can subtract the values from the values truncated to the start of the day to get an INTERVAL containing the time since midnight and to get the difference you can subtract.
Oracle Setup:
CREATE TABLE table_name ( Business_Start_time, Completed_Date_Time ) AS
SELECT '6:00:00 AM',
TO_DATE( '5/1/2019 12:57:19 PM', 'DD/MM/YYYY HH12:MI:SS AM' )
FROM DUAL
Query:
SELECT ( completed_time - TRUNC( completed_time ) ) -
( start_time - TRUNC( start_time ) ) AS time_difference
FROM (
SELECT TO_TIMESTAMP( business_start_time, 'HH12:MI:SS AM' ) AS start_time,
CAST( Completed_Date_Time AS TIMESTAMP ) AS completed_time
FROM table_name
)
Output:
| TIME_DIFFERENCE |
| :---------------------------- |
| +000000000 06:57:19.000000000 |
db<>fiddle here
Although you wrote both the question and a comment, I'm still not sure what you have and what you want to get. Sample case would help (create table & insert into).
Meanwhile, a few words about it: when subtracting two DATE datatype values, the result is number of days, which means that - if you want to display it in a format which is easier to read & understand - you have to do some calculations (a day has 24 hours; an hour has 60 mintues; and so forth).
Here's an example:
SQL> create table test
2 (business_Start_time date,
3 completed_date_Time date
4 );
Table created.
SQL> insert into test (business_start_time, completed_date_time) values
2 (to_date('05.01.2019 12:57:19', 'dd.mm.yyyy hh24:mi:ss'),
3 to_date('05.01.2019 18:58:20', 'dd.mm.yyyy hh24:mi:ss'));
1 row created.
Simply subtracted, you'd get
SQL> select completed_date_time - business_start_time result from test;
RESULT
----------
,250706019
SQL>
Here's a function which presents such a value in another format, dd:hh:mi (days:hours:minutes) (you can omit days by setting the second parameter to 0):
SQL> create or replace
2 function f_days2ddhhmi (par_broj_dana in number, par_cb_dd in number)
3 return varchar2
4 is
5 /* Converting number of days into dd:hh:mi format
6
7 Date from Date to Diff (days) Retval
8 -------------------- -------------------- -------------- ----------------------------------
9 20.11.2018. 07:00:00 - 20.11.2018. 13:45:00 0,28125 0:06:45 (6 hours 45 minutes)
10 23.10.2018. 07:00:00 - 25.10.2018. 22:12:00 2,63333 2:15:12 (2 daysa 15 hours 12 minutes)
11
12 PAR_BROJ_DANA: 0.28125
13 PAR_CB_DD : display number of days or not? 1 - yes --> 0:06:45
14 0 - no --> 06:45
15 */
16 l_broj_dana number := round (par_broj_dana, 15); -- to avoid 1.99999999999999 days = 1 day 24 hours
17 retval varchar2 (20);
18 begin
19 with podaci
20 as (select trunc (l_broj_dana) broj_dana,
21 round (mod (l_broj_dana * 24, 24), 2) broj_sati
22 from dual)
23 select decode (par_cb_dd,
24 1, lpad (p.broj_dana, 2, '0') || ':',
25 0, null)
26 || lpad (trunc (p.broj_sati), 2, '0')
27 || ':'
28 || lpad (round ( (p.broj_sati - trunc (p.broj_sati)) * 60),
29 2,
30 '0')
31 into retval
32 from podaci p;
33
34 return retval;
35 end f_days2ddhhmi;
36 /
Function created.
Applied to the test table, you'd get
SQL> select f_days2ddhhmi(completed_date_time - business_start_time, 0) result
2 from test;
RESULT
--------------------------------------------------------------------------------
06:01
which means that the difference is 6 hours and 1 minute.
If that's what you asked, see whether you can use it. Feel free to enhance it to seconds etc. if necessary.

oracle concat timestmap from current_date

I hardly try to concat timestamps. Column time, defined as varchar2, contains values like 23:15. Now I want to create a timestamp with today's date and that time, in this example 23.03.18 23:15:00.00000 is expected. The way I'm doing this is
to_timestamp(to_char(trunc(current_date),'ddMMyyyy') ||
to_char(time),'dd.MM.yyyy hh24:mi:ss')
and it works. But when field time has value 06:15, I get the message "hour must be between 0 and 23 ". Whatever I try, it's always this message when time value has leading zero. How can that be corrected?
You don't need to use TRUNC on the current date as the TO_CHAR will extract only the year-to-day components and you also don't need TO_CHAR on the time column as it is already a string. Apart from those simplifications, your query works:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE times ( time ) AS
SELECT '00:00' FROM DUAL UNION ALL
SELECT '06:45' FROM DUAL UNION ALL
SELECT '12:00' FROM DUAL UNION ALL
SELECT '18:59' FROM DUAL UNION ALL
SELECT '23:15' FROM DUAL;
Query 1:
SELECT time,
TO_TIMESTAMP(
TO_CHAR( CURRENT_DATE, 'YYYY-MM-DD' ) || time,
'YYYY-MM-DDHH24:MI'
) AS current_day_time
FROM times
Results:
| TIME | CURRENT_DAY_TIME |
|-------|-----------------------|
| 00:00 | 2018-03-23 00:00:00.0 |
| 06:45 | 2018-03-23 06:45:00.0 |
| 12:00 | 2018-03-23 12:00:00.0 |
| 18:59 | 2018-03-23 18:59:00.0 |
| 23:15 | 2018-03-23 23:15:00.0 |
Works OK for me:
SQL> WITH test
2 AS (SELECT '23:15' time FROM DUAL
3 UNION
4 SELECT '06:15' time FROM DUAL)
5 SELECT TO_TIMESTAMP (
6 TO_CHAR (CURRENT_DATE, 'ddMMyyyy') || time,
7 'dd.MM.yyyy hh24:mi:ss') result
8 FROM test;
RESULT
----------------------------------------------------------------
23.03.18 06:15:00,000000000
23.03.18 23:15:00,000000000
SQL>
Please, post your SQL*Plus session so that we could see what you did.
try other way around: insert a leading 0 if hour < 10
to_timestamp(to_char(trunc(current_date),'ddMMyyyy') ||
to_char(
case when substr(time,1,instr(time,':',1,1)-1)<10
then'0'||time
else time
end),'dd.MM.yyyy hh24:mi:ss')

Resources