diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 332db7e..61555ae 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -160,6 +160,7 @@ date_in(PG_FUNCTION_ARGS)
 			break;
 	}
 
+	/* IS_VALID_JULIAN is enough for checking; IS_VALID_DATE is redundant */
 	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
 		ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
@@ -209,8 +210,7 @@ date_recv(PG_FUNCTION_ARGS)
 	/* Limit to the same range that date_in() accepts. */
 	if (DATE_NOT_FINITE(result))
 		 /* ok */ ;
-	else if (result < -POSTGRES_EPOCH_JDATE ||
-			 result >= JULIAN_MAX - POSTGRES_EPOCH_JDATE)
+	else if (!IS_VALID_DATE(result))
 		ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("date out of range")));
@@ -258,6 +258,7 @@ make_date(PG_FUNCTION_ARGS)
 				 errmsg("date field value out of range: %d-%02d-%02d",
 						tm.tm_year, tm.tm_mon, tm.tm_mday)));
 
+	/* IS_VALID_JULIAN is enough for checking; IS_VALID_DATE is redundant */
 	if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
 		ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
@@ -429,9 +430,16 @@ date_pli(PG_FUNCTION_ARGS)
 	int32		days = PG_GETARG_INT32(1);
 
 	if (DATE_NOT_FINITE(dateVal))
-		days = 0;				/* can't change infinity */
+		PG_RETURN_DATEADT(dateVal);    /* can't change infinity */
 
-	PG_RETURN_DATEADT(dateVal + days);
+	dateVal += days;
+
+	if (!IS_VALID_DATE(dateVal))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("date out of range")));
+
+	PG_RETURN_DATEADT(dateVal);
 }
 
 /* Subtract a number of days from a date, giving a new date.
@@ -443,9 +451,16 @@ date_mii(PG_FUNCTION_ARGS)
 	int32		days = PG_GETARG_INT32(1);
 
 	if (DATE_NOT_FINITE(dateVal))
-		days = 0;				/* can't change infinity */
+		PG_RETURN_DATEADT(dateVal);    /* can't change infinity */
 
-	PG_RETURN_DATEADT(dateVal - days);
+	dateVal -= days;
+
+	if (!IS_VALID_DATE(dateVal))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("date out of range")));
+
+	PG_RETURN_DATEADT(dateVal);
 }
 
 /*
@@ -464,14 +479,18 @@ date2timestamp(DateADT dateVal)
 		TIMESTAMP_NOEND(result);
 	else
 	{
-#ifdef HAVE_INT64_TIMESTAMP
-		/* date is days since 2000, timestamp is microseconds since same... */
-		result = dateVal * USECS_PER_DAY;
-		/* Date's range is wider than timestamp's, so check for overflow */
-		if (result / USECS_PER_DAY != dateVal)
+		/*
+		 * Date's range is wider than timestamp's, so check for boundaries.
+		 * Since dates have the same miminum values as timestamps,
+		 * only upper boundary is to be checked for overflow.
+		 */
+		if (dateVal >= (JULIAN_MAX4STAMPS - POSTGRES_EPOCH_JDATE))
 			ereport(ERROR,
 					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 					 errmsg("date out of range for timestamp")));
+#ifdef HAVE_INT64_TIMESTAMP
+		/* date is days since 2000, timestamp is microseconds since same... */
+		result = dateVal * USECS_PER_DAY;
 #else
 		/* date is days since 2000, timestamp is seconds since same... */
 		result = dateVal * (double) SECS_PER_DAY;
@@ -495,6 +514,16 @@ date2timestamptz(DateADT dateVal)
 		TIMESTAMP_NOEND(result);
 	else
 	{
+		/*
+		 * Date's range is wider than timestamp's, so check for boundaries.
+		 * Since dates have the same miminum values as timestamps,
+		 * only upper boundary is to be checked for overflow.
+		 */
+		if (dateVal >= (JULIAN_MAX4STAMPS - POSTGRES_EPOCH_JDATE))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("date out of range for timestamp")));
+
 		j2date(dateVal + POSTGRES_EPOCH_JDATE,
 			   &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
 		tm->tm_hour = 0;
@@ -504,14 +533,17 @@ date2timestamptz(DateADT dateVal)
 
 #ifdef HAVE_INT64_TIMESTAMP
 		result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
-		/* Date's range is wider than timestamp's, so check for overflow */
-		if ((result - tz * USECS_PER_SEC) / USECS_PER_DAY != dateVal)
-			ereport(ERROR,
-					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-					 errmsg("date out of range for timestamp")));
 #else
 		result = dateVal * (double) SECS_PER_DAY + tz;
 #endif
+		/*
+		 * Since it is possible to go beyond allowed timestamptz range because
+		 * of time zone, check for allowed timestamp range after adding tz.
+		 */
+		if (!IS_VALID_TIMESTAMP(result))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("date out of range for timestamp")));
 	}
 
 	return result;
@@ -1053,6 +1085,10 @@ abstime_date(PG_FUNCTION_ARGS)
 
 		default:
 			abstime2tm(abstime, &tz, tm, NULL);
+			if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
+				ereport(ERROR,
+						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+						 errmsg("abstime out of range for date")));
 			result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
 			break;
 	}
@@ -1678,7 +1714,13 @@ datetime_timestamp(PG_FUNCTION_ARGS)
 
 	result = date2timestamp(date);
 	if (!TIMESTAMP_NOT_FINITE(result))
+	{
 		result += time;
+		if (!IS_VALID_TIMESTAMP(result))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("timestamp out of range")));
+	}
 
 	PG_RETURN_TIMESTAMP(result);
 }
@@ -2550,11 +2592,29 @@ datetimetz_timestamptz(PG_FUNCTION_ARGS)
 		TIMESTAMP_NOEND(result);
 	else
 	{
+		/*
+		 * Date's range is wider than timestamp's, so check for boundaries.
+		 * Since dates have the same miminum values as timestamps,
+		 * only upper boundary is to be checked for overflow.
+		 * Also save one day for possible correction by time zone
+		 */
+		if (date >= (JULIAN_MAX4STAMPS - POSTGRES_EPOCH_JDATE + 1))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("date out of range for timestamp")));
 #ifdef HAVE_INT64_TIMESTAMP
 		result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
 #else
 		result = date * (double) SECS_PER_DAY + time->time + time->zone;
 #endif
+		/*
+		 * Since it is possible to go beyond allowed timestamptz range because
+		 * of time zone, check for allowed timestamp range after adding tz.
+		 */
+		if (!IS_VALID_TIMESTAMP(result))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("date out of range for timestamp")));
 	}
 
 	PG_RETURN_TIMESTAMP(result);
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index cdbf72c..0deb6f7 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -1579,7 +1579,7 @@ DetermineTimeZoneOffsetInternal(struct pg_tm * tm, pg_tz *tzp, pg_time_t *tp)
 	 * timezone is GMT.  (For a valid Julian date, integer overflow should be
 	 * impossible with 64-bit pg_time_t, but let's check for safety.)
 	 */
-	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
+	if (!IS_VALID_JULIAN4STAMPS(tm->tm_year, tm->tm_mon, tm->tm_mday))
 		goto overflow;
 	date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE;
 
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 1525d2a..380df6a 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -168,6 +168,11 @@ timestamp_in(PG_FUNCTION_ARGS)
 				ereport(ERROR,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("timestamp out of range: \"%s\"", str)));
+
+			if (!IS_VALID_TIMESTAMP(result))
+				ereport(ERROR,
+						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+						 errmsg("timestamp out of range: \"%s\"", str)));
 			break;
 
 		case DTK_EPOCH:
@@ -261,7 +266,8 @@ timestamp_recv(PG_FUNCTION_ARGS)
 	/* rangecheck: see if timestamp_out would like it */
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		 /* ok */ ;
-	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
+	else if ((timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0) ||
+			 (!IS_VALID_TIMESTAMP(timestamp)))
 		ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
@@ -442,6 +448,11 @@ timestamptz_in(PG_FUNCTION_ARGS)
 				ereport(ERROR,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("timestamp out of range: \"%s\"", str)));
+
+			if (!IS_VALID_TIMESTAMP(result))
+				ereport(ERROR,
+						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+						 errmsg("timestamp out of range: \"%s\"", str)));
 			break;
 
 		case DTK_EPOCH:
@@ -592,7 +603,7 @@ make_timestamp_internal(int year, int month, int day,
 				 errmsg("date field value out of range: %d-%02d-%02d",
 						year, month, day)));
 
