From 78aef14c5935bca92d0cacaa9d188f588d7f2444 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 29 Jul 2009 22:19:18 +0000
Subject: [PATCH] Fix time_part and timetz_part (ie, EXTRACT() for those
 datatypes) to include a fractional part in the output for MILLISECOND and
 SECOND cases, rather than truncating the source value.  This is what the
 float-timestamp code has always done, and it was clearly the code author's
 intent to do the same for integer timestamps, but he forgot about integer
 division in C. The other datatypes supported by EXTRACT() already do this
 correctly.

Backpatch to 8.4, so that the default (integer) behavior of that branch will
match the default (float) behavior of older branches.  Arguably we should
patch further back, but it's possible that applications are expecting the
broken behavior in older branches.  8.4 is new enough that expectations
shouldn't be too settled.

Per report from Greg Stark.
---
 src/backend/utils/adt/date.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 43148bec90d..85450e12cdb 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.146 2009/06/11 14:49:03 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.147 2009/07/29 22:19:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1701,7 +1701,7 @@ time_part(PG_FUNCTION_ARGS)
 		{
 			case DTK_MICROSEC:
 #ifdef HAVE_INT64_TIMESTAMP
-				result = tm->tm_sec * USECS_PER_SEC + fsec;
+				result = tm->tm_sec * 1000000.0 + fsec;
 #else
 				result = (tm->tm_sec + fsec) * 1000000;
 #endif
@@ -1709,7 +1709,7 @@ time_part(PG_FUNCTION_ARGS)
 
 			case DTK_MILLISEC:
 #ifdef HAVE_INT64_TIMESTAMP
-				result = tm->tm_sec * INT64CONST(1000) + fsec / INT64CONST(1000);
+				result = tm->tm_sec * 1000.0 + fsec / 1000.0;
 #else
 				result = (tm->tm_sec + fsec) * 1000;
 #endif
@@ -1717,7 +1717,7 @@ time_part(PG_FUNCTION_ARGS)
 
 			case DTK_SECOND:
 #ifdef HAVE_INT64_TIMESTAMP
-				result = tm->tm_sec + fsec / USECS_PER_SEC;
+				result = tm->tm_sec + fsec / 1000000.0;
 #else
 				result = tm->tm_sec + fsec;
 #endif
@@ -2469,7 +2469,7 @@ timetz_part(PG_FUNCTION_ARGS)
 
 			case DTK_MICROSEC:
 #ifdef HAVE_INT64_TIMESTAMP
-				result = tm->tm_sec * USECS_PER_SEC + fsec;
+				result = tm->tm_sec * 1000000.0 + fsec;
 #else
 				result = (tm->tm_sec + fsec) * 1000000;
 #endif
@@ -2477,7 +2477,7 @@ timetz_part(PG_FUNCTION_ARGS)
 
 			case DTK_MILLISEC:
 #ifdef HAVE_INT64_TIMESTAMP
-				result = tm->tm_sec * INT64CONST(1000) + fsec / INT64CONST(1000);
+				result = tm->tm_sec * 1000.0 + fsec / 1000.0;
 #else
 				result = (tm->tm_sec + fsec) * 1000;
 #endif
@@ -2485,7 +2485,7 @@ timetz_part(PG_FUNCTION_ARGS)
 
 			case DTK_SECOND:
 #ifdef HAVE_INT64_TIMESTAMP
-				result = tm->tm_sec + fsec / USECS_PER_SEC;
+				result = tm->tm_sec + fsec / 1000000.0;
 #else
 				result = tm->tm_sec + fsec;
 #endif
-- 
GitLab