diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index f4aceed0aa3fad85b14e3e7c90e6142586318c14..ab0a3b4e89e27143d11081d424c957d3aa0d6fa3 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.169 2006/07/25 03:51:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.170 2006/09/04 01:26:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2920,16 +2920,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
 						tm->tm_mday += val * 7;
 						if (fval != 0)
 						{
-							int			sec;
-
-							fval *= 7 * SECS_PER_DAY;
-							sec = fval;
-							tm->tm_sec += sec;
+							int extra_days;
+							fval *= 7;
+							extra_days = (int32) fval;
+							tm->tm_mday += extra_days;
+							fval -= extra_days;
+							if (fval != 0)
+							{
+								int			sec;
+								fval *= SECS_PER_DAY;
+								sec = fval;
+								tm->tm_sec += sec;
 #ifdef HAVE_INT64_TIMESTAMP
-							*fsec += (fval - sec) * 1000000;
+								*fsec += (fval - sec) * 1000000;
 #else
-							*fsec += fval - sec;
+								*fsec += fval - sec;
 #endif
+							}
 						}
 						tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
 						break;
@@ -2938,16 +2945,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
 						tm->tm_mon += val;
 						if (fval != 0)
 						{
-							int			sec;
-
-							fval *= DAYS_PER_MONTH * SECS_PER_DAY;
-							sec = fval;
-							tm->tm_sec += sec;
+							int         day;
+							fval *= DAYS_PER_MONTH;
+							day = fval;
+							tm->tm_mday += day;
+							fval -= day;
+							if (fval != 0)
+							{
+								int			sec;
+								fval *= SECS_PER_DAY;
+								sec = fval;
+								tm->tm_sec += sec;
 #ifdef HAVE_INT64_TIMESTAMP
-							*fsec += (fval - sec) * 1000000;
+								*fsec += (fval - sec) * 1000000;
 #else
-							*fsec += fval - sec;
+								*fsec += fval - sec;
 #endif
+							}
 						}
 						tmask = DTK_M(MONTH);
 						break;
diff --git a/src/interfaces/ecpg/pgtypeslib/interval.c b/src/interfaces/ecpg/pgtypeslib/interval.c
index b6d9b19b645d6b355542f0d035867f21e629b819..22643dbd966d114cea02c2c42a163ef60ed8debd 100644
--- a/src/interfaces/ecpg/pgtypeslib/interval.c
+++ b/src/interfaces/ecpg/pgtypeslib/interval.c
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.32 2006/06/06 11:31:55 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.33 2006/09/04 01:26:28 tgl Exp $ */
 
 #include "postgres_fe.h"
 #include <time.h>
@@ -307,16 +307,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fse
 						tm->tm_mday += val * 7;
 						if (fval != 0)
 						{
-							int			sec;
-
-							fval *= 7 * SECS_PER_DAY;
-							sec = fval;
-							tm->tm_sec += sec;
+							int extra_days;
+							fval *= 7;
+							extra_days = (int32) fval;
+							tm->tm_mday += extra_days;
+							fval -= extra_days;
+							if (fval != 0)
+							{
+								int			sec;
+								fval *= SECS_PER_DAY;
+								sec = fval;
+								tm->tm_sec += sec;
 #ifdef HAVE_INT64_TIMESTAMP
-							*fsec += (fval - sec) * 1000000;
+								*fsec += (fval - sec) * 1000000;
 #else
-							*fsec += fval - sec;
+								*fsec += fval - sec;
 #endif
+							}
 						}
 						tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);
 						break;
@@ -325,16 +332,23 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fse
 						tm->tm_mon += val;
 						if (fval != 0)
 						{
-							int			sec;
-
-							fval *= DAYS_PER_MONTH * SECS_PER_DAY;
-							sec = fval;
-							tm->tm_sec += sec;
+							int         day;
+							fval *= DAYS_PER_MONTH;
+							day = fval;
+							tm->tm_mday += day;
+							fval -= day;
+							if (fval != 0)
+							{
+								int			sec;
+								fval *= SECS_PER_DAY;
+								sec = fval;
+								tm->tm_sec += sec;
 #ifdef HAVE_INT64_TIMESTAMP
-							*fsec += (fval - sec) * 1000000;
+								*fsec += (fval - sec) * 1000000;
 #else
-							*fsec += fval - sec;
+								*fsec += fval - sec;
 #endif
+							}
 						}
 						tmask = DTK_M(MONTH);
 						break;
diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out
index 0adda4a981d26e5f05fb01183a1b9dab960d361d..3a5fb12cbc317e8039cdf78f67c6a9518048300f 100644
--- a/src/test/regress/expected/interval.out
+++ b/src/test/regress/expected/interval.out
@@ -39,6 +39,18 @@ SELECT INTERVAL '-1 days +02:03' AS "22 hours ago...";
  -1 days +02:03:00
 (1 row)
 
+SELECT INTERVAL '1.5 weeks' AS "Ten days twelve hours";
+ Ten days twelve hours 
+-----------------------
+ 10 days 12:00:00
+(1 row)
+
+SELECT INTERVAL '1.5 months' AS "One month 15 days";
+ One month 15 days 
+-------------------
+ 1 mon 15 days
+(1 row)
+
 SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years...";
             9 years...            
 ----------------------------------
diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql
index bc384d012120441a155b6b8c4363e89849a3f50d..f38b01e45dc00a6d12c63a9eb1cd0b1dfbce80c8 100644
--- a/src/test/regress/sql/interval.sql
+++ b/src/test/regress/sql/interval.sql
@@ -11,6 +11,8 @@ SELECT INTERVAL '-08:00' AS "Eight hours";
 SELECT INTERVAL '-05' AS "Five hours";
 SELECT INTERVAL '-1 +02:03' AS "22 hours ago...";
 SELECT INTERVAL '-1 days +02:03' AS "22 hours ago...";
+SELECT INTERVAL '1.5 weeks' AS "Ten days twelve hours";
+SELECT INTERVAL '1.5 months' AS "One month 15 days";
 SELECT INTERVAL '10 years -11 month -12 days +13:14' AS "9 years...";
 
 CREATE TABLE INTERVAL_TBL (f1 interval);