-	if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
+	if (!IS_VALID_JULIAN4STAMPS(tm.tm_year, tm.tm_mon, tm.tm_mday))
 		ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("date out of range: %d-%02d-%02d",
@@ -645,6 +656,14 @@ make_timestamp_internal(int year, int month, int day,
 	result = date * SECS_PER_DAY + time;
 #endif
 
+	/* quick test for "YYYY-12-31 24:00:00" (YYYY is maximum allowed year) */
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
+						year, month, day,
+						hour, min, sec)));
+
 	return result;
 }
 
@@ -703,6 +722,7 @@ make_timestamptz_at_timezone(PG_FUNCTION_ARGS)
 	float8		sec = PG_GETARG_FLOAT8(5);
 	text	   *zone = PG_GETARG_TEXT_PP(6);
 	Timestamp	timestamp;
+	TimestampTz	result;
 	struct pg_tm tt;
 	int			tz;
 	fsec_t		fsec;
@@ -717,7 +737,14 @@ make_timestamptz_at_timezone(PG_FUNCTION_ARGS)
 
 	tz = parse_sane_timezone(&tt, zone);
 
-	PG_RETURN_TIMESTAMPTZ((TimestampTz) dt2local(timestamp, -tz));
+	result = dt2local(timestamp, -tz);
+
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range")));
+
+	PG_RETURN_TIMESTAMPTZ(result);
 }
 
 /* timestamptz_out()
@@ -778,7 +805,8 @@ timestamptz_recv(PG_FUNCTION_ARGS)
 	/* rangecheck: see if timestamptz_out would like it */
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		 /* ok */ ;
-	else if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
+	else if ((timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0) ||
+			 (!IS_VALID_TIMESTAMP(timestamp)));
 		ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
@@ -1926,7 +1954,7 @@ tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *result)
 	TimeOffset	time;
 
 	/* Julian day routines are not correct for negative Julian days */
-	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
+	if (!IS_VALID_JULIAN4STAMPS(tm->tm_year, tm->tm_mon, tm->tm_mday))
 	{
 		*result = 0;			/* keep compiler quiet */
 		return -1;
@@ -2982,6 +3010,12 @@ timestamp_pl_interval(PG_FUNCTION_ARGS)
 		}
 
 		timestamp += span->time;
+
+		if (!IS_VALID_TIMESTAMP(timestamp))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("timestamp out of range")));
+
 		result = timestamp;
 	}
 
@@ -3086,6 +3120,12 @@ timestamptz_pl_interval(PG_FUNCTION_ARGS)
 		}
 
 		timestamp += span->time;
+
+		if (!IS_VALID_TIMESTAMP(timestamp))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("timestamp out of range")));
+
 		result = timestamp;
 	}
 
@@ -3876,6 +3916,15 @@ timestamp_trunc(PG_FUNCTION_ARGS)
 		result = 0;
 	}
 
+	/*
+	 * truncating the minimal timestamp (4714-11-24 BC) to year, month
+	 * or even week leads to the result less than the minimum allowed.
+	 */
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range")));
+
 	PG_RETURN_TIMESTAMP(result);
 }
 
@@ -4033,6 +4082,15 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
 		result = 0;
 	}
 
+	/*
+	 * truncating the minimal timestamp (4714-11-24 BC) to year, month
+	 * or even week leads to the result less than the minimum allowed.
+	 */
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range")));
+
 	PG_RETURN_TIMESTAMPTZ(result);
 }
 
@@ -4396,6 +4454,7 @@ timestamp_part(PG_FUNCTION_ARGS)
 {
 	text	   *units = PG_GETARG_TEXT_PP(0);
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(1);
+	Timestamp	epoch;
 	float8		result;
 	int			type,
 				val;
@@ -4575,10 +4634,15 @@ timestamp_part(PG_FUNCTION_ARGS)
 		switch (val)
 		{
 			case DTK_EPOCH:
+				epoch = SetEpochTimestamp();
 #ifdef HAVE_INT64_TIMESTAMP
-				result = (timestamp - SetEpochTimestamp()) / 1000000.0;
+				if (timestamp < (PG_INT64_MAX + epoch))
+					/* save maximal precision before converting to float8 */
+					result = (timestamp - epoch) / 1000000.0;
+				else
+					result = ((float8)timestamp - epoch) / 1000000.0;
 #else
-				result = timestamp - SetEpochTimestamp();
+				result = timestamp - epoch;
 #endif
 				break;
 
@@ -4610,6 +4674,7 @@ timestamptz_part(PG_FUNCTION_ARGS)
 {
 	text	   *units = PG_GETARG_TEXT_PP(0);
 	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
+	Timestamp	epoch;
 	float8		result;
 	int			tz;
 	int			type,
@@ -4792,8 +4857,13 @@ timestamptz_part(PG_FUNCTION_ARGS)
 		switch (val)
 		{
 			case DTK_EPOCH:
+				epoch = SetEpochTimestamp();
 #ifdef HAVE_INT64_TIMESTAMP
-				result = (timestamp - SetEpochTimestamp()) / 1000000.0;
+				if (timestamp < (PG_INT64_MAX + epoch))
+					/* save maximal precision before converting to float8 */
+					result = (timestamp - epoch) / 1000000.0;
+				else
+					result = ((float8)timestamp - epoch) / 1000000.0;
 #else
 				result = timestamp - SetEpochTimestamp();
 #endif
@@ -5120,6 +5190,11 @@ timestamp_zone(PG_FUNCTION_ARGS)
 		}
 	}
 
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range")));
+
 	PG_RETURN_TIMESTAMPTZ(result);
 }
 
@@ -5198,6 +5273,11 @@ timestamp_izone(PG_FUNCTION_ARGS)
 
 	result = dt2local(timestamp, tz);
 
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range")));
+
 	PG_RETURN_TIMESTAMPTZ(result);
 }	/* timestamp_izone() */
 
@@ -5236,6 +5316,11 @@ timestamp2timestamptz(Timestamp timestamp)
 			ereport(ERROR,
 					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 					 errmsg("timestamp out of range")));
+
+		if (!IS_VALID_TIMESTAMP(result))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("timestamp out of range")));
 	}
 
 	return result;
@@ -5266,6 +5351,10 @@ timestamptz_timestamp(PG_FUNCTION_ARGS)
 			ereport(ERROR,
 					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 					 errmsg("timestamp out of range")));
+		if (!IS_VALID_TIMESTAMP(result))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+					 errmsg("timestamp out of range")));
 	}
 	PG_RETURN_TIMESTAMP(result);
 }
@@ -5350,6 +5439,11 @@ timestamptz_zone(PG_FUNCTION_ARGS)
 		}
 	}
 
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range")));
+
 	PG_RETURN_TIMESTAMP(result);
 }
 
@@ -5383,6 +5477,11 @@ timestamptz_izone(PG_FUNCTION_ARGS)
 
 	result = dt2local(timestamp, tz);
 
+	if (!IS_VALID_TIMESTAMP(result))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+				 errmsg("timestamp out of range")));
+
 	PG_RETURN_TIMESTAMP(result);
 }
 
diff --git a/src/include/datatype/timestamp.h b/src/include/datatype/timestamp.h
index 12a2a8a..9b21ba8 100644
--- a/src/include/datatype/timestamp.h
+++ b/src/include/datatype/timestamp.h
@@ -105,6 +105,20 @@ typedef struct
 #define USECS_PER_MINUTE INT64CONST(60000000)
 #define USECS_PER_SEC	INT64CONST(1000000)
 
