Calculating difference between two timestamps in Oracle in milliseconds

SqlOracleDatetime

Sql Problem Overview


How do I calculate the time difference in milliseconds between two timestamps in Oracle?

Sql Solutions


Solution 1 - Sql

When you subtract two variables of type TIMESTAMP, you get an INTERVAL DAY TO SECOND which includes a number of milliseconds and/or microseconds depending on the platform. If the database is running on Windows, systimestamp will generally have milliseconds. If the database is running on Unix, systimestamp will generally have microseconds.

  1  select systimestamp - to_timestamp( '2012-07-23', 'yyyy-mm-dd' )
  2*   from dual
SQL> /

SYSTIMESTAMP-TO_TIMESTAMP('2012-07-23','YYYY-MM-DD')
---------------------------------------------------------------------------
+000000000 14:51:04.339000000

You can use the EXTRACT function to extract the individual elements of an INTERVAL DAY TO SECOND

SQL> ed
Wrote file afiedt.buf

  1  select extract( day from diff ) days,
  2         extract( hour from diff ) hours,
  3         extract( minute from diff ) minutes,
  4         extract( second from diff ) seconds
  5    from (select systimestamp - to_timestamp( '2012-07-23', 'yyyy-mm-dd' ) diff
  6*           from dual)
SQL> /

      DAYS      HOURS    MINUTES    SECONDS
---------- ---------- ---------- ----------
         0         14         55     37.936

You can then convert each of those components into milliseconds and add them up

SQL> ed
Wrote file afiedt.buf

  1  select extract( day from diff )*24*60*60*1000 +
  2         extract( hour from diff )*60*60*1000 +
  3         extract( minute from diff )*60*1000 +
  4         round(extract( second from diff )*1000) total_milliseconds
  5    from (select systimestamp - to_timestamp( '2012-07-23', 'yyyy-mm-dd' ) diff
  6*           from dual)
SQL> /

TOTAL_MILLISECONDS
------------------
          53831842

Normally, however, it is more useful to have either the INTERVAL DAY TO SECOND representation or to have separate columns for hours, minutes, seconds, etc. rather than computing the total number of milliseconds between two TIMESTAMP values.

Solution 2 - Sql

Here's a stored proc to do it:

CREATE OR REPLACE function timestamp_diff(a timestamp, b timestamp) return number is 
begin
  return extract (day    from (a-b))*24*60*60 +
         extract (hour   from (a-b))*60*60+
         extract (minute from (a-b))*60+
         extract (second from (a-b));
end;
/

Up Vote if you also wanted to beat the crap out of the Oracle developer who negated to his job!

BECAUSE comparing timestamps for the first time should take everyone an hour or so...

Solution 3 - Sql

Easier solution:
SELECT numtodsinterval(date1-date2,'day') time_difference from dates;
For timestamps:
SELECT (extract(DAY FROM time2-time1)*24*60*60)+ 
(extract(HOUR FROM time2-time1)*60*60)+
(extract(MINUTE FROM time2-time1)*60)+
extract(SECOND FROM time2-time1)
into diff FROM dual;

RETURN diff;

Solution 4 - Sql

Select date1 - (date2 - 1) * 24 * 60 *60 * 1000 from Table;

Solution 5 - Sql

I know that this has been exhaustively answered, but I wanted to share my FUNCTION with everyone. It gives you the option to choose if you want your answer to be in days, hours, minutes, seconds, or milliseconds. You can modify it to fit your needs.

