diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 8fbb310..006999f 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -4311,6 +4311,69 @@ date2isoyearday(int year, int mon, int mday)
 	return date2j(year, mon, mday) - isoweek2j(date2isoyear(year, mon, mday), 1) + 1;
 }
 
+/*
+ * HandleNonFiniteTimestampTzPart
+ *
+ *	Used by timestamp_part and timestamptz_part when extracting from non-finite timestamp[tz].
+ *	For monotonic units sets result to +/-Inf and returns true.
+ *	For oscillating ones leaves result as is and returns false.
+ *	Return value is a flag whether +/-Inf from result must be returned or NULL.
+ */
+static bool
+HandleNonFiniteTimestampTzPart(int type, int unit, char* lowunits,
+							   float8 *result, bool isNegative)
+{
+	/*
+	 * Units are in the same order as in timestamp_part and timestamptz_part.
+	 * Monotonic units are moved to a separate block (but in the same order).
+	*/
+	if ((type != UNITS) && (type != RESERV))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("timestamp units \"%s\" not recognized", lowunits)));
+
+	switch (unit)
+	{
+		/* Oscillating units */
+		case DTK_MICROSEC:
+		case DTK_MILLISEC:
+		case DTK_SECOND:
+		case DTK_MINUTE:
+		case DTK_HOUR:
+		case DTK_DAY:
+		case DTK_MONTH:
+		case DTK_QUARTER:
+		case DTK_WEEK:
+		/* Monotonic units between WEEK and DOW are moved to the end of switch */
+		case DTK_DOW:
+		case DTK_ISODOW:
+		case DTK_DOY:
+		case DTK_TZ:
+		case DTK_TZ_MINUTE:
+		case DTK_TZ_HOUR:
+			return false;
+
+		/* Monotonic units */
+		case DTK_YEAR:
+		case DTK_DECADE:
+		case DTK_CENTURY:
+		case DTK_MILLENNIUM:
+		case DTK_JULIAN:
+		case DTK_ISOYEAR:
+		case DTK_EPOCH:
+			*result = get_float8_infinity();
+			if (isNegative)
+				*result = -(*result);
+			return true;
+
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("timestamp units \"%s\" not supported",
+							lowunits)));
+	}
+}
+
 /* timestamp_part()
  * Extract specified field from timestamp.
  */
@@ -4327,12 +4390,6 @@ timestamp_part(PG_FUNCTION_ARGS)
 	struct pg_tm tt,
 			   *tm = &tt;
 
-	if (TIMESTAMP_NOT_FINITE(timestamp))
-	{
-		result = 0;
-		PG_RETURN_FLOAT8(result);
-	}
-
 	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
 											VARSIZE_ANY_EXHDR(units),
 											false);
@@ -4341,6 +4398,16 @@ timestamp_part(PG_FUNCTION_ARGS)
 	if (type == UNKNOWN_FIELD)
 		type = DecodeSpecial(0, lowunits, &val);
 
+	if (TIMESTAMP_NOT_FINITE(timestamp))
+	{
+		if (HandleNonFiniteTimestampTzPart(type, val, lowunits,
+										   &result,
+										   TIMESTAMP_IS_NOBEGIN(timestamp)))
+			PG_RETURN_FLOAT8(result);
+		else
+			PG_RETURN_NULL();
+	}
+
 	if (type == UNITS)
 	{
 		if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
@@ -4538,12 +4605,6 @@ timestamptz_part(PG_FUNCTION_ARGS)
 	struct pg_tm tt,
 			   *tm = &tt;
 
-	if (TIMESTAMP_NOT_FINITE(timestamp))
-	{
-		result = 0;
-		PG_RETURN_FLOAT8(result);
-	}
-
 	lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
 											VARSIZE_ANY_EXHDR(units),
 											false);
@@ -4552,6 +4613,16 @@ timestamptz_part(PG_FUNCTION_ARGS)
 	if (type == UNKNOWN_FIELD)
 		type = DecodeSpecial(0, lowunits, &val);
 
