diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index eaaffa7..5ebec5a 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -299,20 +299,27 @@ EncodeSpecialDate(DateADT dt, char *str)
 DateADT
 GetSQLCurrentDate(void)
 {
-	TimestampTz ts;
-	struct pg_tm tt,
-			   *tm = &tt;
-	fsec_t		fsec;
-	int			tz;
+	static DateADT		cache_date; /* cache date for current TX timestamp */
+	static TimestampTz	cache_ts;
+	TimestampTz			cur_ts = GetCurrentTransactionStartTimestamp();
 
-	ts = GetCurrentTransactionStartTimestamp();
+	if (cache_ts != cur_ts)
+	{
+		struct pg_tm	tt,
+					   *tm = &tt;
+		fsec_t			fsec;
+		int				tz;
 
-	if (timestamp2tm(ts, &tz, tm, &fsec, NULL, NULL) != 0)
-		ereport(ERROR,
+		if (timestamp2tm(cur_ts, &tz, tm, &fsec, NULL, NULL) != 0)
+			ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
 
-	return date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
+		cache_date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
+		cache_ts = cur_ts;
+	}
+
+	return cache_date;
 }
 
 /*
@@ -321,22 +328,24 @@ GetSQLCurrentDate(void)
 TimeTzADT *
 GetSQLCurrentTime(int32 typmod)
 {
-	TimeTzADT  *result;
-	TimestampTz ts;
-	struct pg_tm tt,
-			   *tm = &tt;
-	fsec_t		fsec;
-	int			tz;
-
-	ts = GetCurrentTransactionStartTimestamp();
+	static struct pg_tm	cache_pg_tm;	/* cache pg_tm for current TX timestamp */
+	static fsec_t		cache_fsec;		/* cache fsec for current TX timestamp */
+	static int			cache_tz;		/* cache tz for current TX timestamp */
+	static TimestampTz	cache_ts;
+	TimestampTz			cur_ts = GetCurrentTransactionStartTimestamp();
+	TimeTzADT  		   *result;
 
-	if (timestamp2tm(ts, &tz, tm, &fsec, NULL, NULL) != 0)
-		ereport(ERROR,
+	if (cache_ts != cur_ts)
+	{
+		if (timestamp2tm(cur_ts, &cache_tz, &cache_pg_tm, &cache_fsec, NULL, NULL) != 0)
+			ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
+		cache_ts = cur_ts;
+	}
 
 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
-	tm2timetz(tm, fsec, tz, result);
+	tm2timetz(&cache_pg_tm, cache_fsec, cache_tz, result);
 	AdjustTimeForTypmod(&(result->time), typmod);
 	return result;
 }
@@ -347,21 +356,24 @@ GetSQLCurrentTime(int32 typmod)
 TimeADT
 GetSQLLocalTime(int32 typmod)
 {
-	TimeADT		result;
-	TimestampTz ts;
-	struct pg_tm tt,
-			   *tm = &tt;
-	fsec_t		fsec;
-	int			tz;
+	static struct pg_tm	cache_pg_tm;	/* cache pg_tm for current TX timestamp */
+	static fsec_t		cache_fsec;		/* cache fsec for current TX timestamp */
+	static TimestampTz	cache_ts;
+	TimestampTz			cur_ts = GetCurrentTransactionStartTimestamp();
+	TimeADT				result;
 
-	ts = GetCurrentTransactionStartTimestamp();
+	if (cache_ts != cur_ts)
+	{
+		int tz;
 
-	if (timestamp2tm(ts, &tz, tm, &fsec, NULL, NULL) != 0)
-		ereport(ERROR,
+		if (timestamp2tm(cur_ts, &tz, &cache_pg_tm, &cache_fsec, NULL, NULL) != 0)
+			ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
+		cache_ts = cur_ts;
+	}
 
-	tm2time(tm, fsec, &result);
+	tm2time(&cache_pg_tm, cache_fsec, &result);
 	AdjustTimeForTypmod(&result, typmod);
 	return result;
 }
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index dec2fad..67d4268 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -344,12 +344,21 @@ j2day(int date)
 void
 GetCurrentDateTime(struct pg_tm *tm)
 {
-	int			tz;
-	fsec_t		fsec;
+	static struct pg_tm cache_pg_tm; /* Cache pg_tm for current TX timestamp */
+	static TimestampTz 	cache_ts;
+	TimestampTz 		cur_ts = GetCurrentTransactionStartTimestamp();
+
+	if (cache_ts != cur_ts)
+	{
+		int		tz;
+		fsec_t	fsec;
+
+		timestamp2tm(cur_ts, &tz, &cache_pg_tm, &fsec, NULL, NULL);
+		/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
+		cache_ts = cur_ts;
+	}
 
-	timestamp2tm(GetCurrentTransactionStartTimestamp(), &tz, tm, &fsec,
-				 NULL, NULL);
-	/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
+	*tm = cache_pg_tm;
 }
 
 /*
@@ -361,13 +370,23 @@ GetCurrentDateTime(struct pg_tm *tm)
 void
 GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
 {
-	int			tz;
+	static struct pg_tm cache_pg_tm;	/* cache pg_tm for current TX timestamp */
+	static fsec_t		cache_fsec;		/* cache fsec for current TX timestamp */
+	static int			cache_tz;		/* cache tz for current TX timestamp */
+	static TimestampTz	cache_ts;
+	TimestampTz 		cur_ts = GetCurrentTransactionStartTimestamp();
+
+	if (cache_ts != cur_ts)
+	{
+		timestamp2tm(cur_ts, &cache_tz, &cache_pg_tm, &cache_fsec, NULL, NULL);
+		/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
+		cache_ts = cur_ts;
+	}
 
-	timestamp2tm(GetCurrentTransactionStartTimestamp(), &tz, tm, fsec,
-				 NULL, NULL);
-	/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
+	*tm = cache_pg_tm;
+	*fsec = cache_fsec;
 	if (tzp != NULL)
-		*tzp = tz;
+		*tzp = cache_tz;
 }
 
 