CREATE OR REPLACE FUNCTION Return_Elapsed_Time (start_ IN TIMESTAMP, end_ IN TIMESTAMP DEFAULT SYSTIMESTAMP, syntax_ IN NUMBER DEFAULT NULL) RETURN VARCHAR2 IS
	FUNCTION Core (start_ IN TIMESTAMP, end_ IN TIMESTAMP DEFAULT SYSTIMESTAMP, syntax_ IN NUMBER DEFAULT NULL) RETURN VARCHAR2 IS
		day_ VARCHAR2(7); /* This means this FUNCTION only supports up to 99 days */
		hour_ VARCHAR2(9); /* This means this FUNCTION only supports up to 999 hours, which is over 41 days */
		minute_ VARCHAR2(12); /* This means this FUNCTION only supports up to 9999 minutes, which is over 17 days */
		second_ VARCHAR2(18); /* This means this FUNCTION only supports up to 999999 seconds, which is over 11 days */
		msecond_ VARCHAR2(22); /* This means this FUNCTION only supports up to 999999999 milliseconds, which is over 11 days */
		d1_ NUMBER;
		h1_ NUMBER;
		m1_ NUMBER;
		s1_ NUMBER;
		ms_ NUMBER;
		/* If you choose 1, you only get seconds. If you choose 2, you get minutes and seconds etc. */
		precision_ NUMBER; /* 0 => milliseconds; 1 => seconds; 2 => minutes; 3 => hours; 4 => days */
		format_ VARCHAR2(2) := ', ';
		return_ VARCHAR2(50);
	BEGIN
		IF (syntax_ IS NULL) THEN
			precision_ := 0;
		ELSE
			IF (syntax_ = 0) THEN
				precision_ := 0;
			ELSIF (syntax_ = 1) THEN
				precision_ := 1;
			ELSIF (syntax_ = 2) THEN
				precision_ := 2;
			ELSIF (syntax_ = 3) THEN
				precision_ := 3;
			ELSIF (syntax_ = 4) THEN
				precision_ := 4;
			ELSE 
				precision_ := 0;
			END IF;
		END IF;
		SELECT EXTRACT(DAY FROM (end_ - start_)) INTO d1_ FROM DUAL;
		SELECT EXTRACT(HOUR FROM (end_ - start_)) INTO h1_ FROM DUAL;
		SELECT EXTRACT(MINUTE FROM (end_ - start_)) INTO m1_ FROM DUAL;
		SELECT EXTRACT(SECOND FROM (end_ - start_)) INTO s1_ FROM DUAL;
		IF (precision_ = 4) THEN
			IF (d1_ = 1) THEN
				day_ := ' day';
			ELSE
				day_ := ' days';
			END IF;
			IF (h1_ = 1) THEN
				hour_ := ' hour';
			ELSE
				hour_ := ' hours';
			END IF;
			IF (m1_ = 1) THEN
				minute_ := ' minute';
			ELSE
				minute_ := ' minutes';
			END IF;
			IF (s1_ = 1) THEN
				second_ := ' second';
			ELSE
				second_ := ' seconds';
			END IF;
			return_ := d1_ || day_ || format_ || h1_ || hour_ || format_ || m1_ || minute_ || format_ || s1_ || second_;
			RETURN return_;
		ELSIF (precision_ = 3) THEN
			h1_ := (d1_ * 24) + h1_;
			IF (h1_ = 1) THEN
				hour_ := ' hour';
			ELSE
				hour_ := ' hours';
			END IF;
			IF (m1_ = 1) THEN
				minute_ := ' minute';
			ELSE
				minute_ := ' minutes';
			END IF;
			IF (s1_ = 1) THEN
				second_ := ' second';
			ELSE
				second_ := ' seconds';
			END IF;
			return_ := h1_ || hour_ || format_ || m1_ || minute_ || format_ || s1_ || second_;
			RETURN return_;
		ELSIF (precision_ = 2) THEN
			m1_ := (((d1_ * 24) + h1_) * 60) + m1_;
			IF (m1_ = 1) THEN
				minute_ := ' minute';
			ELSE
				minute_ := ' minutes';
			END IF;
			IF (s1_ = 1) THEN
				second_ := ' second';
			ELSE
				second_ := ' seconds';
			END IF;
			return_ := m1_ || minute_ || format_ || s1_ || second_;
			RETURN return_;
		ELSIF (precision_ = 1) THEN
			s1_ := (((((d1_ * 24) + h1_) * 60) + m1_) * 60) + s1_;
			IF (s1_ = 1) THEN
				second_ := ' second';
			ELSE
				second_ := ' seconds';
			END IF;
			return_ := s1_ || second_;
			RETURN return_;
		ELSE
			ms_ := ((((((d1_ * 24) + h1_) * 60) + m1_) * 60) + s1_) * 1000;
			IF (ms_ = 1) THEN
				msecond_ := ' millisecond';
			ELSE
				msecond_ := ' milliseconds';
			END IF;
			return_ := ms_ || msecond_;
			RETURN return_;
		END IF;
	END Core;
BEGIN
	RETURN(Core(start_, end_, syntax_));
END Return_Elapsed_Time;

For example, if I called this function right now (12.10.2018 11:17:00.00) using Return_Elapsed_Time(TO_TIMESTAMP('12.04.2017 12:00:00.00', 'DD.MM.YYYY HH24:MI:SS.FF'),SYSTIMESTAMP), it should return something like:

47344620000 milliseconds

Solution 6 - Sql

Better to use procedure like that:

CREATE OR REPLACE FUNCTION timestamp_diff
(
start_time_in TIMESTAMP
, end_time_in TIMESTAMP
)
RETURN NUMBER
AS
l_days NUMBER;
l_hours NUMBER;
l_minutes NUMBER;
l_seconds NUMBER;
l_milliseconds NUMBER;
BEGIN
SELECT extract(DAY FROM end_time_in-start_time_in)
, extract(HOUR FROM end_time_in-start_time_in)
, extract(MINUTE FROM end_time_in-start_time_in)
, extract(SECOND FROM end_time_in-start_time_in)
INTO l_days, l_hours, l_minutes, l_seconds
FROM dual;

l_milliseconds := l_seconds*1000 + l_minutes*60*1000 + l_hours*60*60*1000 + l_days*24*60*60*1000;
RETURN l_milliseconds;

END;

You can check it by calling:

SELECT timestamp_diff (TO_TIMESTAMP('12.04.2017 12:00:00.00', 'DD.MM.YYYY HH24:MI:SS.FF'), 
                      TO_TIMESTAMP('12.04.2017 12:00:01.111', 'DD.MM.YYYY HH24:MI:SS.FF')) 
            as milliseconds
    FROM DUAL;

