Thread: BUG #7722: extract(epoch from age(...)) appears to be broken
The following bug has been logged on the website: Bug reference: 7722 Logged by: Artem Anisimov Email address: aanisimov@inbox.ru PostgreSQL version: 9.2.1 Operating system: Slackware Linux 14.0/amd64 Description: = The following to queries give the same result (first arguments to age() differ in the day number only, second arguments are identical): select extract(epoch from age('2012-11-23 16:41:31', '2012-10-23 15:56:10')); and select extract(epoch from age('2012-11-22 16:41:31', '2012-10-23 15:56:10')); The problem can also be reproduced in pgsql 9.1.4 of Fedora 17.
aanisimov@inbox.ru wrote: > The following bug has been logged on the website: >=20 > Bug reference: 7722 > Logged by: Artem Anisimov > Email address: aanisimov@inbox.ru > PostgreSQL version: 9.2.1 > Operating system: Slackware Linux 14.0/amd64 > Description: =20 >=20 > The following to queries give the same result (first arguments to age() > differ in the day number only, second arguments are identical): >=20 > select extract(epoch from age('2012-11-23 16:41:31', '2012-10-23 > 15:56:10')); >=20 > and >=20 > select extract(epoch from age('2012-11-22 16:41:31', '2012-10-23 > 15:56:10')); alvherre=3D# select age('2012-11-22 16:41:31', '2012-10-23 15:56:10'); age =20 ------------------ 30 days 00:45:21 (1 fila) alvherre=3D# select age('2012-11-23 16:41:31', '2012-10-23 15:56:10'); age =20 ---------------- 1 mon 00:45:21 (1 fila) The problem is that age() returns 30 days in one case, and "one month" in= the other; extract() then considers the month as equivalent to 30 days. This= is documented as such, see [1]. [1] http://www.postgresql.org/docs/current/static/functions-datetime.html I think if you want a precise computation you should just subtract the tw= o dates and then extract epoch from the result. alvherre=3D# select extract(epoch from timestamp '2012-11-22 16:41:31' - = '2012-10-23 15:56:10'); date_part=20 ----------- 2594721 (1 fila) alvherre=3D# select extract(epoch from timestamp '2012-11-23 16:41:31' - = '2012-10-23 15:56:10'); date_part=20 ----------- 2681121 (1 fila) --=20 =C1lvaro Herrera http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
On Mon, Dec 3, 2012 at 03:05:57AM -0300, Alvaro Herrera wrote: > aanisimov@inbox.ru wrote: > > The following bug has been logged on the website: > > > > Bug reference: 7722 > > Logged by: Artem Anisimov > > Email address: aanisimov@inbox.ru > > PostgreSQL version: 9.2.1 > > Operating system: Slackware Linux 14.0/amd64 > > Description: > > > > The following to queries give the same result (first arguments to age() > > differ in the day number only, second arguments are identical): > > > > select extract(epoch from age('2012-11-23 16:41:31', '2012-10-23 > > 15:56:10')); > > > > and > > > > select extract(epoch from age('2012-11-22 16:41:31', '2012-10-23 > > 15:56:10')); > > alvherre=# select age('2012-11-22 16:41:31', '2012-10-23 15:56:10'); > age > ------------------ > 30 days 00:45:21 > (1 fila) > > alvherre=# select age('2012-11-23 16:41:31', '2012-10-23 15:56:10'); > age > ---------------- > 1 mon 00:45:21 > (1 fila) > > The problem is that age() returns 30 days in one case, and "one month" in the > other; extract() then considers the month as equivalent to 30 days. This is > documented as such, see [1]. > > [1] http://www.postgresql.org/docs/current/static/functions-datetime.html Wow, that is a weird case. In the first test, we count the number of days because it is less than a full month. In the second case, we call it a full month, but then forget how long it is. Not sure how we could improve this. -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + It's impossible for everything to be true. +
> Wow, that is a weird case. In the first test, we count the number of > days because it is less than a full month. In the second case, we call > it a full month, but then forget how long it is. Not sure how we could > improve this. I do not think this needs to be improved, the problem is given two dates you can substract them in three different ways, 1.- (year months)+(days)+(hours minutes seconds), which is what age does and is documented as such. folarte=# select age('2013-11-24 16:41:31','2012-10-23 15:56:10'); age ----------------------------- 1 year 1 mon 1 day 00:45:21 (1 row) Which is apropiate for things like 'I'm xxx old' 2.- (days)+(hours-minutes-seconds), which is what substractint dates do ( or seems to do for me, as I've done: select timestamp '2013-11-23 16:41:31' - '2012-10-23 15:56:10'; ?column? ------------------- 396 days 00:45:21 Which I can not find a use for, but there sure are and I'm doomed to find one soon. 3.- Exact duration ( I do this a lot at work as I need to calculate call durations ): folarte=# select extract(epoch from timestamp '2013-11-23 16:41:31') - extract(epoch from timestamp '2012-10-23 15:56:10'); ?column? ---------- 34217121 (1 row) folarte=# select (extract(epoch from timestamp '2013-11-23 16:41:31') - extract(epoch from timestamp '2012-10-23 15:56:10')) * interval '1 second'; ?column? ------------ 9504:45:21 (1 row) The problem I see is intervals are really complicated and difficult to undestand, so it is at most a documentation problem ( people usually understimate the difficulty of working with them, I see this a lot at work ). Francisco Olarte.
Dear Mr. Herrera and Mr. Momjian, thank you for your feedback and for explaining that age() better not be used. On Monday 03 December 2012 03:05:57 Alvaro Herrera wrote: > The problem is that age() returns 30 days in one case, and "one month" in > the other; extract() then considers the month as equivalent to 30 days. > This is documented as such, see [1]. On Monday 03 December 2012 21:17:00 Bruce Momjian wrote: > Wow, that is a weird case. In the first test, we count the number of > days because it is less than a full month. In the second case, we call > it a full month, but then forget how long it is. Not sure how we could > improve this. Best regargs, Artem Anisimov.