+#ifdef HAVE_INT64_TIMESTAMP
+#define MIN_TIMESTAMP	INT64CONST(-211813488000000000)
+/* == (0 - POSTGRES_EPOCH_JDATE) * 86400 * USECS_PER_SEC */
+#define MAX_TIMESTAMP	INT64CONST(9223371331200000000)
+/* == (JULIAN_MAX4STAMPS - POSTGRES_EPOCH_JDATE) * 86400 * USECS_PER_SEC */
+#else
+#define MIN_TIMESTAMP	-211813488000.0
+/* == (0 - POSTGRES_EPOCH_JDATE) * 86400 */
+#define MAX_TIMESTAMP	9223371331200.0
+/* == (JULIAN_MAX4STAMPS - POSTGRES_EPOCH_JDATE) * 86400 */
+#endif
+
+#define IS_VALID_TIMESTAMP(j)  ((MIN_TIMESTAMP <= (j)) && ((j) < MAX_TIMESTAMP))
+
 /*
  * We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
  * Currently, the record holders for wackiest offsets in actual use are zones
@@ -156,6 +170,7 @@ typedef struct
 #define JULIAN_MINMONTH (11)
 #define JULIAN_MINDAY (24)
 #define JULIAN_MAXYEAR (5874898)
+#define JULIAN_MAXYEAR4STAMPS (294277)
 
 #define IS_VALID_JULIAN(y,m,d) \
 	(((y) > JULIAN_MINYEAR \
@@ -164,10 +179,22 @@ typedef struct
 		   || ((m) == JULIAN_MINMONTH && (d) >= JULIAN_MINDAY)))) \
 	 && (y) < JULIAN_MAXYEAR)
 
+#define IS_VALID_JULIAN4STAMPS(y,m,d) \
+	(((y) > JULIAN_MINYEAR \
+	  || ((y) == JULIAN_MINYEAR && \
+		  ((m) > JULIAN_MINMONTH \
+		   || ((m) == JULIAN_MINMONTH && (d) >= JULIAN_MINDAY)))) \
+	 && (y) < JULIAN_MAXYEAR4STAMPS)
+
 #define JULIAN_MAX (2147483494) /* == date2j(JULIAN_MAXYEAR, 1, 1) */
+#define JULIAN_MAX4STAMPS (109203528) /* == date2j(JULIAN_MAXYEAR4STAMPS, 1, 1) */
 
 /* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */
 #define UNIX_EPOCH_JDATE		2440588 /* == date2j(1970, 1, 1) */
 #define POSTGRES_EPOCH_JDATE	2451545 /* == date2j(2000, 1, 1) */
 
+#define IS_VALID_DATE(j) \
+	((-POSTGRES_EPOCH_JDATE <= (j)) && \
+	 ((j) < (JULIAN_MAX - POSTGRES_EPOCH_JDATE)))
+
 #endif   /* DATATYPE_TIMESTAMP_H */
diff --git a/src/interfaces/ecpg/pgtypeslib/dt.h b/src/interfaces/ecpg/pgtypeslib/dt.h
index 145e2b7..32a350c 100644
--- a/src/interfaces/ecpg/pgtypeslib/dt.h
+++ b/src/interfaces/ecpg/pgtypeslib/dt.h
@@ -297,12 +297,14 @@ do { \
 #define JULIAN_MINYEAR (-4713)
 #define JULIAN_MINMONTH (11)
 #define JULIAN_MINDAY (24)
-#define JULIAN_MAXYEAR (5874898)
+#define JULIAN_MAXYEAR4STAMPS (294277)
 
-#define IS_VALID_JULIAN(y,m,d) ((((y) > JULIAN_MINYEAR) \
-  || (((y) == JULIAN_MINYEAR) && (((m) > JULIAN_MINMONTH) \
-  || (((m) == JULIAN_MINMONTH) && ((d) >= JULIAN_MINDAY))))) \
- && ((y) < JULIAN_MAXYEAR))
+#define IS_VALID_JULIAN4STAMPS(y,m,d) \
+	(((y) > JULIAN_MINYEAR \
+	  || ((y) == JULIAN_MINYEAR && \
+		  ((m) > JULIAN_MINMONTH \
+		   || ((m) == JULIAN_MINMONTH && (d) >= JULIAN_MINDAY)))) \
+	 && (y) < JULIAN_MAXYEAR4STAMPS)
 
 #define UTIME_MINYEAR (1901)
 #define UTIME_MINMONTH (12)
diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c
index cf1fed2..2f5219b 100644
--- a/src/interfaces/ecpg/pgtypeslib/timestamp.c
+++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c
@@ -62,7 +62,7 @@ tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, timestamp * result)
 #endif
 
 	/* Julian day routines are not correct for negative Julian days */
-	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
+	if (!IS_VALID_JULIAN4STAMPS(tm->tm_year, tm->tm_mon, tm->tm_mday))
 		return -1;
 
 	dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out
index 56c5520..b197f3a 100644
--- a/src/test/regress/expected/date.out
+++ b/src/test/regress/expected/date.out
@@ -920,6 +920,66 @@ SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '1970-01-01+00');  --  0
          0
 (1 row)
 
