You can use various datetime expressions or a user-defined DATEDIFF function (UDF) to calculate the difference between 2 datetime values in seconds, minutes, hours, days, weeks, months and years in PostgreSQL.
PostgreSQL does not provide DATEDIFF function similar to SQL Server DATEDIFF, but you can use various expressions or UDF to get the same results.
SQL Server and Sybase | PostgreSQL | |
Years | DATEDIFF(yy, start, end) | DATE_PART('year', end) - DATE_PART('year', start) |
Months | DATEDIFF(mm, start, end) | years_diff * 12 + (DATE_PART('month', end) - DATE_PART('month', start)) |
Days | DATEDIFF(dd, start, end) | DATE_PART('day', end - start) |
Weeks | DATEDIFF(wk, start, end) | TRUNC(DATE_PART('day', end - start)/7) |
Hours | DATEDIFF(hh, start, end) | days_diff * 24 + DATE_PART('hour', end - start ) |
Minutes | DATEDIFF(mi, start, end) | hours_diff * 60 + DATE_PART('minute', end - start ) |
Seconds | DATEDIFF(ss, start, end) | minutes_diff * 60 + DATE_PART('minute', end - start ) |
Consider SQL Server function to calculate the difference between 2 dates in years:
SQL Server:
-- Difference between Oct 02, 2011 and Jan 01, 2012 in years SELECT DATEDIFF(year, '2011-10-02', '2012-01-01'); -- Result: 1
Note that SQL Server DATEDIFF function returned 1 year although there are only 3 months between dates.
SQL Server does not count full years passed between the dates, it calculates the difference between the year parts only.
In PostgreSQL, you can get the year parts from the dates and subtract them.
PostgreSQL:
-- Difference between Oct 02, 2011 and Jan 01, 2012 in years SELECT DATE_PART('year', '2012-01-01'::date) - DATE_PART('year', '2011-10-02'::date); -- Result: 1
Consider SQL Server function to calculate the difference between 2 dates in months:
SQL Server:
-- Difference between Oct 02, 2011 and Jan 01, 2012 in months SELECT DATEDIFF(month, '2011-10-02', '2012-01-01'); -- Result: 3
In PostgreSQL, you can take the difference in years, multiply by 12 and add the difference between month parts that can be negative.
PostgreSQL:
-- Difference between Oct 02, 2011 and Jan 01, 2012 in months SELECT (DATE_PART('year', '2012-01-01'::date) - DATE_PART('year', '2011-10-02'::date)) * 12 + (DATE_PART('month', '2012-01-01'::date) - DATE_PART('month', '2011-10-02'::date)); -- Result: 3
Consider SQL Server function to calculate the difference between 2 dates in days:
SQL Server:
-- Difference between Dec 29, 2011 23:00 and Dec 31, 2011 01:00 in days SELECT DATEDIFF(day, '2011-12-29 23:00:00', '2011-12-31 01:00:00'); -- Result: 2
Note that DATEDIFF returned 2 days, although there is only 1 day and 2 hours between the datetime values.
In PostgreSQL, if you subtract one datetime value (TIMESTAMP, DATE or TIME data type) from another, you will get an INTERVAL value in the form ”ddd days hh:mi:ss”.
SELECT '2011-12-31 01:00:00'::timestamp - '2011-12-29 23:00:00'::timestamp; -- Result: "1 day 02:00:00" SELECT '2011-12-31 01:00:00'::timestamp - '2010-09-17 23:00:00'::timestamp; -- Result: "469 days 02:00:00"
So you can use DATE_PART function to extact the number of days, but it returns the number of full days between the dates.
PostgreSQL:
-- Difference between Dec 29, 2011 23:00 and Dec 31, 2011 01:00 in days SELECT DATE_PART('day', '2011-12-31 01:00:00'::timestamp - '2011-12-29 23:00:00'::timestamp); -- Result: 1
Consider SQL Server function to calculate the difference between 2 dates in weeks:
SQL Server:
-- Difference between Dec 22, 2011 and Dec 31, 2011 in weeks SELECT DATEDIFF(week, '2011-12-22', '2011-12-31'); -- Result: 1
DATEDIFF returnes the number of full weeks between the datetime values.
In PostgreSQL, you can use an expression to define the number of days (see above) and divide it by 7. TRUNC is required to remove the decimal part after the division.
PostgreSQL:
-- Difference between Dec 22, 2011 and Dec 31, 2011 in weeks SELECT TRUNC(DATE_PART('day', '2011-12-31'::timestamp - '2011-12-22'::timestamp)/7); -- Result: 1
Consider SQL Server function to calculate the difference between 2 datetime value in hours:
SQL Server:
-- Difference between Dec 30, 2011 08:55 and Dec 30, 2011 9:05 in weeks SELECT DATEDIFF(hour, '2011-12-30 08:55', '2011-12-30 09:05'); -- Result: 1
Note that DATEDIFF returned 1 hour although there is just 10 minutes difference between the datetime values.
In PostgreSQL, you can use an expression to define the number of days (see above), multiple by 24 and add the difference is hours.
PostgreSQL:
-- Difference between Dec 30, 2011 08:55 and Dec 30, 2011 9:05 in weeks SELECT DATE_PART('day', '2011-12-30 08:55'::timestamp - '2011-12-30 09:05'::timestamp) * 24 + DATE_PART('hour', '2011-12-30 08:55'::timestamp - '2011-12-30 09:05'::timestamp); -- Result: 0
Note that this PostreSQL expression returns the number of full hours passed between the datetime values.
Consider SQL Server function to calculate the difference between 2 datetime values in minutes:
SQL Server:
-- Difference between Dec 30, 2011 08:54:55 and Dec 30, 2011 08:56:10 in minutes SELECT DATEDIFF(minute, '2011-12-30 08:54:55', '2011-12-30 08:56:10'); -- Result: 2 -- Time only SELECT DATEDIFF(minute, '08:54:55', '08:56:10'); -- Result: 2
Note that DATEDIFF returned 2 minutes although there is just 1 minute and 15 seconds between the datetime values.
In PostgreSQL, you can use an expression to define the number of hours (see above), multiple by 60 and add the difference is minutes.
PostgreSQL:
-- Difference between Dec 30, 2011 08:54:55 and Dec 30, 2011 08:56:10 in minutes SELECT (DATE_PART('day', '2011-12-30 08:56:10'::timestamp - '2011-12-30 08:54:55'::timestamp) * 24 + DATE_PART('hour', '2011-12-30 08:56:10'::timestamp - '2011-12-30 08:54:55'::timestamp)) * 60 + DATE_PART('minute', '2011-12-30 08:56:10'::timestamp - '2011-12-30 08:54:55'::timestamp); -- Result: 1 -- Time only SELECT DATE_PART('hour', '08:56:10'::time - '08:54:55'::time) * 60 + DATE_PART('minute', '08:56:10'::time - '08:54:55'::time); -- Result: 1
Note that these PostreSQL expressions return the number of full minutes passed between the datetime values.
Consider SQL Server function to calculate the difference between 2 datetime values in seconds:
SQL Server:
-- Difference between Dec 30, 2011 08:54:55 and Dec 30, 2011 08:56:10 in seconds SELECT DATEDIFF(second, '2011-12-30 08:54:55', '2011-12-30 08:56:10'); -- Result: 75 -- Time only SELECT DATEDIFF(second, '08:54:55', '08:56:10'); -- Result: 75
In PostgreSQL, you can use an expression to define the number of minutes (see above), multiple by 60 and add the difference is seconds.
PostgreSQL:
-- Difference between Dec 30, 2011 08:54:55 and Dec 30, 2011 08:56:10 in seconds SELECT ((DATE_PART('day', '2011-12-30 08:56:10'::timestamp - '2011-12-30 08:54:55'::timestamp) * 24 + DATE_PART('hour', '2011-12-30 08:56:10'::timestamp - '2011-12-30 08:54:55'::timestamp)) * 60 + DATE_PART('minute', '2011-12-30 08:56:10'::timestamp - '2011-12-30 08:54:55'::timestamp)) * 60 + DATE_PART('second', '2011-12-30 08:56:10'::timestamp - '2011-12-30 08:54:55'::timestamp); -- Result: 75 -- Time only SELECT (DATE_PART('hour', '08:56:10'::time - '08:54:55'::time) * 60 + DATE_PART('minute', '08:56:10'::time - '08:54:55'::time)) * 60 + DATE_PART('second', '08:56:10'::time - '08:54:55'::time); -- Result: 75
Besides a separate expression to calculate the datetime difference for each time unit, you can use a function similar to SQL Server DATEDIFF function.
PostgreSQL:
CREATE OR REPLACE FUNCTION DateDiff (units VARCHAR(30), start_t TIMESTAMP, end_t TIMESTAMP) RETURNS INT AS $$ DECLARE diff_interval INTERVAL; diff INT = 0; years_diff INT = 0; BEGIN IF units IN ('yy', 'yyyy', 'year', 'mm', 'm', 'month') THEN years_diff = DATE_PART('year', end_t) - DATE_PART('year', start_t); IF units IN ('yy', 'yyyy', 'year') THEN -- SQL Server does not count full years passed (only difference between year parts) RETURN years_diff; ELSE -- If end month is less than start month it will subtracted RETURN years_diff * 12 + (DATE_PART('month', end_t) - DATE_PART('month', start_t)); END IF; END IF; -- Minus operator returns interval 'DDD days HH:MI:SS' diff_interval = end_t - start_t; diff = diff + DATE_PART('day', diff_interval); IF units IN ('wk', 'ww', 'week') THEN diff = diff/7; RETURN diff; END IF; IF units IN ('dd', 'd', 'day') THEN RETURN diff; END IF; diff = diff * 24 + DATE_PART('hour', diff_interval); IF units IN ('hh', 'hour') THEN RETURN diff; END IF; diff = diff * 60 + DATE_PART('minute', diff_interval); IF units IN ('mi', 'n', 'minute') THEN RETURN diff; END IF; diff = diff * 60 + DATE_PART('second', diff_interval); RETURN diff; END; $$ LANGUAGE plpgsql;
The syntax is similar to SQL Server DATEDIFF, but you have to specify a time unit (second, minute etc. and their abbreviations) as a string literal in PostgreSQL, for example:
-- Difference between Dec 30, 2011 08:54:55 and Dec 30, 2011 08:56:10 in seconds SELECT DATEDIFF('second', '2011-12-30 08:54:55'::timestamp, '2011-12-30 08:56:10'::timestamp); -- Result: 75
You can have another function that operates on time data types only. PostgreSQL supports overloaded functions having the same name, but different data types of parameters:
CREATE OR REPLACE FUNCTION DateDiff (units VARCHAR(30), start_t TIME, end_t TIME) RETURNS INT AS $$ DECLARE diff_interval INTERVAL; diff INT = 0; BEGIN -- Minus operator for TIME returns interval 'HH:MI:SS' diff_interval = end_t - start_t; diff = DATE_PART('hour', diff_interval); IF units IN ('hh', 'hour') THEN RETURN diff; END IF; diff = diff * 60 + DATE_PART('minute', diff_interval); IF units IN ('mi', 'n', 'minute') THEN RETURN diff; END IF; diff = diff * 60 + DATE_PART('second', diff_interval); RETURN diff; END; $$ LANGUAGE plpgsql;
For example, you can call this function as:
-- Difference between 08:54:55 and 08:56:10 in seconds SELECT DATEDIFF('second', '08:54:55'::time, '08:56:10'::time); -- Result: 75
For more information, see SQL Server to PostgreSQL Migration.
Discussion
THANKS Ilove youuu hahahahahahahah really thanks
Function date_part(text, interval) return type double precision, when input parameter will contain, timestamp type with millisecond, function datediff('ss',timestamp,timestamp) return error (diff INT = 0;)