PostgreSQL: format interval as minutes

Postgresql

Postgresql Problem Overview


When I subtract timestamps, the interval is in form DD:HH:MM:SS. How can I convert it all to minutes without extracting days and hours and multiplication/addition? I'm looking for a single function which I can substitute for date_part in this query so that it returns 65:

select date_part('minutes', '65 minutes'::interval);

Context: I need to know how many minutes have passed since given timestamp.

Postgresql Solutions


Solution 1 - Postgresql

SELECT EXTRACT(EPOCH FROM '2 months 3 days 12 hours 65 minutes'::INTERVAL)/60;

seems to work.

WARNING: "seems" is the key word.

Solution 2 - Postgresql

As a previous answer points out, the trick is to convert the interval to an "epoch", that is, an absolute number of seconds, and then divide appropriately for absolute numbers of other units.

Sone years ago, I wrote an interval_convert function which generalises this to most of the arguments accepted by date_part, assuming that a month is 30 days, and a year is 365.25 days.

Feel free to use and modify as you see fit:

CREATE FUNCTION 
	interval_convert(in_unit text, in_interval interval) 
	RETURNS double precision
AS $FUNC$
	SELECT
		EXTRACT(
			EPOCH FROM
			$2 -- in_interval 
		)
		/
		-- Slightly lazy way of allowing both singular and plural
		--	has side effect that 'centurie' and 'centurys' are accepted
		--	but otherwise behaves similarly to DATE_TRUNC
		CASE TRIM(TRAILING 's' FROM LOWER(
			$1 -- in_unit
		))
			WHEN 'microsecond'  THEN 0.000001 
			WHEN 'millisecond'  THEN 0.001
			WHEN 'second'       THEN 1
			WHEN 'minute'       THEN 60
			WHEN 'hour'         THEN 3600
			WHEN 'day'          THEN 86400
			WHEN 'week'         THEN 604800
			WHEN 'month'        THEN 2592000 -- 30 days
			-- WHEN 'quarter'      THEN -- Not supported
			WHEN 'year'         THEN 31557600 -- 365.35 days
			WHEN 'decade'       THEN 315576000
			WHEN 'century'      THEN 3155760000
			WHEN 'centurie'     THEN 3155760000
			WHEN 'millennium'   THEN 31557600000
			WHEN 'millennia'    THEN 31557600000
		END
$FUNC$
	LANGUAGE sql 
	IMMUTABLE 
	RETURNS NULL ON NULL INPUT;

Solution 3 - Postgresql

I don't actually think you can without doing a bunch of weirdness (like to_char) because minutes roll over at 59. Which is why you get:

postgres=# select date_part('minutes', '65 minutes'::interval);
 date_part 
-----------
         5
(1 row)

postgres=# select '65 minutes'::interval
postgres-# ;
 interval 
----------
 01:05:00
(1 row)

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
QuestionKonrad GarusView Question on Stackoverflow
Solution 1 - PostgresqlMilen A. RadevView Answer on Stackoverflow
Solution 2 - PostgresqlIMSoPView Answer on Stackoverflow
Solution 3 - PostgresqlJoshua D. DrakeView Answer on Stackoverflow