+-- corner cases for EPOCH from TIMESTAMPTZ
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '4714-11-24 00:00:00.000000+00 BC');
+   date_part   
+---------------
+ -210866803200
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294247-01-10 04:00:54.775805+00');  -- just before INT64_MAX in extract
+    date_part     
+------------------
+ 9223372036854.78
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294247-01-10 04:00:55.775806+00');  -- just after  INT64_MAX in extract
+    date_part     
+------------------
+ 9223372036855.78
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294276-12-31 23:59:59.9+00');
+    date_part    
+-----------------
+ 9224318015999.9
+(1 row)
+
+-- ERROR (not to forget to change test here when range become wider)
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294276-12-31 24:00:00.000000+00');  -- should fail (timestamp out of range)
+ERROR:  timestamp out of range: "294276-12-31 24:00:00.000000+00"
+LINE 1: SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294276-12-31 24:00:00...
+                                              ^
+-- corner cases for EPOCH from TIMESTAMP
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '4714-11-24 00:00:00.000000 BC');
+   date_part   
+---------------
+ -210866803200
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294247-01-10 04:00:54.775805');  -- just before INT64_MAX in extract
+    date_part     
+------------------
+ 9223372036854.78
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294247-01-10 04:00:55.775806');  -- just after  INT64_MAX in extract
+    date_part     
+------------------
+ 9223372036855.78
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294276-12-31 23:59:59.9');
+    date_part    
+-----------------
+ 9224318015999.9
+(1 row)
+
+-- ERROR (not to forget to change test here when range become wider)
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294276-12-31 24:00:00.000000');  -- should fail (timestamp out of range)
+ERROR:  timestamp out of range: "294276-12-31 24:00:00.000000"
+LINE 1: SELECT EXTRACT(EPOCH FROM TIMESTAMP '294276-12-31 24:00:00.0...
+                                            ^
 --
 -- century
 --
@@ -1452,3 +1512,66 @@ select make_time(10, 55, 100.1);
 ERROR:  time field value out of range: 10:55:100.1
 select make_time(24, 0, 2.1);
 ERROR:  time field value out of range: 24:00:2.1
+-- corner cases
+-- (to prevent raising errors in *_out functions firstly write values to a table)
+CREATE TABLE test_dates(txt TEXT, val DATE);
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('4713-01-01 BC'))t(v);  -- OK
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('5874897-12-31'))t(v);  -- OK
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('5874898-01-01'))t(v);  -- should fail
+ERROR:  date out of range: "5874898-01-01"
+SELECT txt, val FROM test_dates;
+      txt      |      val      
+---------------+---------------
+ 4714-11-24 BC | 11-24-4714 BC
+ 4713-01-01 BC | 01-01-4713 BC
+ 5874897-12-31 | 12-31-5874897
+(3 rows)
+
+DROP TABLE test_dates;
+-- arithmetic operations(only with int values: intervals lead to convert dates to timestamps)
+CREATE TABLE test_dates(txt TEXT, delta int, val DATE);
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC', -2147483648))t(v, d);  -- should fail(overflow check)
+ERROR:  date out of range
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC', -1))t(v, d);  -- should fail
+ERROR:  date out of range
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC',  0))t(v, d);  -- OK
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC', +1))t(v, d);  -- OK
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', -1))t(v, d);  -- OK
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31',  0))t(v, d);  -- OK
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +1))t(v, d);  -- should fail
+ERROR:  date out of range
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2147483647))t(v, d);  -- should fail(overflow check)
+ERROR:  date out of range
+-- previously it resulted OK, +inf, -inf, very high result (can't reach normally)
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451698))t(v, d);  -- should fail(not in allowed range)
+ERROR:  date out of range
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451699))t(v, d);  -- should fail(overflow check)
+ERROR:  date out of range
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451700))t(v, d);  -- should fail(overflow check)
+ERROR:  date out of range
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451701))t(v, d);  -- should fail(overflow check)
+ERROR:  date out of range
+-- Currently it is impossible to reach overflow result of MAX_DATE+MAX_INT
+-- or MIN_DATE+MIN_INT and to be in range [MIN_DATE;MAX_DATE) because the 2nd
+-- addend is type of int4; in case of int8 it is possible thereby when int8 is
+-- allowed as an addend it is necessary to insert checking for overflow result.
+-- Note: originally "select '5874897-12-31'::date + 2147483647" => 4714-06-21 BC
+--  which is _very_ close (156 days) to MIN_DATE(4714-11-24 BC)
+SELECT v::text, d, v::date + d::bigint FROM(VALUES('5874897-12-31', +2147483648))t(v, d);  -- should fail(no operator)
+ERROR:  operator does not exist: date + bigint
+LINE 1: SELECT v::text, d, v::date + d::bigint FROM(VALUES('5874897-...
+                                   ^
+HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
+SELECT txt, delta, val FROM test_dates;
+      txt      | delta |      val      
+---------------+-------+---------------
+ 4714-11-24 BC |     0 | 11-24-4714 BC
+ 4714-11-24 BC |     1 | 11-25-4714 BC
+ 5874897-12-31 |    -1 | 12-30-5874897
+ 5874897-12-31 |     0 | 12-31-5874897
+(4 rows)
+
+DROP TABLE test_dates;
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index 1fe02be..6ce6aae 100644
--- a/src/test/regress/expected/horology.out
+++ b/src/test/regress/expected/horology.out
@@ -3039,4 +3039,38 @@ SELECT to_char('2012-12-12 12:00'::timestamptz, 'YYYY-MM-DD HH:MI:SS TZ');
  2012-12-12 12:00:00 -01:30
 (1 row)
 
+-- corner cases
+SET TIME ZONE 'UTC';
+SELECT to_date('4714 11 23 BC', 'YYYY MM DD BC'); -- ERROR:  date out of range: "-4713 01 01"
+ERROR:  date out of range: "4714 11 23 BC"
+SELECT to_date('4714 11 24 BC', 'YYYY MM DD BC'); -- OK
+    to_date    
+---------------
+ 11-24-4714 BC
+(1 row)
+
+SELECT to_date('5874897 12 31', 'YYYY MM DD');  -- OK
+    to_date    
+---------------
+ 12-31-5874897
+(1 row)
+
+SELECT to_date('5874898 01 01', 'YYYY MM DD');  -- ERROR:  date out of range: "5874898 01 01"
+ERROR:  date out of range: "5874898 01 01"
+SELECT to_timestamp('4714 11 23 23:59:59 BC', 'YYYY MM DD HH24:MI:SS BC');  -- should fail
+ERROR:  timestamp out of range
+SELECT to_timestamp('4714 11 24 00:00:00 BC', 'YYYY MM DD HH24:MI:SS BC');  -- OK
+          to_timestamp           
+---------------------------------
+ Mon Nov 24 00:00:00 4714 UTC BC
+(1 row)
+
+SELECT to_timestamp('294276 12 31 23:59:59', 'YYYY MM DD HH24:MI:SS'); -- OK
+          to_timestamp          
+--------------------------------
+ Sun Dec 31 23:59:59 294276 UTC
+(1 row)
+
+SELECT to_timestamp('294277 01 01 00:00:00', 'YYYY MM DD HH24:MI:SS'); -- should fail
+ERROR:  timestamp out of range
 RESET TIME ZONE;
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index e9f5e77..8a75585 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -1592,3 +1592,206 @@ SELECT make_timestamp(2014,12,28,6,30,45.887);
  Sun Dec 28 06:30:45.887 2014
 (1 row)
 
+-- corner cases
+-- (to prevent raising errors in *_out functions insert values to a table and then select from it)
+SET TIME ZONE 'UTC';
+CREATE TABLE test_timestamps(txt TEXT, val timestamp);
+-- previously it resulted OK, +inf, -inf, ERROR (in timestamp_out!)
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775806'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 04:00:54.775806"
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775807'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 04:00:54.775807"
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775808'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 04:00:54.775808"
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775809'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 04:00:54.775809"
+-- current corner cases
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('4714-11-23 23:59:59.999999 BC'))t(v);  -- should fail
+ERROR:  timestamp out of range: "4714-11-23 23:59:59.999999 BC"
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('4714-11-24 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('4713-01-01 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294276-12-31 23:59:59.999999'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294276-12-31 24:00:00.000000'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294276-12-31 24:00:00.000000"
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-01 00:00:00.000000'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-01 00:00:00.000000"
+-- current corner cases with make_timestamp (note: negative years are not allowed)
+INSERT INTO test_timestamps SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamp(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 23,59,59.999999))t(y,m,d,h,mm,s);  -- OK
+INSERT INTO test_timestamps SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamp(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 24,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+ERROR:  timestamp out of range: 294276-12-31 24:00:00
+INSERT INTO test_timestamps SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamp(y,m,d,h,mm,s) FROM(VALUES(294277,01,01, 00,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+ERROR:  date out of range: 294277-01-01
+-- conversion from date (has bigger allowed interval)
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('294277-01-01'))t(v);  -- should fail
+ERROR:  date out of range for timestamp
+-- conversion from date+time (has bigger allowed interval)
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('4714-11-23 BC', '23:59:59.999999'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('4714-11-23 BC', '24:00:00.000000'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('4714-11-24 BC', '00:00:00.000000'))t(d,t);  -- OK
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('294276-12-31',  '23:59:59.999999'))t(d,t);  -- OK
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('294276-12-31',  '24:00:00.000000'))t(d,t);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('294277-01-01',  '00:00:00.000000'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+SELECT txt, val FROM test_timestamps;
+              txt              |                val                
+-------------------------------+-----------------------------------
+ 4714-11-24 00:00:00.000000 BC | Mon Nov 24 00:00:00 4714 BC
+ 4713-01-01 00:00:00.000000 BC | Thu Jan 01 00:00:00 4713 BC
+ 294276-12-31 23:59:59.999999  | Sun Dec 31 23:59:59.999999 294276
+ 294276-12-31 23:59:59.999999  | Sun Dec 31 23:59:59.999999 294276
+ 4714-11-24 BC                 | Mon Nov 24 00:00:00 4714 BC
+ 294276-12-31                  | Sun Dec 31 00:00:00 294276
+ 4714-11-24 BC 00:00:00.000000 | Mon Nov 24 00:00:00 4714 BC
+ 294276-12-31 23:59:59.999999  | Sun Dec 31 23:59:59.999999 294276
+(8 rows)
+
+DROP TABLE test_timestamps;
+-- truncating tests
+CREATE TABLE test_timestamps(txt TEXT, unit text, val timestamp);
+-- truncating minimum allowed value results to even less value (not allowed)
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('day',   '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('week',  '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('month', '4714-11-30 23:59:59.999999 BC'))t(u,v);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('year',  '4714-12-31 23:59:59.999999 BC'))t(u,v);  -- should fail
+ERROR:  timestamp out of range
+SELECT txt, unit, val FROM test_timestamps;
+              txt              | unit |             val             
+-------------------------------+------+-----------------------------
+ 4714-11-24 00:00:00.000000 BC | day  | Mon Nov 24 00:00:00 4714 BC
+(1 row)
+
+DROP TABLE test_timestamps;
+-- time zone conversions tests
+CREATE TABLE test_timestamps(txt TEXT, tz text, val timestamptz);
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 01:00:00.000000 BC'))t(tz,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+0',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+0',  '294276-12-31 23:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 22:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 23:00:00.000000'))t(tz,v);  -- should fail
+ERROR:  timestamp out of range
+SELECT txt, tz, val FROM test_timestamps;
+              txt              |  tz   |                  val                   
+-------------------------------+-------+----------------------------------------
+ 4714-11-24 01:00:00.000000 BC | GMT-1 | Mon Nov 24 00:00:00 4714 UTC BC
+ 4714-11-24 00:59:59.999999 BC | GMT+0 | Mon Nov 24 00:59:59.999999 4714 UTC BC
+ 294276-12-31 23:59:59.999999  | GMT+0 | Sun Dec 31 23:59:59.999999 294276 UTC
+ 294276-12-31 22:59:59.999999  | GMT+1 | Sun Dec 31 23:59:59.999999 294276 UTC
+(4 rows)
+
+DROP TABLE test_timestamps;
+-- arithmetic operations
+CREATE TABLE test_timestamps(txt TEXT, delta INTERVAL, val timestamp);
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with months)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with days)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with hours)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with seconds)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- current corner cases
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-1mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-1day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-1sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-0.000001sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1day'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1mon'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1mon'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1day'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+0.000001sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+-- try to add/substract maximal/minimal intervals (check for unexpected overflow)
+-- years, months
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+-- days
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+SELECT txt, delta, val FROM test_timestamps;
+             txt              |        delta        |                val                 
+------------------------------+---------------------+------------------------------------
+ 4714-11-24 BC                | @ 0                 | Mon Nov 24 00:00:00 4714 BC
+ 4714-11-24 BC                | @ 0.000001 secs     | Mon Nov 24 00:00:00.000001 4714 BC
+ 4714-11-24 BC                | @ 1 sec             | Mon Nov 24 00:00:01 4714 BC
+ 4714-11-24 BC                | @ 1 sec             | Mon Nov 24 00:00:01 4714 BC
+ 4714-11-24 BC                | @ 1 day             | Tue Nov 25 00:00:00 4714 BC
+ 4714-11-24 BC                | @ 1 mon             | Wed Dec 24 00:00:00 4714 BC
+ 294276-12-31 23:59:59.999999 | @ 1 mon ago         | Thu Nov 30 23:59:59.999999 294276
+ 294276-12-31 23:59:59.999999 | @ 1 day ago         | Sat Dec 30 23:59:59.999999 294276
+ 294276-12-31 23:59:59.999999 | @ 1 sec ago         | Sun Dec 31 23:59:58.999999 294276
+ 294276-12-31 23:59:59.999999 | @ 0.000001 secs ago | Sun Dec 31 23:59:59.999998 294276
+ 294276-12-31 23:59:59.999999 | @ 0                 | Sun Dec 31 23:59:59.999999 294276
+(11 rows)
+
+DROP TABLE test_timestamps;
+RESET TIME ZONE;
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index 40a2254..1abeaaf 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -2487,3 +2487,325 @@ SELECT '2007-12-09 07:30:00 UTC'::timestamptz AT TIME ZONE 'VET';
  Sun Dec 09 03:00:00 2007
 (1 row)
 