+	if (TIMESTAMP_NOT_FINITE(timestamp))
+	{
+		if (HandleNonFiniteTimestampTzPart(type, val, lowunits,
+										   &result,
+										   TIMESTAMP_IS_NOBEGIN(timestamp)))
+			PG_RETURN_FLOAT8(result);
+		else
+			PG_RETURN_NULL();
+	}
+
 	if (type == UNITS)
 	{
 		if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out
index 8923f60..56c5520 100644
--- a/src/test/regress/expected/date.out
+++ b/src/test/regress/expected/date.out
@@ -900,6 +900,27 @@ SELECT date 'tomorrow' - date 'yesterday' AS "Two days";
 --
 -- test extract!
 --
+-- epoch
+--
+SELECT EXTRACT(EPOCH FROM DATE        '1970-01-01');     --  0
+ date_part 
+-----------
+         0
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMP   '1970-01-01');     --  0
+ date_part 
+-----------
+         0
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '1970-01-01+00');  --  0
+ date_part 
+-----------
+         0
+(1 row)
+
+--
 -- century
 --
 SELECT EXTRACT(CENTURY FROM DATE '0101-12-31 BC'); -- -2
@@ -1184,6 +1205,227 @@ select isfinite('infinity'::date), isfinite('-infinity'::date), isfinite('today'
  f        | f        | t
 (1 row)
 
+--
+-- oscillating fields from non-finite date/timestamptz:
+--
+SELECT EXTRACT(HOUR FROM DATE 'infinity');      -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(HOUR FROM DATE '-infinity');     -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(HOUR FROM TIMESTAMP   'infinity');      -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(HOUR FROM TIMESTAMP   '-infinity');     -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(HOUR FROM TIMESTAMPTZ 'infinity');      -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(HOUR FROM TIMESTAMPTZ '-infinity');     -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+-- all possible fields
+SELECT EXTRACT(MICROSECONDS  FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(MILLISECONDS  FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(SECOND        FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(MINUTE        FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(HOUR          FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(DAY           FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(MONTH         FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(QUARTER       FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(WEEK          FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(DOW           FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(ISODOW        FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(DOY           FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(TIMEZONE      FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(TIMEZONE_M    FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+SELECT EXTRACT(TIMEZONE_H    FROM DATE 'infinity');    -- NULL
+ date_part 
+-----------
+          
+(1 row)
+
+--
+-- monotonic fields from non-finite date/timestamptz:
+--
+SELECT EXTRACT(EPOCH FROM DATE 'infinity');         --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM DATE '-infinity');        -- -Infinity
+ date_part 
+-----------
+ -Infinity
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMP   'infinity');  --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMP   '-infinity'); -- -Infinity
+ date_part 
+-----------
+ -Infinity
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ 'infinity');  --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '-infinity'); -- -Infinity
+ date_part 
+-----------
+ -Infinity
+(1 row)
+
+-- all possible fields
+SELECT EXTRACT(YEAR       FROM DATE 'infinity');    --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(DECADE     FROM DATE 'infinity');    --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(CENTURY    FROM DATE 'infinity');    --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(MILLENNIUM FROM DATE 'infinity');    --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(JULIAN     FROM DATE 'infinity');    --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(ISOYEAR    FROM DATE 'infinity');    --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+SELECT EXTRACT(EPOCH      FROM DATE 'infinity');    --  Infinity
+ date_part 
+-----------
+  Infinity
+(1 row)
+
+--
+-- wrong fields from non-finite date:
+--
+SELECT EXTRACT(MICROSEC  FROM DATE 'infinity');     -- ERROR:  timestamp units "microsec" not recognized
+ERROR:  timestamp units "microsec" not recognized
+CONTEXT:  SQL function "date_part" statement 1
+SELECT EXTRACT(UNDEFINED FROM DATE 'infinity');     -- ERROR:  timestamp units "undefined" not supported
+ERROR:  timestamp units "undefined" not supported
+CONTEXT:  SQL function "date_part" statement 1
 -- test constructors
 select make_date(2013, 7, 15);
  make_date  
diff --git a/src/test/regress/sql/date.sql b/src/test/regress/sql/date.sql
index a62e92a..e40b4c4 100644
--- a/src/test/regress/sql/date.sql
+++ b/src/test/regress/sql/date.sql
@@ -212,6 +212,12 @@ SELECT date 'tomorrow' - date 'yesterday' AS "Two days";
 --
 -- test extract!
 --
+-- epoch
+--
+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
+--
 -- century
 --
 SELECT EXTRACT(CENTURY FROM DATE '0101-12-31 BC'); -- -2
@@ -276,6 +282,53 @@ select 'infinity'::date, '-infinity'::date;
 select 'infinity'::date > 'today'::date as t;
 select '-infinity'::date < 'today'::date as t;
 select isfinite('infinity'::date), isfinite('-infinity'::date), isfinite('today'::date);
+--
+-- oscillating fields from non-finite date/timestamptz:
+--
+SELECT EXTRACT(HOUR FROM DATE 'infinity');      -- NULL
+SELECT EXTRACT(HOUR FROM DATE '-infinity');     -- NULL
+SELECT EXTRACT(HOUR FROM TIMESTAMP   'infinity');      -- NULL
+SELECT EXTRACT(HOUR FROM TIMESTAMP   '-infinity');     -- NULL
+SELECT EXTRACT(HOUR FROM TIMESTAMPTZ 'infinity');      -- NULL
+SELECT EXTRACT(HOUR FROM TIMESTAMPTZ '-infinity');     -- NULL
+-- all possible fields
+SELECT EXTRACT(MICROSECONDS  FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(MILLISECONDS  FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(SECOND        FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(MINUTE        FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(HOUR          FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(DAY           FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(MONTH         FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(QUARTER       FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(WEEK          FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(DOW           FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(ISODOW        FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(DOY           FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(TIMEZONE      FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(TIMEZONE_M    FROM DATE 'infinity');    -- NULL
+SELECT EXTRACT(TIMEZONE_H    FROM DATE 'infinity');    -- NULL
+--
+-- monotonic fields from non-finite date/timestamptz:
+--
+SELECT EXTRACT(EPOCH FROM DATE 'infinity');         --  Infinity
+SELECT EXTRACT(EPOCH FROM DATE '-infinity');        -- -Infinity
+SELECT EXTRACT(EPOCH FROM TIMESTAMP   'infinity');  --  Infinity
+SELECT EXTRACT(EPOCH FROM TIMESTAMP   '-infinity'); -- -Infinity
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ 'infinity');  --  Infinity
+SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '-infinity'); -- -Infinity
+-- all possible fields
+SELECT EXTRACT(YEAR       FROM DATE 'infinity');    --  Infinity
+SELECT EXTRACT(DECADE     FROM DATE 'infinity');    --  Infinity
+SELECT EXTRACT(CENTURY    FROM DATE 'infinity');    --  Infinity
+SELECT EXTRACT(MILLENNIUM FROM DATE 'infinity');    --  Infinity
+SELECT EXTRACT(JULIAN     FROM DATE 'infinity');    --  Infinity
+SELECT EXTRACT(ISOYEAR    FROM DATE 'infinity');    --  Infinity
+SELECT EXTRACT(EPOCH      FROM DATE 'infinity');    --  Infinity
+--
+-- wrong fields from non-finite date:
+--
+SELECT EXTRACT(MICROSEC  FROM DATE 'infinity');     -- ERROR:  timestamp units "microsec" not recognized
+SELECT EXTRACT(UNDEFINED FROM DATE 'infinity');     -- ERROR:  timestamp units "undefined" not supported
 
 -- test constructors
 select make_date(2013, 7, 15);
