From b4daf5b14a31c3eb004a7429e0e96cce71ac2c25 Mon Sep 17 00:00:00 2001
From: Jeevan Chalke <jeevan.chalke@enterprisedb.com>
Date: Mon, 28 Aug 2023 18:43:06 +0530
Subject: [PATCH v1 2/4] Implement .date(), .time(), .time_tz(), .timestamp(),
 and .timestamp_tz() methods

This commit implements jsonpath .date(), .time(), .time_tz(),
.timestamp(), .timestamp_tz() methods.  The JSON string representing
a valid date/time is converted to the specific date or time type
representation.

The changes use the infrastructure of the .datetime() method and
perform the datatype conversion as appropriate.  All these methods
accept no argument and use ISO datetime formats.

Jeevan Chalke
---
 doc/src/sgml/func.sgml                       |  70 +++
 src/backend/utils/adt/jsonpath.c             |  42 ++
 src/backend/utils/adt/jsonpath_exec.c        | 197 ++++++-
 src/backend/utils/adt/jsonpath_gram.y        |  11 +
 src/backend/utils/adt/jsonpath_scan.l        |   5 +
 src/include/utils/jsonpath.h                 |   5 +
 src/test/regress/expected/jsonb_jsonpath.out | 804 ++++++++++++++++++++++++++-
 src/test/regress/expected/jsonpath.out       |  30 +
 src/test/regress/sql/jsonb_jsonpath.sql      | 245 ++++++++
 src/test/regress/sql/jsonpath.sql            |   5 +
 10 files changed, 1401 insertions(+), 13 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index ca9899f..fdf2995 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -17650,6 +17650,76 @@ strict $.**.HR
 
       <row>
        <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>string</replaceable> <literal>.</literal> <literal>date()</literal>
+        <returnvalue><replaceable>date</replaceable></returnvalue>
+       </para>
+       <para>
+        Date value converted from a string
+       </para>
+       <para>
+        <literal>jsonb_path_query('"2023-08-15"', '$.date()')</literal>
+        <returnvalue>"2023-08-15"</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>string</replaceable> <literal>.</literal> <literal>time()</literal>
+        <returnvalue><replaceable>time without time zone</replaceable></returnvalue>
+       </para>
+       <para>
+        Time without time zone value converted from a string
+       </para>
+       <para>
+        <literal>jsonb_path_query('"12:34:56"', '$.time()')</literal>
+        <returnvalue>"12:34:56"</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>string</replaceable> <literal>.</literal> <literal>time_tz()</literal>
+        <returnvalue><replaceable>time with time zone</replaceable></returnvalue>
+       </para>
+       <para>
+        Time with time zone value converted from a string
+       </para>
+       <para>
+        <literal>jsonb_path_query('"12:34:56 +05:30"', '$.time_tz()')</literal>
+        <returnvalue>"12:34:56+05:30"</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>string</replaceable> <literal>.</literal> <literal>timestamp()</literal>
+        <returnvalue><replaceable>timestamp without time zone</replaceable></returnvalue>
+       </para>
+       <para>
+        Timestamp without time zone value converted from a string
+       </para>
+       <para>
+        <literal>jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp()')</literal>
+        <returnvalue>"2023-08-15T12:34:56"</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <replaceable>string</replaceable> <literal>.</literal> <literal>timestamp_tz()</literal>
+        <returnvalue><replaceable>timestamp with time zone</replaceable></returnvalue>
+       </para>
+       <para>
+        Timestamp with time zone value converted from a string
+       </para>
+       <para>
+        <literal>jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()')</literal>
+        <returnvalue>"2023-08-15T12:34:56+05:30"</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
         <replaceable>object</replaceable> <literal>.</literal> <literal>keyvalue()</literal>
         <returnvalue><replaceable>array</replaceable></returnvalue>
        </para>
diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c
index f45f919..70987cd 100644
--- a/src/backend/utils/adt/jsonpath.c
+++ b/src/backend/utils/adt/jsonpath.c
@@ -368,6 +368,12 @@ flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext,
 				*(int32 *) (buf->data + arg) = chld - pos;
 			}
 			break;
+		case jpiDate:
+		case jpiTime:
+		case jpiTimeTz:
+		case jpiTimestamp:
+		case jpiTimestampTz:
+			break;
 		case jpiNull:
 			break;
 		case jpiRoot:
@@ -751,6 +757,21 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
 			}
 			appendStringInfoChar(buf, ')');
 			break;
+		case jpiDate:
+			appendStringInfoString(buf, ".date()");
+			break;
+		case jpiTime:
+			appendStringInfoString(buf, ".time()");
+			break;
+		case jpiTimeTz:
+			appendStringInfoString(buf, ".time_tz()");
+			break;
+		case jpiTimestamp:
+			appendStringInfoString(buf, ".timestamp()");
+			break;
+		case jpiTimestampTz:
+			appendStringInfoString(buf, ".timestamp_tz()");
+			break;
 		case jpiKeyValue:
 			appendStringInfoString(buf, ".keyvalue()");
 			break;
@@ -821,6 +842,16 @@ jspOperationName(JsonPathItemType type)
 			return "ceiling";
 		case jpiDatetime:
 			return "datetime";
+		case jpiDate:
+			return "date";
+		case jpiTime:
+			return "time";
+		case jpiTimeTz:
+			return "time_tz";
+		case jpiTimestamp:
+			return "timestamp";
+		case jpiTimestampTz:
+			return "timestamp_tz";
 		default:
 			elog(ERROR, "unrecognized jsonpath item type: %d", type);
 			return NULL;
@@ -962,6 +993,12 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
 		case jpiDatetime:
 			read_int32(v->content.arg, base, pos);
 			break;
+		case jpiDate:
+		case jpiTime:
+		case jpiTimeTz:
+		case jpiTimestamp:
+		case jpiTimestampTz:
+			break;
 		case jpiIndexArray:
 			read_int32(v->content.array.nelems, base, pos);
 			read_int32_n(v->content.array.elems, base, pos,
@@ -1037,6 +1074,11 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
 			   v->type == jpiInteger ||
 			   v->type == jpiNumber ||
 			   v->type == jpiDatetime ||
+			   v->type == jpiDate ||
+			   v->type == jpiTime ||
+			   v->type == jpiTimeTz ||
+			   v->type == jpiTimestamp ||
+			   v->type == jpiTimestampTz ||
 			   v->type == jpiKeyValue ||
 			   v->type == jpiStartsWith ||
 			   v->type == jpiLikeRegex);
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index ff7fdaf..dbf4315 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -1289,6 +1289,11 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 			break;
 
 		case jpiDatetime:
+		case jpiDate:
+		case jpiTime:
+		case jpiTimeTz:
+		case jpiTimestamp:
+		case jpiTimestampTz:
 			if (unwrap && JsonbType(jb) == jbvArray)
 				return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
 