+-- corner cases
+-- (to prevent raising errors in *_out functions insert values to a table and then select from it)
+SET TIME ZONE 'UTC';
+CREATE TABLE test_timestamptzs(txt TEXT, val timestamptz);
+-- previously it resulted OK, +inf, -inf, ERROR (in timestamp_out!)
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775806-01'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 03:00:54.775806-01"
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775807-01'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 03:00:54.775807-01"
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775808-01'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 03:00:54.775808-01"
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775809-01'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-09 03:00:54.775809-01"
+-- current corner cases
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-23 23:59:59.999999 BC'))t(v);  -- should fail
+ERROR:  timestamp out of range: "4714-11-23 23:59:59.999999 BC"
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-24 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4713-01-01 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 23:59:59.999999'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 24:00:00.000000'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294276-12-31 24:00:00.000000"
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-01 00:00:00.000000'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294277-01-01 00:00:00.000000"
+-- current corner cases with non-UTC time zones
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-24 00:59:59.999999+01 BC'))t(v);  -- should fail
+ERROR:  timestamp out of range: "4714-11-24 00:59:59.999999+01 BC"
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-24 01:00:00.000000+01 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4713-01-01 01:00:00.000000+01 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 22:59:59.999999-01'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 23:00:00.000000-01'))t(v);  -- should fail
+ERROR:  timestamp out of range: "294276-12-31 23:00:00.000000-01"
+-- current corner cases with make_timestamptz(current tz=UTC) (note: negative years are not allowed)
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamptz(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 23,59,59.999999))t(y,m,d,h,mm,s);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamptz(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 24,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+ERROR:  timestamp out of range: 294276-12-31 24:00:00
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamptz(y,m,d,h,mm,s) FROM(VALUES(294277,01,01, 00,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+ERROR:  date out of range: 294277-01-01
+-- current corner cases with make_timestamptz(in non-UTC TZ) (note: negative years are not allowed)
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s %s', y,m,d,h,mm,s,tz), make_timestamptz(y,m,d,h,mm,s,tz) FROM(VALUES(294276,12,31, 23,59,59.999999, 'GMT+0'))t(y,m,d,h,mm,s,tz);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s %s', y,m,d,h,mm,s,tz), make_timestamptz(y,m,d,h,mm,s,tz) FROM(VALUES(294276,12,31, 22,59,59.999999, 'GMT+1'))t(y,m,d,h,mm,s,tz);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s %s', y,m,d,h,mm,s,tz), make_timestamptz(y,m,d,h,mm,s,tz) FROM(VALUES(294276,12,31, 23,00,00.000000, 'GMT+1'))t(y,m,d,h,mm,s,tz);  -- should fail
+ERROR:  timestamp out of range
+-- conversion from date (has bigger allowed interval)
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-01'))t(v);  -- should fail
+ERROR:  date out of range for timestamp
+-- check for overflow because of time zones
+SET TIME ZONE 'GMT-1';
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-22 BC'))t(v);  -- should fail
+ERROR:  date out of range: "4714-11-22 BC"
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-24 BC'))t(v);  -- should fail (-4714-11-23 23:00:00)
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-25 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-30'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-01'))t(v);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-02'))t(v);  -- should fail
+ERROR:  date out of range for timestamp
+SET TIME ZONE 'GMT+1';
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-22 BC'))t(v);  -- should fail
+ERROR:  date out of range: "4714-11-22 BC"
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-25 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-30'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-01'))t(v);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-02'))t(v);  -- should fail
+ERROR:  date out of range for timestamp
+-- restore UTC by default
+SET TIME ZONE 'UTC';
+-- conversion from date+time (has bigger allowed interval)
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '23:59:59.999999'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '24:00:00.000000'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:00:00.000000'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:59:59.999999'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '24:00:00.000000'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294277-01-01',  '00:00:00.000000'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+-- conversion from date+timeTZ (has bigger allowed interval)
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '23:59:59.999999-01'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '24:00:00.000000-01'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:00:00.000000-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:59:59.999999-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '01:00:00.000000-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '22:59:59.999999-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:00:00.000000-01'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:59:59.999999-01'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '24:00:00.000000-01'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '23:59:59.999999+01'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '24:00:00.000000+01'))t(d,t);  -- should fail
+ERROR:  date out of range: "4714-11-23 BC"
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:00:00.000000+01'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:59:59.999999+01'))t(d,t);  -- should fail
+ERROR:  date out of range for timestamp
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '01:00:00.000000+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '22:59:59.999999+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:00:00.000000+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:59:59.999999+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '24:00:00.000000+01'))t(d,t);  -- OK
+SELECT txt, val FROM test_timestamptzs;
+                txt                 |                  val                   
+------------------------------------+----------------------------------------
+ 4714-11-24 00:00:00.000000 BC      | Mon Nov 24 00:00:00 4714 UTC BC
+ 4713-01-01 00:00:00.000000 BC      | Thu Jan 01 00:00:00 4713 UTC BC
+ 294276-12-31 23:59:59.999999       | Sun Dec 31 23:59:59.999999 294276 UTC
+ 4714-11-24 01:00:00.000000+01 BC   | Mon Nov 24 00:00:00 4714 UTC BC
+ 4713-01-01 01:00:00.000000+01 BC   | Thu Jan 01 00:00:00 4713 UTC BC
+ 294276-12-31 22:59:59.999999-01    | Sun Dec 31 23:59:59.999999 294276 UTC
+ 294276-12-31 23:59:59.999999       | Sun Dec 31 23:59:59.999999 294276 UTC
+ 294276-12-31 23:59:59.999999 GMT+0 | Sun Dec 31 23:59:59.999999 294276 UTC
+ 294276-12-31 22:59:59.999999 GMT+1 | Sun Dec 31 23:59:59.999999 294276 UTC
+ 4714-11-24 BC                      | Mon Nov 24 00:00:00 4714 UTC BC
+ 294276-12-31                       | Sun Dec 31 00:00:00 294276 UTC
+ 4714-11-25 BC                      | Mon Nov 24 23:00:00 4714 UTC BC
+ 294276-12-30                       | Fri Dec 29 23:00:00 294276 UTC
+ 294276-12-31                       | Sat Dec 30 23:00:00 294276 UTC
+ 4714-11-24 BC                      | Mon Nov 24 01:00:00 4714 UTC BC
+ 4714-11-25 BC                      | Tue Nov 25 01:00:00 4714 UTC BC
+ 294276-12-30                       | Sat Dec 30 01:00:00 294276 UTC
+ 294276-12-31                       | Sun Dec 31 01:00:00 294276 UTC
+ 4714-11-24 BC 00:00:00.000000      | Mon Nov 24 00:00:00 4714 UTC BC
+ 294276-12-31 23:59:59.999999       | Sun Dec 31 23:59:59.999999 294276 UTC
+ 4714-11-24 BC 00:00:00.000000-01   | Mon Nov 24 01:00:00 4714 UTC BC
+ 4714-11-24 BC 00:59:59.999999-01   | Mon Nov 24 01:59:59.999999 4714 UTC BC
+ 4714-11-24 BC 01:00:00.000000-01   | Mon Nov 24 02:00:00 4714 UTC BC
+ 294276-12-31 22:59:59.999999-01    | Sun Dec 31 23:59:59.999999 294276 UTC
+ 4714-11-24 BC 01:00:00.000000+01   | Mon Nov 24 00:00:00 4714 UTC BC
+ 294276-12-31 22:59:59.999999+01    | Sun Dec 31 21:59:59.999999 294276 UTC
+ 294276-12-31 23:00:00.000000+01    | Sun Dec 31 22:00:00 294276 UTC
+ 294276-12-31 23:59:59.999999+01    | Sun Dec 31 22:59:59.999999 294276 UTC
+ 294276-12-31 24:00:00.000000+01    | Sun Dec 31 23:00:00 294276 UTC
+(29 rows)
+
+DROP TABLE test_timestamptzs;
+-- truncating tests
+CREATE TABLE test_timestamptzs(txt TEXT, unit text, val timestamptz);
+-- truncating minimum allowed value results to even less value (not allowed)
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('day',   '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('week',  '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('month', '4714-11-30 23:59:59.999999 BC'))t(u,v);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('year',  '4714-12-31 23:59:59.999999 BC'))t(u,v);  -- should fail
+ERROR:  timestamp out of range
+SELECT txt, unit, val FROM test_timestamptzs;
+              txt              | unit |               val               
+-------------------------------+------+---------------------------------
+ 4714-11-24 00:00:00.000000 BC | day  | Mon Nov 24 00:00:00 4714 UTC BC
+(1 row)
+
+DROP TABLE test_timestamptzs;
+-- time zone conversions tests
+CREATE TABLE test_timestamptzs(txt TEXT, tz text, val timestamp);
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 01:00:00.000000 BC'))t(tz,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+0',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+0',  '294276-12-31 23:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 22:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 23:00:00.000000'))t(tz,v);  -- should fail
+SELECT txt, tz, val FROM test_timestamptzs;
+              txt              |  tz   |                val                 
+-------------------------------+-------+------------------------------------
+ 4714-11-24 00:59:59.999999 BC | GMT-1 | Mon Nov 24 01:59:59.999999 4714 BC
+ 4714-11-24 01:00:00.000000 BC | GMT-1 | Mon Nov 24 02:00:00 4714 BC
+ 4714-11-24 00:59:59.999999 BC | GMT+0 | Mon Nov 24 00:59:59.999999 4714 BC
+ 294276-12-31 23:59:59.999999  | GMT+0 | Sun Dec 31 23:59:59.999999 294276
+ 294276-12-31 22:59:59.999999  | GMT+1 | Sun Dec 31 21:59:59.999999 294276
+ 294276-12-31 23:00:00.000000  | GMT+1 | Sun Dec 31 22:00:00 294276
+(6 rows)
+
+DROP TABLE test_timestamptzs;
+-- arithmetic operations
+CREATE TABLE test_timestamptzs(txt TEXT, delta INTERVAL, val timestamptz);
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with months)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with days)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with hours)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with seconds)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775806'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775807'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775808'))t(v, d);
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775809'))t(v, d);
+ERROR:  timestamp out of range
+-- current corner cases
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-1mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-1day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-1sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-0.000001sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1day'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1mon'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1mon'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1day'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+0.000001sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+-- try to add/substract maximal/minimal intervals (check for unexpected overflow)
+-- years, months
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648mon'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+-- days
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648day'))t(v, d);  -- should fail
+ERROR:  timestamp out of range
+SELECT txt, delta, val FROM test_timestamptzs;
+             txt              |        delta        |                  val                   
+------------------------------+---------------------+----------------------------------------
+ 4714-11-24 BC                | @ 0                 | Mon Nov 24 00:00:00 4714 UTC BC
+ 4714-11-24 BC                | @ 0.000001 secs     | Mon Nov 24 00:00:00.000001 4714 UTC BC
+ 4714-11-24 BC                | @ 1 sec             | Mon Nov 24 00:00:01 4714 UTC BC
+ 4714-11-24 BC                | @ 1 sec             | Mon Nov 24 00:00:01 4714 UTC BC
+ 4714-11-24 BC                | @ 1 day             | Tue Nov 25 00:00:00 4714 UTC BC
+ 4714-11-24 BC                | @ 1 mon             | Wed Dec 24 00:00:00 4714 UTC BC
+ 294276-12-31 23:59:59.999999 | @ 1 mon ago         | Thu Nov 30 23:59:59.999999 294276 UTC
+ 294276-12-31 23:59:59.999999 | @ 1 day ago         | Sat Dec 30 23:59:59.999999 294276 UTC
+ 294276-12-31 23:59:59.999999 | @ 1 sec ago         | Sun Dec 31 23:59:58.999999 294276 UTC
+ 294276-12-31 23:59:59.999999 | @ 0.000001 secs ago | Sun Dec 31 23:59:59.999998 294276 UTC
+ 294276-12-31 23:59:59.999999 | @ 0                 | Sun Dec 31 23:59:59.999999 294276 UTC
+(11 rows)
+
+DROP TABLE test_timestamptzs;
+-- IN/OUT in different time zones
+SET TIME ZONE 'GMT-1';
+SELECT '4714-11-24 00:00:00.000000+00 BC'::timestamptz;  --min allowed timestamptz
+           timestamptz           
+---------------------------------
+ Mon Nov 24 01:00:00 4714 GMT BC
+(1 row)
+
+SELECT '294276-12-31 23:59:59.999999+00'::timestamptz;   --max allowed timestamptz
+              timestamptz              
+---------------------------------------
+ Mon Jan 01 00:59:59.999999 294277 GMT
+(1 row)
+
+SET TIME ZONE 'GMT+1';
+SELECT '4714-11-24 00:00:00.000000+00 BC'::timestamptz;  --min allowed timestamptz
+           timestamptz           
+---------------------------------
+ Sun Nov 23 23:00:00 4714 GMT BC
+(1 row)
+
+SELECT '294276-12-31 23:59:59.999999+00'::timestamptz;   --max allowed timestamptz
+              timestamptz              
+---------------------------------------
+ Sun Dec 31 22:59:59.999999 294276 GMT
+(1 row)
+
+RESET TIME ZONE;
diff --git a/src/test/regress/sql/date.sql b/src/test/regress/sql/date.sql
index e40b4c4..f277f71 100644
--- a/src/test/regress/sql/date.sql
+++ b/src/test/regress/sql/date.sql
@@ -217,6 +217,23 @@ SELECT date 'tomorrow' - date 'yesterday' AS "Two days";
 SELECT EXTRACT(EPOCH FROM DATE        '1970-01-01');     --  0
 SELECT EXTRACT(EPOCH FROM TIMESTAMP   '1970-01-01');     --  0
 SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '1970-01-01+00');  --  0