Solution 7 - Sql

The timestamp casted correctly between formats else there is a chance the fields would be misinterpreted.

Here is a working sample that is correct when two different dates (Date2, Date1) are considered from table TableXYZ.

SELECT ROUND (totalSeconds / (24 * 60 * 60), 1) TotalTimeSpendIn_DAYS,
       ROUND (totalSeconds / (60 * 60), 0) TotalTimeSpendIn_HOURS,
       ROUND (totalSeconds / 60) TotalTimeSpendIn_MINUTES,
	   ROUND (totalSeconds) TotalTimeSpendIn_SECONDS
  FROM (SELECT ROUND (
                    EXTRACT (DAY FROM timeDiff) * 24 * 60 * 60
                  + EXTRACT (HOUR FROM timeDiff) * 60 * 60
                  + EXTRACT (MINUTE FROM timeDiff) * 60
                  + EXTRACT (SECOND FROM timeDiff))
                  totalSeconds,
          FROM (SELECT TO_TIMESTAMP (
                            TO_CHAR (Date2,
                                     'yyyy-mm-dd HH24:mi:ss')
                          - 'yyyy-mm-dd HH24:mi:ss'),
                       TO_TIMESTAMP (
                          TO_CHAR (Date1,
                                   'yyyy-mm-dd HH24:mi:ss'),
                          'yyyy-mm-dd HH24:mi:ss')
                          timeDiff
                  FROM TableXYZ))

Solution 8 - Sql

Above one has some syntax error, Please use following on oracle:

SELECT ROUND (totalSeconds / (24 * 60 * 60), 1) TotalTimeSpendIn_DAYS,
  ROUND (totalSeconds      / (60 * 60), 0) TotalTimeSpendIn_HOURS,
  ROUND (totalSeconds      / 60) TotalTimeSpendIn_MINUTES,
  ROUND (totalSeconds) TotalTimeSpendIn_SECONDS
FROM
  (SELECT ROUND ( EXTRACT (DAY FROM timeDiff) * 24 * 60 * 60 + EXTRACT (HOUR FROM timeDiff) * 60 * 60 + EXTRACT (MINUTE FROM timeDiff) * 60 + EXTRACT (SECOND FROM timeDiff)) totalSeconds
  FROM
    (SELECT TO_TIMESTAMP(TO_CHAR( date2 , 'yyyy-mm-dd HH24:mi:ss'), 'yyyy-mm-dd HH24:mi:ss') - TO_TIMESTAMP(TO_CHAR(date1, 'yyyy-mm-dd HH24:mi:ss'),'yyyy-mm-dd HH24:mi:ss') timeDiff
    FROM TABLENAME
    )
);

Solution 9 - Sql

I) if you need to calculate the elapsed time in seconds between two timestamp columns try this:

SELECT 
    extract ( day from (end_timestamp - start_timestamp) )*86400 
    + extract ( hour from (end_timestamp - start_timestamp) )*3600 
    + extract ( minute from (end_timestamp - start_timestamp) )*60 
    + extract ( second from (end_timestamp - start_timestamp) ) 
FROM table_name

II) if you want to just show the time difference in character format try this:

SELECT to_char (end_timestamp - start_timestamp) FROM table_name

Solution 10 - Sql

I've posted here some methods to convert interval to nanoseconds and nanoseconds to interval. These methods have a nanosecond precision.

You just need to adjust it to get milliseconds instead of nanoseconds.

A shorter method to convert interval to nanoseconds.

SELECT (EXTRACT(DAY FROM (
	INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval --Maximum value: INTERVAL '+694444 10:39:59.999999999' DAY(6) TO SECOND(9) or up to 3871 year
) * 24 * 60) * 60 + EXTRACT(SECOND FROM (
	INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval
))) * 100 AS MILLIS FROM DUAL;

MILLIS
1598434427263.027

Solution 11 - Sql

I know that many people finding this solution simple and clear:

create table diff_timestamp (
f1 timestamp
, f2 timestamp);

insert into diff_timestamp values(systimestamp-1, systimestamp+2);
commit;

select cast(f2 as date) - cast(f1 as date) from diff_timestamp;

bingo!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsarsnakeView Question on Stackoverflow
Solution 1 - SqlJustin CaveView Answer on Stackoverflow
Solution 2 - SqlBrian McGinityView Answer on Stackoverflow
Solution 3 - Sqlpat34515View Answer on Stackoverflow
Solution 4 - SqlphadaphunkView Answer on Stackoverflow
Solution 5 - SqliamdoubzView Answer on Stackoverflow
Solution 6 - SqlKonkiView Answer on Stackoverflow
Solution 7 - SqlSreesankarView Answer on Stackoverflow
Solution 8 - SqlSanjay TiwariView Answer on Stackoverflow
Solution 9 - Sqlhany heggyView Answer on Stackoverflow
Solution 10 - SqlDanton Estevam PintoView Answer on Stackoverflow
Solution 11 - SqlIgor EgorovView Answer on Stackoverflow