@@ -1961,11 +1966,14 @@ executeNumericItemMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 }
 
 /*
- * Implementation of the .datetime() method.
+ * Implementation of the .datetime() and related methods.
  *
  * Converts a string into a date/time value. The actual type is determined at run time.
  * If an argument is provided, this argument is used as a template string.
  * Otherwise, the first fitting ISO format is selected.
+ *
+ * .date(), .time(), .time_tz(), .timestamp(), .timestamp_tz() methods don't
+ * have a format, so ISO format is used.
  */
 static JsonPathExecResult
 executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
@@ -1998,7 +2006,11 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	 */
 	collid = DEFAULT_COLLATION_OID;
 
-	if (jsp->content.arg)
+	/*
+	 * .datetime(template) has an argument, the rest of the methods don't have
+	 * an argument.  So we handle that separately.
+	 */
+	if (jsp->type == jpiDatetime && jsp->content.arg)
 	{
 		text	   *template;
 		char	   *template_str;
@@ -2086,11 +2098,182 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 		}
 
 		if (res == jperNotFound)
-			RETURN_ERROR(ereport(ERROR,
-								 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
-								  errmsg("datetime format is not recognized: \"%s\"",
-										 text_to_cstring(datetime)),
-								  errhint("Use a datetime template argument to specify the input data format."))));
+		{
+			if (jsp->type == jpiDatetime)
+				RETURN_ERROR(ereport(ERROR,
+									 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
+									  errmsg("datetime format is not recognized: \"%s\"",
+											 text_to_cstring(datetime)),
+									  errhint("Use a datetime template argument to specify the input data format."))));
+			else
+				RETURN_ERROR(ereport(ERROR,
+									 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
+									  errmsg("%s format is not recognized: \"%s\"",
+											 jspOperationName(jsp->type), text_to_cstring(datetime)))));
+
+		}
+	}
+
+	/*
+	 * parse_datetime() processes the entire input string per the template or
+	 * ISO format and returns the Datum in best fitted datetime type.  So, if
+	 * this call is for a specific datatype, then we do the conversion here.
+	 * Throw an error for incompatible types.
+	 */
+	switch (jsp->type)
+	{
+		case jpiDatetime:					/* Nothing to do for DATETIME */
+			break;
+		case jpiDate:
+			{
+				/* Convert result type to date */
+				switch (typid)
+				{
+					case DATEOID:			/* Nothing to do for DATE */
+						break;
+					case TIMEOID:
+					case TIMETZOID:
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
+											  errmsg("date format is not recognized: \"%s\"",
+													 text_to_cstring(datetime)))));
+						break;
+					case TIMESTAMPOID:
+						value = DirectFunctionCall1(timestamp_date,
+													value);
+						break;
+					case TIMESTAMPTZOID:
+						value = DirectFunctionCall1(timestamptz_date,
+													value);
+						break;
+					default:
+						elog(ERROR, "type with oid %d not supported", typid);
+				}
+
+				typid = DATEOID;
+			}
+			break;
+		case jpiTime:
+			{
+				/* Convert result type to time without time zone */
+				switch (typid)
+				{
+					case TIMEOID:			/* Nothing to do for TIME */
+						break;
+					case DATEOID:
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
+											  errmsg("time format is not recognized: \"%s\"",
+													 text_to_cstring(datetime)))));
+						break;
+					case TIMETZOID:
+						value = DirectFunctionCall1(timetz_time,
+													value);
+						break;
+					case TIMESTAMPOID:
+						value = DirectFunctionCall1(timestamp_time,
+													value);
+						break;
+					case TIMESTAMPTZOID:
+						value = DirectFunctionCall1(timestamptz_time,
+													value);
+						break;
+					default:
+						elog(ERROR, "type with oid %d not supported", typid);
+				}
+
+				typid = TIMEOID;
+			}
+			break;
+		case jpiTimeTz:
+			{
+				/* Convert result type to time with time zone */
+				switch (typid)
+				{
+					case TIMETZOID:			/* Nothing to do for TIMETZ */
+						break;
+					case DATEOID:
+					case TIMESTAMPOID:
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
+											  errmsg("time_tz format is not recognized: \"%s\"",
+													 text_to_cstring(datetime)))));
+						break;
+					case TIMEOID:
+						value = DirectFunctionCall1(time_timetz,
+													value);
+						break;
+					case TIMESTAMPTZOID:
+						value = DirectFunctionCall1(timestamptz_timetz,
+													value);
+						break;
+					default:
+						elog(ERROR, "type with oid %d not supported", typid);
+				}
+
+				typid = TIMETZOID;
+			}
+			break;
+		case jpiTimestamp:
+			{
+				/* Convert result type to timestamp without time zone */
+				switch (typid)
+				{
+					case TIMESTAMPOID:		/* Nothing to do for TIMESTAMP */
+						break;
+					case TIMEOID:
+					case TIMETZOID:
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
+											  errmsg("timestamp format is not recognized: \"%s\"",
+													 text_to_cstring(datetime)))));
+						break;
+					case DATEOID:
+						value = DirectFunctionCall1(date_timestamp,
+													value);
+						break;
+					case TIMESTAMPTZOID:
+						value = DirectFunctionCall1(timestamptz_timestamp,
+													value);
+						break;
+					default:
+						elog(ERROR, "type with oid %d not supported", typid);
+				}
+
+				typid = TIMESTAMPOID;
+			}
+			break;
+		case jpiTimestampTz:
+			{
+				/* Convert result type to timestamp with time zone */
+				switch (typid)
+				{
+					case TIMESTAMPTZOID:	/* Nothing to do for TIMESTAMPTZ */
+						break;
+					case TIMEOID:
+					case TIMETZOID:
+						RETURN_ERROR(ereport(ERROR,
+											 (errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
+											  errmsg("timestamp_tz format is not recognized: \"%s\"",
+													 text_to_cstring(datetime)))));
+						break;
+					case DATEOID:
+						value = DirectFunctionCall1(date_timestamptz,
+													value);
+						break;
+					case TIMESTAMPOID:
+						value = DirectFunctionCall1(timestamp_timestamptz,
+													value);
+						break;
+					default:
+						elog(ERROR, "type with oid %d not supported", typid);
+				}
+
+				typid = TIMESTAMPTZOID;
+			}
+			break;
+		default:
+			elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
 	}
 
 	pfree(datetime);
diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y
index 340caa9..53baa0e 100644
--- a/src/backend/utils/adt/jsonpath_gram.y
+++ b/src/backend/utils/adt/jsonpath_gram.y
@@ -82,6 +82,7 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr,
 %token	<str>		ANY_P STRICT_P LAX_P LAST_P STARTS_P WITH_P LIKE_REGEX_P FLAG_P
 %token	<str>		ABS_P SIZE_P TYPE_P FLOOR_P DOUBLE_P CEILING_P KEYVALUE_P
 %token	<str>		DATETIME_P
+%token	<str>		DATE_P TIME_P TIME_TZ_P TIMESTAMP_P TIMESTAMP_TZ_P
 %token	<str>		BIGINT_P INTEGER_P NUMBER_P
 
 %type	<result>	result