+
+-- corner cases for EPOCH from TIMESTAMPTZ
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '4714-11-24 00:00:00.000000+00 BC');
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294247-01-10 04:00:54.775805+00');  -- just before INT64_MAX in extract
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294247-01-10 04:00:55.775806+00');  -- just after  INT64_MAX in extract
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294276-12-31 23:59:59.9+00');
+-- ERROR (not to forget to change test here when range become wider)
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '294276-12-31 24:00:00.000000+00');  -- should fail (timestamp out of range)
+
+-- corner cases for EPOCH from TIMESTAMP
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '4714-11-24 00:00:00.000000 BC');
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294247-01-10 04:00:54.775805');  -- just before INT64_MAX in extract
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294247-01-10 04:00:55.775806');  -- just after  INT64_MAX in extract
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294276-12-31 23:59:59.9');
+-- ERROR (not to forget to change test here when range become wider)
+SELECT EXTRACT(EPOCH FROM TIMESTAMP '294276-12-31 24:00:00.000000');  -- should fail (timestamp out of range)
+
 --
 -- century
 --
@@ -340,3 +357,45 @@ select make_date(2013, 11, -1);
 select make_date(-44, 3, 15);  -- perhaps we should allow this sometime?
 select make_time(10, 55, 100.1);
 select make_time(24, 0, 2.1);
