On Jul 9, 2024, at 11:08, Junwang Zhao <zhjw...@gmail.com> wrote: > In JsonbValue.val.datatime, there is a tz field, I think that's where > the offset stored, it is 18000 in the first example > > struct > { > Datum value; > Oid typid; > int32 typmod; > int tz; /* Numeric time zone, in seconds, for > * TimestampTz data type */ > } datetime;
Oooh, okay, so it’s a jsonb variant of the type. Interesting. Ah, and it’s assigned here[1]: jb->val.datetime.tz = tz; It seems like JSONB timestamptz values want to display the recorded time zone, so I suspect we need to set it when the converting from a non-tz to a local tz setting, something like this: ``` patch diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index d79c929822..f63b3b9330 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -2707,12 +2707,16 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, break; case jpiTimestampTz: { + struct pg_tm *tm; /* Convert result type to timestamp with time zone */ switch (typid) { case DATEOID: checkTimezoneIsUsedForCast(cxt->useTz, "date", "timestamptz"); + if (timestamp2tm(DatumGetTimestamp(value), NULL, tm, NULL, NULL, NULL) == 0) { + tz = DetermineTimeZoneOffset(tm, session_timezone); + } value = DirectFunctionCall1(date_timestamptz, value); break; @@ -2726,6 +2730,9 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, case TIMESTAMPOID: checkTimezoneIsUsedForCast(cxt->useTz, "timestamp", "timestamptz"); + if (timestamp2tm(DatumGetTimestamp(value), NULL, tm, NULL, NULL, NULL) == 0) { + tz = DetermineTimeZoneOffset(tm, session_timezone); + } value = DirectFunctionCall1(timestamp_timestamptz, value); break; ``` Only, you know, doesn’t crash the server. Best, David [1]: https://github.com/postgres/postgres/blob/629520be5f9da9d0192c7f6c8796bfddb4746760/src/backend/utils/adt/jsonpath_exec.c#L2784