@@ -289,6 +290,11 @@ key_name:
 	| NUMBER_P
 	| CEILING_P
 	| DATETIME_P
+	| DATE_P
+	| TIME_P
+	| TIME_TZ_P
+	| TIMESTAMP_P
+	| TIMESTAMP_TZ_P
 	| KEYVALUE_P
 	| LAST_P
 	| STARTS_P
@@ -308,6 +314,11 @@ method:
 	| NUMBER_P						{ $$ = jpiNumber; }
 	| CEILING_P						{ $$ = jpiCeiling; }
 	| KEYVALUE_P					{ $$ = jpiKeyValue; }
+	| DATE_P						{ $$ = jpiDate; }
+	| TIME_P						{ $$ = jpiTime; }
+	| TIME_TZ_P						{ $$ = jpiTimeTz; }
+	| TIMESTAMP_P					{ $$ = jpiTimestamp; }
+	| TIMESTAMP_TZ_P				{ $$ = jpiTimestampTz; }
 	;
 %%
 
diff --git a/src/backend/utils/adt/jsonpath_scan.l b/src/backend/utils/adt/jsonpath_scan.l
index 1abcea3..2847865 100644
--- a/src/backend/utils/adt/jsonpath_scan.l
+++ b/src/backend/utils/adt/jsonpath_scan.l
@@ -401,10 +401,12 @@ static const JsonPathKeyword keywords[] = {
 	{ 2, false,	TO_P,		"to"},
 	{ 3, false,	ABS_P,		"abs"},
 	{ 3, false,	LAX_P,		"lax"},
+	{ 4, false,	DATE_P,		"date"},
 	{ 4, false,	FLAG_P,		"flag"},
 	{ 4, false,	LAST_P,		"last"},
 	{ 4, true,	NULL_P,		"null"},
 	{ 4, false,	SIZE_P,		"size"},
+	{ 4, false,	TIME_P,		"time"},
 	{ 4, true,	TRUE_P,		"true"},
 	{ 4, false,	TYPE_P,		"type"},
 	{ 4, false,	WITH_P,		"with"},
@@ -418,10 +420,13 @@ static const JsonPathKeyword keywords[] = {
 	{ 6, false,	STRICT_P,	"strict"},
 	{ 7, false,	CEILING_P,	"ceiling"},
 	{ 7, false,	INTEGER_P,	"integer"},
+	{ 7, false,	TIME_TZ_P,	"time_tz"},
 	{ 7, false,	UNKNOWN_P,	"unknown"},
 	{ 8, false,	DATETIME_P,	"datetime"},
 	{ 8, false,	KEYVALUE_P,	"keyvalue"},
+	{ 9, false,	TIMESTAMP_P, "timestamp"},
 	{ 10,false, LIKE_REGEX_P, "like_regex"},
+	{ 12,false, TIMESTAMP_TZ_P, "timestamp_tz"},
 };
 
 /* Check if current scanstring value is a keyword */
diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h
index 9fe161f..d73d297 100644
--- a/src/include/utils/jsonpath.h
+++ b/src/include/utils/jsonpath.h
@@ -93,6 +93,11 @@ typedef enum JsonPathItemType
 	jpiInteger,					/* .integer() item method */
 	jpiNumber,					/* .number() item method */
 	jpiDatetime,				/* .datetime() item method */
+	jpiDate,					/* .date() item method */
+	jpiTime,					/* .time() item method */
+	jpiTimeTz,					/* .time_tz() item method */
+	jpiTimestamp,				/* .timestamp() item method */
+	jpiTimestampTz,				/* .timestamp_tz() item method */
 	jpiKeyValue,				/* .keyvalue() item method */
 	jpiSubscript,				/* array subscript: 'expr' or 'expr TO expr' */
 	jpiLast,					/* LAST array subscript */
diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out
index c7d1a4e..d7cfa43 100644
--- a/src/test/regress/expected/jsonb_jsonpath.out
+++ b/src/test/regress/expected/jsonb_jsonpath.out
@@ -2061,7 +2061,271 @@ select jsonb_path_query('"10-03-2017t12:34:56"', '$.datetime("dd-mm-yyyy\"T\"HH2
 ERROR:  unmatched format character "T"
 select jsonb_path_query('"10-03-2017 12:34:56"', '$.datetime("dd-mm-yyyy\"T\"HH24:MI:SS")');
 ERROR:  unmatched format character "T"
+-- Test .date()
+select jsonb_path_query('null', '$.date()');
+ERROR:  jsonpath item method .date() can only be applied to a string
+select jsonb_path_query('true', '$.date()');
+ERROR:  jsonpath item method .date() can only be applied to a string
+select jsonb_path_query('1', '$.date()');
+ERROR:  jsonpath item method .date() can only be applied to a string
+select jsonb_path_query('[]', '$.date()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.date()');
+ERROR:  jsonpath item method .date() can only be applied to a string
+select jsonb_path_query('{}', '$.date()');
+ERROR:  jsonpath item method .date() can only be applied to a string
+select jsonb_path_query('"bogus"', '$.date()');
+ERROR:  date format is not recognized: "bogus"
+select jsonb '"2023-08-15"' @? '$.date()';
+ ?column? 
+----------
+ t
+(1 row)
+
+select jsonb_path_query('"2023-08-15"', '$.date()');
+ jsonb_path_query 
+------------------
+ "2023-08-15"
+(1 row)
+
+select jsonb_path_query('"2023-08-15"', '$.date().type()');
+ jsonb_path_query 
+------------------
+ "date"
+(1 row)
+
+select jsonb_path_query('"12:34:56"', '$.date()');
+ERROR:  date format is not recognized: "12:34:56"
+select jsonb_path_query('"12:34:56 +05:30"', '$.date()');
+ERROR:  date format is not recognized: "12:34:56 +05:30"
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.date()');
+ jsonb_path_query 
+------------------
+ "2023-08-15"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.date()');
+ jsonb_path_query 
+------------------
+ "2023-08-15"
+(1 row)
+
+-- Test .time()
+select jsonb_path_query('null', '$.time()');
+ERROR:  jsonpath item method .time() can only be applied to a string
+select jsonb_path_query('true', '$.time()');
+ERROR:  jsonpath item method .time() can only be applied to a string
+select jsonb_path_query('1', '$.time()');
+ERROR:  jsonpath item method .time() can only be applied to a string
+select jsonb_path_query('[]', '$.time()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.time()');
+ERROR:  jsonpath item method .time() can only be applied to a string
+select jsonb_path_query('{}', '$.time()');
+ERROR:  jsonpath item method .time() can only be applied to a string
+select jsonb_path_query('"bogus"', '$.time()');
+ERROR:  time format is not recognized: "bogus"
+select jsonb '"12:34:56"' @? '$.time()';
+ ?column? 
+----------
+ t
+(1 row)
+
+select jsonb_path_query('"12:34:56"', '$.time()');
+ jsonb_path_query 
+------------------
+ "12:34:56"
+(1 row)
+
+select jsonb_path_query('"12:34:56"', '$.time().type()');
+     jsonb_path_query     
+--------------------------
+ "time without time zone"
+(1 row)
+
+select jsonb_path_query('"2023-08-15"', '$.time()');
+ERROR:  time format is not recognized: "2023-08-15"
+select jsonb_path_query('"12:34:56 +05:30"', '$.time()');
+ jsonb_path_query 
+------------------
+ "12:34:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.time()');
+ jsonb_path_query 
+------------------
+ "12:34:56"
+(1 row)
+
+-- Test .time_tz()
+select jsonb_path_query('null', '$.time_tz()');
+ERROR:  jsonpath item method .time_tz() can only be applied to a string
+select jsonb_path_query('true', '$.time_tz()');
+ERROR:  jsonpath item method .time_tz() can only be applied to a string
+select jsonb_path_query('1', '$.time_tz()');
+ERROR:  jsonpath item method .time_tz() can only be applied to a string
+select jsonb_path_query('[]', '$.time_tz()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.time_tz()');
+ERROR:  jsonpath item method .time_tz() can only be applied to a string
+select jsonb_path_query('{}', '$.time_tz()');
+ERROR:  jsonpath item method .time_tz() can only be applied to a string
+select jsonb_path_query('"bogus"', '$.time_tz()');
+ERROR:  time_tz format is not recognized: "bogus"
+select jsonb '"12:34:56 +05:30"' @? '$.time_tz()';
+ ?column? 
+----------
+ t
+(1 row)
+
+select jsonb_path_query('"12:34:56 +05:30"', '$.time_tz()');
+ jsonb_path_query 
+------------------
+ "12:34:56+05:30"
+(1 row)
+
+select jsonb_path_query('"12:34:56 +05:30"', '$.time_tz().type()');
+   jsonb_path_query    
+-----------------------
+ "time with time zone"
+(1 row)
+
+select jsonb_path_query('"2023-08-15"', '$.time_tz()');
+ERROR:  time_tz format is not recognized: "2023-08-15"
+select jsonb_path_query('"12:34:56"', '$.time_tz()');
+ jsonb_path_query 
+------------------
+ "12:34:56-07:00"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.time_tz()');
+ERROR:  time_tz format is not recognized: "2023-08-15 12:34:56"
+-- Test .timestamp()
+select jsonb_path_query('null', '$.timestamp()');
+ERROR:  jsonpath item method .timestamp() can only be applied to a string
+select jsonb_path_query('true', '$.timestamp()');
+ERROR:  jsonpath item method .timestamp() can only be applied to a string
+select jsonb_path_query('1', '$.timestamp()');
+ERROR:  jsonpath item method .timestamp() can only be applied to a string
+select jsonb_path_query('[]', '$.timestamp()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.timestamp()');
+ERROR:  jsonpath item method .timestamp() can only be applied to a string
+select jsonb_path_query('{}', '$.timestamp()');
+ERROR:  jsonpath item method .timestamp() can only be applied to a string
+select jsonb_path_query('"bogus"', '$.timestamp()');
+ERROR:  timestamp format is not recognized: "bogus"
+select jsonb '"2023-08-15 12:34:56"' @? '$.timestamp()';
+ ?column? 
+----------
+ t
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp()');
+   jsonb_path_query    
+-----------------------
+ "2023-08-15T12:34:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().type()');
+       jsonb_path_query        
+-------------------------------
+ "timestamp without time zone"
+(1 row)
+
+select jsonb_path_query('"2023-08-15"', '$.timestamp()');
+   jsonb_path_query    
+-----------------------
+ "2023-08-15T00:00:00"
+(1 row)
+
+select jsonb_path_query('"12:34:56"', '$.timestamp()');
+ERROR:  timestamp format is not recognized: "12:34:56"
+select jsonb_path_query('"12:34:56 +05:30"', '$.timestamp()');
+ERROR:  timestamp format is not recognized: "12:34:56 +05:30"
+-- Test .timestamp_tz()
+select jsonb_path_query('null', '$.timestamp_tz()');
+ERROR:  jsonpath item method .timestamp_tz() can only be applied to a string
+select jsonb_path_query('true', '$.timestamp_tz()');
+ERROR:  jsonpath item method .timestamp_tz() can only be applied to a string
+select jsonb_path_query('1', '$.timestamp_tz()');
+ERROR:  jsonpath item method .timestamp_tz() can only be applied to a string
+select jsonb_path_query('[]', '$.timestamp_tz()');
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('[]', 'strict $.timestamp_tz()');
+ERROR:  jsonpath item method .timestamp_tz() can only be applied to a string
+select jsonb_path_query('{}', '$.timestamp_tz()');
+ERROR:  jsonpath item method .timestamp_tz() can only be applied to a string
+select jsonb_path_query('"bogus"', '$.timestamp_tz()');
+ERROR:  timestamp_tz format is not recognized: "bogus"
+select jsonb '"2023-08-15 12:34:56 +05:30"' @? '$.timestamp_tz()';
+ ?column? 
+----------
+ t
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()');
+      jsonb_path_query       
+-----------------------------
+ "2023-08-15T12:34:56+05:30"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz().type()');
+      jsonb_path_query      
+----------------------------
+ "timestamp with time zone"
+(1 row)
+
+select jsonb_path_query('"2023-08-15"', '$.timestamp_tz()');
+      jsonb_path_query       
+-----------------------------
+ "2023-08-15T07:00:00+00:00"
+(1 row)
+
+select jsonb_path_query('"12:34:56"', '$.timestamp_tz()');
+ERROR:  timestamp_tz format is not recognized: "12:34:56"
+select jsonb_path_query('"12:34:56 +05:30"', '$.timestamp_tz()');
+ERROR:  timestamp_tz format is not recognized: "12:34:56 +05:30"
 set time zone '+00';
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time()');
+ jsonb_path_query 
+------------------
+ "07:04:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time_tz()');
+ jsonb_path_query 
+------------------
+ "07:04:56+00:00"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp()');
+   jsonb_path_query    
+-----------------------
+ "2023-08-15T07:04:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp_tz()');
+      jsonb_path_query       
+-----------------------------
+ "2023-08-15T12:34:56+00:00"
+(1 row)
+
 select jsonb_path_query('"10-03-2017 12:34"', '$.datetime("dd-mm-yyyy HH24:MI")');
    jsonb_path_query    
 -----------------------
@@ -2127,6 +2391,36 @@ select jsonb_path_query('"12:34 -05:20"', '$.datetime("HH24:MI TZH:TZM")');
 (1 row)
 
 set time zone '+10';
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time()');
+ jsonb_path_query 
+------------------
+ "17:04:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time_tz()');
+ jsonb_path_query 
+------------------
+ "17:04:56+10:00"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp()');
+   jsonb_path_query    
+-----------------------
+ "2023-08-15T17:04:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp_tz()');
+      jsonb_path_query       
+-----------------------------
+ "2023-08-15T02:34:56+00:00"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()');
+      jsonb_path_query       
+-----------------------------
+ "2023-08-15T12:34:56+05:30"
+(1 row)
+
 select jsonb_path_query('"10-03-2017 12:34"', '$.datetime("dd-mm-yyyy HH24:MI")');
    jsonb_path_query    
 -----------------------
@@ -2192,6 +2486,30 @@ select jsonb_path_query('"12:34 -05:20"', '$.datetime("HH24:MI TZH:TZM")');
 (1 row)
 
 set time zone default;
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time()');
+ jsonb_path_query 
+------------------
+ "00:04:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time_tz()');
+ jsonb_path_query 
+------------------
+ "00:04:56-07:00"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp()');
+   jsonb_path_query    
+-----------------------
+ "2023-08-15T00:04:56"
+(1 row)
+
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()');
+      jsonb_path_query       
+-----------------------------
+ "2023-08-15T12:34:56+05:30"
+(1 row)
+
 select jsonb_path_query('"2017-03-10"', '$.datetime().type()');
  jsonb_path_query 
 ------------------
@@ -2348,6 +2666,101 @@ select jsonb_path_query_tz(
  "2017-03-10T01:02:03+04:00"
 (2 rows)
 
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].datetime() ? (@ == "2017-03-10".date())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10"
+ "2017-03-10T00:00:00"
+ "2017-03-10T03:00:00+03:00"
+(3 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].datetime() ? (@ >= "2017-03-10".date())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10"
+ "2017-03-11"
+ "2017-03-10T00:00:00"
+ "2017-03-10T12:34:56"
+ "2017-03-10T03:00:00+03:00"
+(5 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].datetime() ? (@ <  "2017-03-10".date())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-09"
+ "2017-03-10T01:02:03+04:00"
+(2 rows)
+
+select jsonb_path_query(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ == "2017-03-10".date())');
+ jsonb_path_query 
+------------------
+ "2017-03-10"
+ "2017-03-10"
+ "2017-03-10"
+ "2017-03-10"
+(4 rows)
+
+select jsonb_path_query(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ >= "2017-03-10".date())');
+ jsonb_path_query 
+------------------
+ "2017-03-10"
+ "2017-03-11"
+ "2017-03-10"
+ "2017-03-10"
+ "2017-03-10"
+(5 rows)
+
+select jsonb_path_query(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ <  "2017-03-10".date())');
+ jsonb_path_query 
+------------------
+ "2017-03-09"
+ "2017-03-09"
+(2 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ == "2017-03-10".date())');
+ jsonb_path_query_tz 
+---------------------
+ "2017-03-10"
+ "2017-03-10"
+ "2017-03-10"
+ "2017-03-10"
+(4 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ >= "2017-03-10".date())');
+ jsonb_path_query_tz 
+---------------------
+ "2017-03-10"
+ "2017-03-11"
+ "2017-03-10"
+ "2017-03-10"
+ "2017-03-10"
+(5 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ <  "2017-03-10".date())');
+ jsonb_path_query_tz 
+---------------------
+ "2017-03-09"
+ "2017-03-09"
+(2 rows)
+
 -- time comparison
 select jsonb_path_query(
 	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
@@ -2393,12 +2806,107 @@ select jsonb_path_query_tz(
  "13:35:00+01:00"
 (3 rows)
 
--- timetz comparison
-select jsonb_path_query(
-	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00 +1"]',
-	'$[*].datetime() ? (@ == "12:35 +1".datetime("HH24:MI TZH"))');
-ERROR:  cannot convert value from time to timetz without time zone usage
-HINT:  Use *_tz() function for time zone support.
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].datetime() ? (@ == "12:35:00".time())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00"
+ "12:35:00+00:00"
+(2 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].datetime() ? (@ >= "12:35:00".time())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00"
+ "12:36:00"
+ "12:35:00+00:00"
+(3 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].datetime() ? (@ <  "12:35:00".time())');
+ jsonb_path_query_tz 
+---------------------
+ "12:34:00"
+ "12:35:00+01:00"
+ "13:35:00+01:00"
+(3 rows)
+
+select jsonb_path_query(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ == "12:35:00".time())');
+ jsonb_path_query 
+------------------
+ "12:35:00"
+ "12:35:00"
+ "12:35:00"
+ "12:35:00"
+(4 rows)
+
+select jsonb_path_query(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ >= "12:35:00".time())');
+ jsonb_path_query 
+------------------
+ "12:35:00"
+ "12:36:00"
+ "12:35:00"
+ "12:35:00"
+ "13:35:00"
+ "12:35:00"
+(6 rows)
+
+select jsonb_path_query(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ <  "12:35:00".time())');
+ jsonb_path_query 
+------------------
+ "12:34:00"
+ "11:35:00"
+(2 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ == "12:35:00".time())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00"
+ "12:35:00"
+ "12:35:00"
+ "12:35:00"
+(4 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ >= "12:35:00".time())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00"
+ "12:36:00"
+ "12:35:00"
+ "12:35:00"
+ "13:35:00"
+ "12:35:00"
+(6 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ <  "12:35:00".time())');
+ jsonb_path_query_tz 
+---------------------
+ "12:34:00"
+ "11:35:00"
+(2 rows)
+
+-- timetz comparison
+select jsonb_path_query(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].datetime() ? (@ == "12:35 +1".datetime("HH24:MI TZH"))');
+ERROR:  cannot convert value from time to timetz without time zone usage
+HINT:  Use *_tz() function for time zone support.
 select jsonb_path_query(
 	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00 +1"]',
 	'$[*].datetime() ? (@ >= "12:35 +1".datetime("HH24:MI TZH"))');
@@ -2439,6 +2947,98 @@ select jsonb_path_query_tz(
  "10:35:00"
 (3 rows)
 
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].datetime() ? (@ == "12:35:00 +1".time_tz())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00+01:00"
+(1 row)
+
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].datetime() ? (@ >= "12:35:00 +1".time_tz())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00+01:00"
+ "12:36:00+01:00"
+ "12:35:00-02:00"
+ "11:35:00"
+ "12:35:00"
+(5 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].datetime() ? (@ <  "12:35:00 +1".time_tz())');
+ jsonb_path_query_tz 
+---------------------
+ "12:34:00+01:00"
+ "12:35:00+02:00"
+ "10:35:00"
+(3 rows)
+
+select jsonb_path_query(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ == "12:35:00 +1".time_tz())');
+ jsonb_path_query 
+------------------
+ "12:35:00+01:00"
+(1 row)
+
+select jsonb_path_query(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ >= "12:35:00 +1".time_tz())');
+ jsonb_path_query 
+------------------
+ "12:35:00+01:00"
+ "12:36:00+01:00"
+ "12:35:00-02:00"
+ "11:35:00+00:00"
+ "12:35:00+00:00"
+ "11:35:00+00:00"
+(6 rows)
+
+select jsonb_path_query(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ <  "12:35:00 +1".time_tz())');
+ jsonb_path_query 
+------------------
+ "12:34:00+01:00"
+ "12:35:00+02:00"
+ "10:35:00+00:00"
+(3 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ == "12:35:00 +1".time_tz())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00+01:00"
+(1 row)
+
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ >= "12:35:00 +1".time_tz())');
+ jsonb_path_query_tz 
+---------------------
+ "12:35:00+01:00"
+ "12:36:00+01:00"
+ "12:35:00-02:00"
+ "11:35:00+00:00"
+ "12:35:00+00:00"
+ "11:35:00+00:00"
+(6 rows)
+
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ <  "12:35:00 +1".time_tz())');
+ jsonb_path_query_tz 
+---------------------
+ "12:34:00+01:00"
+ "12:35:00+02:00"
+ "10:35:00+00:00"
+(3 rows)
+
 -- timestamp comparison
 select jsonb_path_query(
 	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11", "12:34:56", "12:34:56+01"]',
@@ -2486,6 +3086,99 @@ select jsonb_path_query_tz(
  "2017-03-10"
 (3 rows)
 
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ == "2017-03-10 12:35:00".timestamp())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:35:00"
+ "2017-03-10T13:35:00+01:00"
+(2 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ >= "2017-03-10 12:35:00".timestamp())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:35:00"
+ "2017-03-10T12:36:00"
+ "2017-03-10T13:35:00+01:00"
+ "2017-03-10T12:35:00-01:00"
+ "2017-03-11"
+(5 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ < "2017-03-10 12:35:00".timestamp())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:34:00"
+ "2017-03-10T12:35:00+01:00"
+ "2017-03-10"
+(3 rows)
+
+select jsonb_path_query(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ == "2017-03-10 12:35:00".timestamp())');
+   jsonb_path_query    
+-----------------------
+ "2017-03-10T12:35:00"
+ "2017-03-10T12:35:00"
+(2 rows)
+
+select jsonb_path_query(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ >= "2017-03-10 12:35:00".timestamp())');
+   jsonb_path_query    
+-----------------------
+ "2017-03-10T12:35:00"
+ "2017-03-10T12:36:00"
+ "2017-03-10T12:35:00"
+ "2017-03-10T13:35:00"
+ "2017-03-11T00:00:00"
+(5 rows)
+
+select jsonb_path_query(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ < "2017-03-10 12:35:00".timestamp())');
+   jsonb_path_query    
+-----------------------
+ "2017-03-10T12:34:00"
+ "2017-03-10T11:35:00"
+ "2017-03-10T00:00:00"
+(3 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ == "2017-03-10 12:35:00".timestamp())');
+  jsonb_path_query_tz  
+-----------------------
+ "2017-03-10T12:35:00"
+ "2017-03-10T12:35:00"
+(2 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ >= "2017-03-10 12:35:00".timestamp())');
+  jsonb_path_query_tz  
+-----------------------
+ "2017-03-10T12:35:00"
+ "2017-03-10T12:36:00"
+ "2017-03-10T12:35:00"
+ "2017-03-10T13:35:00"
+ "2017-03-11T00:00:00"
+(5 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ < "2017-03-10 12:35:00".timestamp())');
+  jsonb_path_query_tz  
+-----------------------
+ "2017-03-10T12:34:00"
+ "2017-03-10T11:35:00"
+ "2017-03-10T00:00:00"
+(3 rows)
+
 -- timestamptz comparison
 select jsonb_path_query(
 	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11", "12:34:56", "12:34:56+01"]',
@@ -2535,6 +3228,105 @@ select jsonb_path_query_tz(
  "2017-03-10"
 (4 rows)
 
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ == "2017-03-10 12:35:00 +1".timestamp_tz())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:35:00+01:00"
+ "2017-03-10T11:35:00"
+(2 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ >= "2017-03-10 12:35:00 +1".timestamp_tz())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:35:00+01:00"
+ "2017-03-10T12:36:00+01:00"
+ "2017-03-10T12:35:00-02:00"
+ "2017-03-10T11:35:00"
+ "2017-03-10T12:35:00"
+ "2017-03-11"
+(6 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ < "2017-03-10 12:35:00 +1".timestamp_tz())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:34:00+01:00"
+ "2017-03-10T12:35:00+02:00"
+ "2017-03-10T10:35:00"
+ "2017-03-10"
+(4 rows)
+
+select jsonb_path_query(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ == "2017-03-10 12:35:00 +1".timestamp_tz())');
+      jsonb_path_query       
+-----------------------------
+ "2017-03-10T12:35:00+01:00"
+ "2017-03-10T11:35:00+00:00"
+(2 rows)
+
+select jsonb_path_query(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ >= "2017-03-10 12:35:00 +1".timestamp_tz())');
+      jsonb_path_query       
+-----------------------------
+ "2017-03-10T12:35:00+01:00"
+ "2017-03-10T12:36:00+01:00"
+ "2017-03-10T12:35:00-02:00"
+ "2017-03-10T11:35:00+00:00"
+ "2017-03-10T12:35:00+00:00"
+ "2017-03-11T00:00:00+00:00"
+(6 rows)
+
+select jsonb_path_query(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ < "2017-03-10 12:35:00 +1".timestamp_tz())');
+      jsonb_path_query       
+-----------------------------
+ "2017-03-10T12:34:00+01:00"
+ "2017-03-10T12:35:00+02:00"
+ "2017-03-10T10:35:00+00:00"
+ "2017-03-10T00:00:00+00:00"
+(4 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ == "2017-03-10 12:35:00 +1".timestamp_tz())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:35:00+01:00"
+ "2017-03-10T11:35:00+00:00"
+(2 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ >= "2017-03-10 12:35:00 +1".timestamp_tz())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:35:00+01:00"
+ "2017-03-10T12:36:00+01:00"
+ "2017-03-10T12:35:00-02:00"
+ "2017-03-10T11:35:00+00:00"
+ "2017-03-10T12:35:00+00:00"
+ "2017-03-11T00:00:00+00:00"
+(6 rows)
+
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ < "2017-03-10 12:35:00 +1".timestamp_tz())');
+     jsonb_path_query_tz     
+-----------------------------
+ "2017-03-10T12:34:00+01:00"
+ "2017-03-10T12:35:00+02:00"
+ "2017-03-10T10:35:00+00:00"
+ "2017-03-10T00:00:00+00:00"
+(4 rows)
+
 -- overflow during comparison
 select jsonb_path_query('"1000000-01-01"', '$.datetime() > "2020-01-01 12:00:00".datetime()'::jsonpath);
  jsonb_path_query 
diff --git a/src/test/regress/expected/jsonpath.out b/src/test/regress/expected/jsonpath.out
index eeffb38..0a666a3 100644
--- a/src/test/regress/expected/jsonpath.out
+++ b/src/test/regress/expected/jsonpath.out
@@ -405,6 +405,36 @@ select '$.datetime("datetime template")'::jsonpath;
  $.datetime("datetime template")
 (1 row)
 
+select '$.date()'::jsonpath;
+ jsonpath 
+----------
+ $.date()
+(1 row)
+
+select '$.time()'::jsonpath;
+ jsonpath 
+----------
+ $.time()
+(1 row)
+
+select '$.time_tz()'::jsonpath;
+  jsonpath   
+-------------
+ $.time_tz()
+(1 row)
+
+select '$.timestamp()'::jsonpath;
+   jsonpath    
+---------------
+ $.timestamp()
+(1 row)
+
+select '$.timestamp_tz()'::jsonpath;
+     jsonpath     
+------------------
+ $.timestamp_tz()
+(1 row)
+
 select '$ ? (@ starts with "abc")'::jsonpath;
         jsonpath         
 -------------------------
diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql
index a9240c2..e3ed7c9 100644
--- a/src/test/regress/sql/jsonb_jsonpath.sql
+++ b/src/test/regress/sql/jsonb_jsonpath.sql
@@ -458,8 +458,100 @@ select jsonb_path_query('"10-03-2017T12:34:56"', '$.datetime("dd-mm-yyyy\"T\"HH2
 select jsonb_path_query('"10-03-2017t12:34:56"', '$.datetime("dd-mm-yyyy\"T\"HH24:MI:SS")');
 select jsonb_path_query('"10-03-2017 12:34:56"', '$.datetime("dd-mm-yyyy\"T\"HH24:MI:SS")');
 
+-- Test .date()
+select jsonb_path_query('null', '$.date()');
+select jsonb_path_query('true', '$.date()');
+select jsonb_path_query('1', '$.date()');
+select jsonb_path_query('[]', '$.date()');
+select jsonb_path_query('[]', 'strict $.date()');
+select jsonb_path_query('{}', '$.date()');
+select jsonb_path_query('"bogus"', '$.date()');
+
+select jsonb '"2023-08-15"' @? '$.date()';
+select jsonb_path_query('"2023-08-15"', '$.date()');
+select jsonb_path_query('"2023-08-15"', '$.date().type()');
+
+select jsonb_path_query('"12:34:56"', '$.date()');
+select jsonb_path_query('"12:34:56 +05:30"', '$.date()');
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.date()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.date()');
+
+-- Test .time()
+select jsonb_path_query('null', '$.time()');
+select jsonb_path_query('true', '$.time()');
+select jsonb_path_query('1', '$.time()');
+select jsonb_path_query('[]', '$.time()');
+select jsonb_path_query('[]', 'strict $.time()');
+select jsonb_path_query('{}', '$.time()');
+select jsonb_path_query('"bogus"', '$.time()');
+
+select jsonb '"12:34:56"' @? '$.time()';
+select jsonb_path_query('"12:34:56"', '$.time()');
+select jsonb_path_query('"12:34:56"', '$.time().type()');
+
+select jsonb_path_query('"2023-08-15"', '$.time()');
+select jsonb_path_query('"12:34:56 +05:30"', '$.time()');
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.time()');
+
+-- Test .time_tz()
+select jsonb_path_query('null', '$.time_tz()');
+select jsonb_path_query('true', '$.time_tz()');
+select jsonb_path_query('1', '$.time_tz()');
+select jsonb_path_query('[]', '$.time_tz()');
+select jsonb_path_query('[]', 'strict $.time_tz()');
+select jsonb_path_query('{}', '$.time_tz()');
+select jsonb_path_query('"bogus"', '$.time_tz()');
+
+select jsonb '"12:34:56 +05:30"' @? '$.time_tz()';
+select jsonb_path_query('"12:34:56 +05:30"', '$.time_tz()');
+select jsonb_path_query('"12:34:56 +05:30"', '$.time_tz().type()');
+
+select jsonb_path_query('"2023-08-15"', '$.time_tz()');
+select jsonb_path_query('"12:34:56"', '$.time_tz()');
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.time_tz()');
+
+-- Test .timestamp()
+select jsonb_path_query('null', '$.timestamp()');
+select jsonb_path_query('true', '$.timestamp()');
+select jsonb_path_query('1', '$.timestamp()');
+select jsonb_path_query('[]', '$.timestamp()');
+select jsonb_path_query('[]', 'strict $.timestamp()');
+select jsonb_path_query('{}', '$.timestamp()');
+select jsonb_path_query('"bogus"', '$.timestamp()');
+
+select jsonb '"2023-08-15 12:34:56"' @? '$.timestamp()';
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp()');
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().type()');
+
+select jsonb_path_query('"2023-08-15"', '$.timestamp()');
+select jsonb_path_query('"12:34:56"', '$.timestamp()');
+select jsonb_path_query('"12:34:56 +05:30"', '$.timestamp()');
+
+-- Test .timestamp_tz()
+select jsonb_path_query('null', '$.timestamp_tz()');
+select jsonb_path_query('true', '$.timestamp_tz()');
+select jsonb_path_query('1', '$.timestamp_tz()');
+select jsonb_path_query('[]', '$.timestamp_tz()');
+select jsonb_path_query('[]', 'strict $.timestamp_tz()');
+select jsonb_path_query('{}', '$.timestamp_tz()');
+select jsonb_path_query('"bogus"', '$.timestamp_tz()');
+
+select jsonb '"2023-08-15 12:34:56 +05:30"' @? '$.timestamp_tz()';
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz().type()');
+
+select jsonb_path_query('"2023-08-15"', '$.timestamp_tz()');
+select jsonb_path_query('"12:34:56"', '$.timestamp_tz()');
+select jsonb_path_query('"12:34:56 +05:30"', '$.timestamp_tz()');
+
+
 set time zone '+00';
 
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time_tz()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp()');
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp_tz()');
+
 select jsonb_path_query('"10-03-2017 12:34"', '$.datetime("dd-mm-yyyy HH24:MI")');
 select jsonb_path_query('"10-03-2017 12:34"', '$.datetime("dd-mm-yyyy HH24:MI TZH")');
 select jsonb_path_query('"10-03-2017 12:34 +05"', '$.datetime("dd-mm-yyyy HH24:MI TZH")');
@@ -475,6 +567,12 @@ select jsonb_path_query('"12:34 -05:20"', '$.datetime("HH24:MI TZH:TZM")');
 
 set time zone '+10';
 
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time_tz()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp()');
+select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp_tz()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()');
+
 select jsonb_path_query('"10-03-2017 12:34"', '$.datetime("dd-mm-yyyy HH24:MI")');
 select jsonb_path_query('"10-03-2017 12:34"', '$.datetime("dd-mm-yyyy HH24:MI TZH")');
 select jsonb_path_query('"10-03-2017 12:34 +05"', '$.datetime("dd-mm-yyyy HH24:MI TZH")');
@@ -490,6 +588,11 @@ select jsonb_path_query('"12:34 -05:20"', '$.datetime("HH24:MI TZH:TZM")');
 
 set time zone default;
 
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.time_tz()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp()');
+select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()');
+
 select jsonb_path_query('"2017-03-10"', '$.datetime().type()');
 select jsonb_path_query('"2017-03-10"', '$.datetime()');
 select jsonb_path_query('"2017-03-10 12:34:56"', '$.datetime().type()');
@@ -532,6 +635,34 @@ select jsonb_path_query_tz(
 	'["2017-03-10", "2017-03-11", "2017-03-09", "12:34:56", "01:02:03+04", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
 	'$[*].datetime() ? (@ <  "10.03.2017".datetime("dd.mm.yyyy"))');
 
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].datetime() ? (@ == "2017-03-10".date())');
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].datetime() ? (@ >= "2017-03-10".date())');
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].datetime() ? (@ <  "2017-03-10".date())');
+select jsonb_path_query(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ == "2017-03-10".date())');
+select jsonb_path_query(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ >= "2017-03-10".date())');
+select jsonb_path_query(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ <  "2017-03-10".date())');
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ == "2017-03-10".date())');
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ >= "2017-03-10".date())');
+select jsonb_path_query_tz(
+	'["2017-03-10", "2017-03-11", "2017-03-09", "2017-03-10 00:00:00", "2017-03-10 12:34:56", "2017-03-10 01:02:03+04", "2017-03-10 03:00:00+03"]',
+	'$[*].date() ? (@ <  "2017-03-10".date())');
+
 -- time comparison
 select jsonb_path_query(
 	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
@@ -552,6 +683,35 @@ select jsonb_path_query_tz(
 	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
 	'$[*].datetime() ? (@ <  "12:35".datetime("HH24:MI"))');
 
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].datetime() ? (@ == "12:35:00".time())');
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].datetime() ? (@ >= "12:35:00".time())');
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].datetime() ? (@ <  "12:35:00".time())');
+select jsonb_path_query(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ == "12:35:00".time())');
+select jsonb_path_query(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ >= "12:35:00".time())');
+select jsonb_path_query(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ <  "12:35:00".time())');
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ == "12:35:00".time())');
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ >= "12:35:00".time())');
+select jsonb_path_query_tz(
+	'["12:34:00", "12:35:00", "12:36:00", "12:35:00+00", "12:35:00+01", "13:35:00+01", "2017-03-10 12:35:00", "2017-03-10 12:35:00+01"]',
+	'$[*].time() ? (@ <  "12:35:00".time())');
+
+
 -- timetz comparison
 select jsonb_path_query(
 	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00 +1"]',
@@ -572,6 +732,34 @@ select jsonb_path_query_tz(
 	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10", "2017-03-10 12:35:00", "2017-03-10 12:35:00 +1"]',
 	'$[*].datetime() ? (@ <  "12:35 +1".datetime("HH24:MI TZH"))');
 
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].datetime() ? (@ == "12:35:00 +1".time_tz())');
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].datetime() ? (@ >= "12:35:00 +1".time_tz())');
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].datetime() ? (@ <  "12:35:00 +1".time_tz())');
+select jsonb_path_query(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ == "12:35:00 +1".time_tz())');
+select jsonb_path_query(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ >= "12:35:00 +1".time_tz())');
+select jsonb_path_query(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ <  "12:35:00 +1".time_tz())');
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ == "12:35:00 +1".time_tz())');
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ >= "12:35:00 +1".time_tz())');
+select jsonb_path_query_tz(
+	'["12:34:00+01", "12:35:00+01", "12:36:00+01", "12:35:00+02", "12:35:00-02", "10:35:00", "11:35:00", "12:35:00", "2017-03-10 12:35:00 +1"]',
+	'$[*].time_tz() ? (@ <  "12:35:00 +1".time_tz())');
+
 -- timestamp comparison
 select jsonb_path_query(
 	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11", "12:34:56", "12:34:56+01"]',
@@ -592,6 +780,34 @@ select jsonb_path_query_tz(
 	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11", "12:34:56", "12:34:56+01"]',
 	'$[*].datetime() ? (@ < "10.03.2017 12:35".datetime("dd.mm.yyyy HH24:MI"))');
 
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ == "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ >= "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ < "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ == "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ >= "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ < "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ == "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ >= "2017-03-10 12:35:00".timestamp())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00", "2017-03-10 12:35:00", "2017-03-10 12:36:00", "2017-03-10 12:35:00+01", "2017-03-10 13:35:00+01", "2017-03-10 12:35:00-01", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp() ? (@ < "2017-03-10 12:35:00".timestamp())');
+
 -- timestamptz comparison
 select jsonb_path_query(
 	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11", "12:34:56", "12:34:56+01"]',
@@ -612,6 +828,35 @@ select jsonb_path_query_tz(
 	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11", "12:34:56", "12:34:56+01"]',
 	'$[*].datetime() ? (@ < "10.03.2017 12:35 +1".datetime("dd.mm.yyyy HH24:MI TZH"))');
 
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ == "2017-03-10 12:35:00 +1".timestamp_tz())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ >= "2017-03-10 12:35:00 +1".timestamp_tz())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].datetime() ? (@ < "2017-03-10 12:35:00 +1".timestamp_tz())');
+
+select jsonb_path_query(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ == "2017-03-10 12:35:00 +1".timestamp_tz())');
+select jsonb_path_query(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ >= "2017-03-10 12:35:00 +1".timestamp_tz())');
+select jsonb_path_query(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ < "2017-03-10 12:35:00 +1".timestamp_tz())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ == "2017-03-10 12:35:00 +1".timestamp_tz())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ >= "2017-03-10 12:35:00 +1".timestamp_tz())');
+select jsonb_path_query_tz(
+	'["2017-03-10 12:34:00+01", "2017-03-10 12:35:00+01", "2017-03-10 12:36:00+01", "2017-03-10 12:35:00+02", "2017-03-10 12:35:00-02", "2017-03-10 10:35:00", "2017-03-10 11:35:00", "2017-03-10 12:35:00", "2017-03-10", "2017-03-11"]',
+	'$[*].timestamp_tz() ? (@ < "2017-03-10 12:35:00 +1".timestamp_tz())');
+
 -- overflow during comparison
 select jsonb_path_query('"1000000-01-01"', '$.datetime() > "2020-01-01 12:00:00".datetime()'::jsonpath);
 
diff --git a/src/test/regress/sql/jsonpath.sql b/src/test/regress/sql/jsonpath.sql
index 56e0bef..b39aefd 100644
--- a/src/test/regress/sql/jsonpath.sql
+++ b/src/test/regress/sql/jsonpath.sql
@@ -73,6 +73,11 @@ select '$.double().floor().ceiling().abs()'::jsonpath;
 select '$.keyvalue().key'::jsonpath;
 select '$.datetime()'::jsonpath;
 select '$.datetime("datetime template")'::jsonpath;
+select '$.date()'::jsonpath;
+select '$.time()'::jsonpath;
+select '$.time_tz()'::jsonpath;
+select '$.timestamp()'::jsonpath;
+select '$.timestamp_tz()'::jsonpath;
 
 select '$ ? (@ starts with "abc")'::jsonpath;
 select '$ ? (@ starts with $var)'::jsonpath;
-- 
1.8.3.1