+
+-- corner cases
+-- (to prevent raising errors in *_out functions firstly write values to a table)
+CREATE TABLE test_dates(txt TEXT, val DATE);
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('4713-01-01 BC'))t(v);  -- OK
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('5874897-12-31'))t(v);  -- OK
+INSERT INTO test_dates SELECT v::text, v::date FROM(VALUES('5874898-01-01'))t(v);  -- should fail
+
+SELECT txt, val FROM test_dates;
+DROP TABLE test_dates;
+
+-- arithmetic operations(only with int values: intervals lead to convert dates to timestamps)
+CREATE TABLE test_dates(txt TEXT, delta int, val DATE);
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC', -2147483648))t(v, d);  -- should fail(overflow check)
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC', -1))t(v, d);  -- should fail
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC',  0))t(v, d);  -- OK
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('4714-11-24 BC', +1))t(v, d);  -- OK
+
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', -1))t(v, d);  -- OK
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31',  0))t(v, d);  -- OK
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +1))t(v, d);  -- should fail
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2147483647))t(v, d);  -- should fail(overflow check)
+
+-- previously it resulted OK, +inf, -inf, very high result (can't reach normally)
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451698))t(v, d);  -- should fail(not in allowed range)
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451699))t(v, d);  -- should fail(overflow check)
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451700))t(v, d);  -- should fail(overflow check)
+INSERT INTO test_dates SELECT v::text, d, v::date + d FROM(VALUES('5874897-12-31', +2451701))t(v, d);  -- should fail(overflow check)
+
+-- Currently it is impossible to reach overflow result of MAX_DATE+MAX_INT
+-- or MIN_DATE+MIN_INT and to be in range [MIN_DATE;MAX_DATE) because the 2nd
+-- addend is type of int4; in case of int8 it is possible thereby when int8 is
+-- allowed as an addend it is necessary to insert checking for overflow result.
+-- Note: originally "select '5874897-12-31'::date + 2147483647" => 4714-06-21 BC
+--  which is _very_ close (156 days) to MIN_DATE(4714-11-24 BC)
+SELECT v::text, d, v::date + d::bigint FROM(VALUES('5874897-12-31', +2147483648))t(v, d);  -- should fail(no operator)
+
+
+SELECT txt, delta, val FROM test_dates;
+DROP TABLE test_dates;
diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql
index c81437b..39ad7c0 100644
--- a/src/test/regress/sql/horology.sql
+++ b/src/test/regress/sql/horology.sql
@@ -496,4 +496,18 @@ SELECT '2012-12-12 12:00 America/New_York'::timestamptz;
 
 SELECT to_char('2012-12-12 12:00'::timestamptz, 'YYYY-MM-DD HH:MI:SS TZ');
 
+-- corner cases
+SET TIME ZONE 'UTC';
+
+SELECT to_date('4714 11 23 BC', 'YYYY MM DD BC'); -- ERROR:  date out of range: "-4713 01 01"
+SELECT to_date('4714 11 24 BC', 'YYYY MM DD BC'); -- OK
+SELECT to_date('5874897 12 31', 'YYYY MM DD');  -- OK
+SELECT to_date('5874898 01 01', 'YYYY MM DD');  -- ERROR:  date out of range: "5874898 01 01"
+
+
+SELECT to_timestamp('4714 11 23 23:59:59 BC', 'YYYY MM DD HH24:MI:SS BC');  -- should fail
+SELECT to_timestamp('4714 11 24 00:00:00 BC', 'YYYY MM DD HH24:MI:SS BC');  -- OK
+SELECT to_timestamp('294276 12 31 23:59:59', 'YYYY MM DD HH24:MI:SS'); -- OK
+SELECT to_timestamp('294277 01 01 00:00:00', 'YYYY MM DD HH24:MI:SS'); -- should fail
+
 RESET TIME ZONE;
diff --git a/src/test/regress/sql/timestamp.sql b/src/test/regress/sql/timestamp.sql
index b22cd48..ad94b23 100644
--- a/src/test/regress/sql/timestamp.sql
+++ b/src/test/regress/sql/timestamp.sql
@@ -225,3 +225,140 @@ SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
 
 -- timestamp numeric fields constructor
 SELECT make_timestamp(2014,12,28,6,30,45.887);
+
+-- corner cases
+-- (to prevent raising errors in *_out functions insert values to a table and then select from it)
+SET TIME ZONE 'UTC';
+
+CREATE TABLE test_timestamps(txt TEXT, val timestamp);
+
+-- previously it resulted OK, +inf, -inf, ERROR (in timestamp_out!)
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775806'))t(v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775807'))t(v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775808'))t(v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-09 04:00:54.775809'))t(v);  -- should fail
+
+-- current corner cases
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('4714-11-23 23:59:59.999999 BC'))t(v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('4714-11-24 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('4713-01-01 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294276-12-31 23:59:59.999999'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294276-12-31 24:00:00.000000'))t(v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, v::timestamp FROM(VALUES('294277-01-01 00:00:00.000000'))t(v);  -- should fail
+
+-- current corner cases with make_timestamp (note: negative years are not allowed)
+INSERT INTO test_timestamps SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamp(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 23,59,59.999999))t(y,m,d,h,mm,s);  -- OK
+INSERT INTO test_timestamps SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamp(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 24,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+INSERT INTO test_timestamps SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamp(y,m,d,h,mm,s) FROM(VALUES(294277,01,01, 00,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+
+-- conversion from date (has bigger allowed interval)
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, v::date::timestamp FROM(VALUES('294277-01-01'))t(v);  -- should fail
+
+-- conversion from date+time (has bigger allowed interval)
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('4714-11-23 BC', '23:59:59.999999'))t(d,t);  -- should fail
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('4714-11-23 BC', '24:00:00.000000'))t(d,t);  -- should fail
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('4714-11-24 BC', '00:00:00.000000'))t(d,t);  -- OK
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('294276-12-31',  '23:59:59.999999'))t(d,t);  -- OK
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('294276-12-31',  '24:00:00.000000'))t(d,t);  -- should fail
+INSERT INTO test_timestamps SELECT format('%s %s', d::text, t::text), "timestamp"(d::date, t::time) FROM(VALUES('294277-01-01',  '00:00:00.000000'))t(d,t);  -- should fail
+
+SELECT txt, val FROM test_timestamps;
+DROP TABLE test_timestamps;
+
+
+-- truncating tests
+CREATE TABLE test_timestamps(txt TEXT, unit text, val timestamp);
+-- truncating minimum allowed value results to even less value (not allowed)
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('day',   '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('week',  '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('month', '4714-11-30 23:59:59.999999 BC'))t(u,v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, u, date_trunc(u, v::timestamp) FROM(VALUES('year',  '4714-12-31 23:59:59.999999 BC'))t(u,v);  -- should fail
+
+SELECT txt, unit, val FROM test_timestamps;
+DROP TABLE test_timestamps;
+
+
+-- time zone conversions tests
+CREATE TABLE test_timestamps(txt TEXT, tz text, val timestamptz);
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 01:00:00.000000 BC'))t(tz,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+0',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- OK
+
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+0',  '294276-12-31 23:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 22:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamps SELECT v::text, tz, v::timestamp AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 23:00:00.000000'))t(tz,v);  -- should fail
+
+SELECT txt, tz, val FROM test_timestamps;
+DROP TABLE test_timestamps;
+
+
+-- arithmetic operations
+CREATE TABLE test_timestamps(txt TEXT, delta INTERVAL, val timestamp);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with months)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775806'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775807'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775808'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775809'))t(v, d);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with days)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775806'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775807'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775808'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775809'))t(v, d);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with hours)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775806'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775807'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775808'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775809'))t(v, d);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamp (with seconds)  [should fail]
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775806'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775807'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775808'))t(v, d);
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294247-01-10',           '946699254.775809'))t(v, d);
+
+-- current corner cases
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-1mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-1day'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-1sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '-0.000001sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1day'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 BC', '+1mon'))t(v, d);  -- OK
+
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1mon'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1day'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+0.000001sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1day'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1mon'))t(v, d);  -- should fail
+
+-- try to add/substract maximal/minimal intervals (check for unexpected overflow)
+-- years, months
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648mon'))t(v, d);  -- should fail
+-- days
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647day'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648day'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647day'))t(v, d);  -- should fail
+INSERT INTO test_timestamps SELECT v::text, d::interval, v::timestamp + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648day'))t(v, d);  -- should fail
+
+SELECT txt, delta, val FROM test_timestamps;
+DROP TABLE test_timestamps;
+
+
+RESET TIME ZONE;
diff --git a/src/test/regress/sql/timestamptz.sql b/src/test/regress/sql/timestamptz.sql
index f4b455e..1571f45 100644
--- a/src/test/regress/sql/timestamptz.sql
+++ b/src/test/regress/sql/timestamptz.sql
@@ -432,3 +432,207 @@ SELECT '2007-12-09 07:00:00 UTC'::timestamptz AT TIME ZONE 'VET';
 SELECT '2007-12-09 07:00:01 UTC'::timestamptz AT TIME ZONE 'VET';
 SELECT '2007-12-09 07:29:59 UTC'::timestamptz AT TIME ZONE 'VET';
 SELECT '2007-12-09 07:30:00 UTC'::timestamptz AT TIME ZONE 'VET';
