diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 48caaa2994ffcb26a6e24b340ff6e909f57772c8..0d4819e8094f709ddb77ef46873e114c1d052968 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.160 2005/10/02 23:50:06 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.161 2005/10/14 11:47:56 momjian Exp $
 -->
 
  <chapter id="datatype">
@@ -1368,7 +1368,7 @@ SELECT b, char_length(b) FROM test2;
         <entry>8 bytes</entry>
         <entry>times of day only</entry>
         <entry>00:00:00.00</entry>
-        <entry>23:59:59.99</entry>
+        <entry>24:00:00</entry>
         <entry>1 microsecond / 14 digits</entry>
        </row>
        <row>
@@ -1376,7 +1376,7 @@ SELECT b, char_length(b) FROM test2;
         <entry>12 bytes</entry>
         <entry>times of day only, with time zone</entry>
         <entry>00:00:00.00+12</entry>
-        <entry>23:59:59.99-12</entry>
+        <entry>24:00:00-12</entry>
         <entry>1 microsecond / 14 digits</entry>
        </row>
       </tbody>
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 74dda5441f1684b896e00fad03fd5456551ebce5..faacdb2eba47840db863964d0a502355caf94eb8 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.158 2005/10/09 17:21:46 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.159 2005/10/14 11:47:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1114,7 +1114,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
 				 * Check upper limit on hours; other limits checked in
 				 * DecodeTime()
 				 */
-				if (tm->tm_hour > 23)
+				/* test for > 24:00:00 */
+				if  (tm->tm_hour > 24 ||
+					 (tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)))
 					return DTERR_FIELD_OVERFLOW;
 				break;
 
@@ -2243,14 +2245,16 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
 	else if (mer == PM && tm->tm_hour != 12)
 		tm->tm_hour += 12;
 
+	if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
+		tm->tm_sec < 0 || tm->tm_sec > 60 || tm->tm_hour > 24 ||
+		/* test for > 24:00:00 */
+	    (tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0 ||
 #ifdef HAVE_INT64_TIMESTAMP
-	if (tm->tm_hour < 0 || tm->tm_hour > 23 || tm->tm_min < 0 ||
-		tm->tm_min > 59 || tm->tm_sec < 0 || tm->tm_sec > 60 ||
+		*fsec > INT64CONST(0))) ||
 		*fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
 		return DTERR_FIELD_OVERFLOW;
 #else
-	if (tm->tm_hour < 0 || tm->tm_hour > 23 || tm->tm_min < 0 ||
-		tm->tm_min > 59 || tm->tm_sec < 0 || tm->tm_sec > 60 ||
+		*fsec > 0)) ||
 		*fsec < 0 || *fsec >= 1)
 		return DTERR_FIELD_OVERFLOW;
 #endif
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index d097b51e8bfecf7d2338a65fb7c02b7314cbc7e4..148ee0abb1c428b940f9ec19341819603918cd17 100644
--- a/src/backend/utils/adt/nabstime.c
+++ b/src/backend/utils/adt/nabstime.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.143 2005/09/24 22:54:38 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.144 2005/10/14 11:47:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -184,12 +184,14 @@ tm2abstime(struct pg_tm *tm, int tz)
 	AbsoluteTime sec;
 
 	/* validate, before going out of range on some members */
-	if (tm->tm_year < 1901 || tm->tm_year > 2038
-		|| tm->tm_mon < 1 || tm->tm_mon > 12
-		|| tm->tm_mday < 1 || tm->tm_mday > 31
-		|| tm->tm_hour < 0 || tm->tm_hour > 23
-		|| tm->tm_min < 0 || tm->tm_min > 59
-		|| tm->tm_sec < 0 || tm->tm_sec > 60)
+	if (tm->tm_year < 1901 || tm->tm_year > 2038 ||
+		tm->tm_mon < 1 || tm->tm_mon > 12 ||
+		tm->tm_mday < 1 || tm->tm_mday > 31 ||
+		tm->tm_hour < 0 ||
+		tm->tm_hour > 24 ||	/* test for > 24:00:00 */
+		(tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)) ||
+		tm->tm_min < 0 || tm->tm_min > 59 ||
+		tm->tm_sec < 0 || tm->tm_sec > 60)
 		return INVALID_ABSTIME;
 
 	day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE;
diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c
index 305f192a7bdc6094f6acb1699b57903b70533e77..b5939c243ec66fe9547ae1b1648985ff8dbf407c 100644
--- a/src/interfaces/ecpg/pgtypeslib/dt_common.c
+++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c
@@ -2095,7 +2095,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
 				 * Check upper limit on hours; other limits checked in
 				 * DecodeTime()
 				 */
-				if (tm->tm_hour > 23)
+				/* test for > 24:00:00 */
+				if  (tm->tm_hour > 24 ||
+					 (tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)))
 					return -1;
 				break;
 
@@ -3161,7 +3163,8 @@ PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp *d,
 			err = 1;
 			*minute = 0;
 		}
-		if (*hour > 23)
+		if (*hour > 24 ||	/* test for > 24:00:00 */
+			(*hour == 24 && (*minute > 0 || *second > 0)))
 		{
 			err = 1;
 			*hour = 0;