+
+-- corner cases
+-- (to prevent raising errors in *_out functions insert values to a table and then select from it)
+SET TIME ZONE 'UTC';
+
+CREATE TABLE test_timestamptzs(txt TEXT, val timestamptz);
+
+-- previously it resulted OK, +inf, -inf, ERROR (in timestamp_out!)
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775806-01'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775807-01'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775808-01'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-09 03:00:54.775809-01'))t(v);  -- should fail
+
+-- current corner cases
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-23 23:59:59.999999 BC'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-24 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4713-01-01 00:00:00.000000 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 23:59:59.999999'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 24:00:00.000000'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294277-01-01 00:00:00.000000'))t(v);  -- should fail
+
+-- current corner cases with non-UTC time zones
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-24 00:59:59.999999+01 BC'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4714-11-24 01:00:00.000000+01 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('4713-01-01 01:00:00.000000+01 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 22:59:59.999999-01'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::timestamptz FROM(VALUES('294276-12-31 23:00:00.000000-01'))t(v);  -- should fail
+
+-- current corner cases with make_timestamptz(current tz=UTC) (note: negative years are not allowed)
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamptz(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 23,59,59.999999))t(y,m,d,h,mm,s);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamptz(y,m,d,h,mm,s) FROM(VALUES(294276,12,31, 24,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s', y,m,d,h,mm,s), make_timestamptz(y,m,d,h,mm,s) FROM(VALUES(294277,01,01, 00,00,00.000000))t(y,m,d,h,mm,s);  -- should fail
+
+-- current corner cases with make_timestamptz(in non-UTC TZ) (note: negative years are not allowed)
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s %s', y,m,d,h,mm,s,tz), make_timestamptz(y,m,d,h,mm,s,tz) FROM(VALUES(294276,12,31, 23,59,59.999999, 'GMT+0'))t(y,m,d,h,mm,s,tz);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s %s', y,m,d,h,mm,s,tz), make_timestamptz(y,m,d,h,mm,s,tz) FROM(VALUES(294276,12,31, 22,59,59.999999, 'GMT+1'))t(y,m,d,h,mm,s,tz);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s-%s-%s %s:%s:%s %s', y,m,d,h,mm,s,tz), make_timestamptz(y,m,d,h,mm,s,tz) FROM(VALUES(294276,12,31, 23,00,00.000000, 'GMT+1'))t(y,m,d,h,mm,s,tz);  -- should fail
+
+-- conversion from date (has bigger allowed interval)
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-01'))t(v);  -- should fail
+
+-- check for overflow because of time zones
+SET TIME ZONE 'GMT-1';
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-22 BC'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-24 BC'))t(v);  -- should fail (-4714-11-23 23:00:00)
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-25 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-30'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-01'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-02'))t(v);  -- should fail
+
+SET TIME ZONE 'GMT+1';
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-22 BC'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-23 BC'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-24 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('4714-11-25 BC'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-30'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294276-12-31'))t(v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-01'))t(v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, v::date::timestamptz FROM(VALUES('294277-01-02'))t(v);  -- should fail
+
+-- restore UTC by default
+SET TIME ZONE 'UTC';
+
+-- conversion from date+time (has bigger allowed interval)
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '23:59:59.999999'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '24:00:00.000000'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:00:00.000000'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:59:59.999999'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '24:00:00.000000'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294277-01-01',  '00:00:00.000000'))t(d,t);  -- should fail
+
+-- conversion from date+timeTZ (has bigger allowed interval)
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '23:59:59.999999-01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '24:00:00.000000-01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:00:00.000000-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:59:59.999999-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '01:00:00.000000-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '22:59:59.999999-01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:00:00.000000-01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:59:59.999999-01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '24:00:00.000000-01'))t(d,t);  -- should fail
+
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '23:59:59.999999+01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-23 BC', '24:00:00.000000+01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:00:00.000000+01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '00:59:59.999999+01'))t(d,t);  -- should fail
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('4714-11-24 BC', '01:00:00.000000+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '22:59:59.999999+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:00:00.000000+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '23:59:59.999999+01'))t(d,t);  -- OK
+INSERT INTO test_timestamptzs SELECT format('%s %s', d::text, t::text), "timestamptz"(d::date, t::timetz) FROM(VALUES('294276-12-31',  '24:00:00.000000+01'))t(d,t);  -- OK
+
+
+SELECT txt, val FROM test_timestamptzs;
+DROP TABLE test_timestamptzs;
+
+
+-- truncating tests
+CREATE TABLE test_timestamptzs(txt TEXT, unit text, val timestamptz);
+-- truncating minimum allowed value results to even less value (not allowed)
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('day',   '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('week',  '4714-11-24 00:00:00.000000 BC'))t(u,v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('month', '4714-11-30 23:59:59.999999 BC'))t(u,v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, u, date_trunc(u, v::timestamptz) FROM(VALUES('year',  '4714-12-31 23:59:59.999999 BC'))t(u,v);  -- should fail
+
+SELECT txt, unit, val FROM test_timestamptzs;
+DROP TABLE test_timestamptzs;
+
+
+-- time zone conversions tests
+CREATE TABLE test_timestamptzs(txt TEXT, tz text, val timestamp);
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT-1',  '4714-11-24 01:00:00.000000 BC'))t(tz,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+0',  '4714-11-24 00:59:59.999999 BC'))t(tz,v);  -- OK
+
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+0',  '294276-12-31 23:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 22:59:59.999999'))t(tz,v);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, tz, v::timestamptz AT TIME ZONE tz FROM(VALUES('GMT+1',  '294276-12-31 23:00:00.000000'))t(tz,v);  -- should fail
+
+SELECT txt, tz, val FROM test_timestamptzs;
+DROP TABLE test_timestamptzs;
+
+
+-- arithmetic operations
+CREATE TABLE test_timestamptzs(txt TEXT, delta INTERVAL, val timestamptz);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with months)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775806'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775807'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775808'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-09', '360 months 04:00:54.775809'))t(v, d);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with days)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775806'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775807'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775808'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10', '10957 days 04:00:54.775809'))t(v, d);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with hours)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775806'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775807'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775808'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',        '262972:00:54.775809'))t(v, d);
+
+-- the same as '294277-01-09 04:00:54.77580*'::timestamptz (with seconds)  [should fail]
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775806'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775807'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775808'))t(v, d);
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294247-01-10',           '946699254.775809'))t(v, d);
+
+-- current corner cases
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-1mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-1day'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-1sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '-0.000001sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1day'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 BC', '+1mon'))t(v, d);  -- OK
+
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1mon'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1day'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-1sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '-0.000001sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', ' 0sec'))t(v, d);  -- OK
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+0.000001sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1sec'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1day'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999', '+1mon'))t(v, d);  -- should fail
+
+-- try to add/substract maximal/minimal intervals (check for unexpected overflow)
+-- years, months
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647mon'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648mon'))t(v, d);  -- should fail
+-- days
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '+2147483647day'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('294276-12-31 23:59:59.999999',  '-2147483648day'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '+2147483647day'))t(v, d);  -- should fail
+INSERT INTO test_timestamptzs SELECT v::text, d::interval, v::timestamptz + d::interval FROM(VALUES('4714-11-24 01:00:00.000000 BC', '-2147483648day'))t(v, d);  -- should fail
+
+SELECT txt, delta, val FROM test_timestamptzs;
+DROP TABLE test_timestamptzs;
+
+-- IN/OUT in different time zones
+SET TIME ZONE 'GMT-1';
+SELECT '4714-11-24 00:00:00.000000+00 BC'::timestamptz;  --min allowed timestamptz
+SELECT '294276-12-31 23:59:59.999999+00'::timestamptz;   --max allowed timestamptz
+
+SET TIME ZONE 'GMT+1';
+SELECT '4714-11-24 00:00:00.000000+00 BC'::timestamptz;  --min allowed timestamptz
+SELECT '294276-12-31 23:59:59.999999+00'::timestamptz;   --max allowed timestamptz
+
+
+RESET TIME ZONE;
