summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/json.c32
-rw-r--r--src/backend/utils/adt/jsonb.c27
-rw-r--r--src/backend/utils/adt/jsonb_util.c21
3 files changed, 71 insertions, 9 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 26d293709a..d4ba3bd87d 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -1506,7 +1506,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
{
char buf[MAXDATELEN + 1];
- JsonEncodeDateTime(buf, val, DATEOID);
+ JsonEncodeDateTime(buf, val, DATEOID, NULL);
appendStringInfo(result, "\"%s\"", buf);
}
break;
@@ -1514,7 +1514,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
{
char buf[MAXDATELEN + 1];
- JsonEncodeDateTime(buf, val, TIMESTAMPOID);
+ JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
appendStringInfo(result, "\"%s\"", buf);
}
break;
@@ -1522,7 +1522,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
{
char buf[MAXDATELEN + 1];
- JsonEncodeDateTime(buf, val, TIMESTAMPTZOID);
+ JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
appendStringInfo(result, "\"%s\"", buf);
}
break;
@@ -1550,10 +1550,11 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
/*
* Encode 'value' of datetime type 'typid' into JSON string in ISO format using
- * optionally preallocated buffer 'buf'.
+ * optionally preallocated buffer 'buf'. Optional 'tzp' determines time-zone
+ * offset (in seconds) in which we want to show timestamptz.
*/
char *
-JsonEncodeDateTime(char *buf, Datum value, Oid typid)
+JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
{
if (!buf)
buf = palloc(MAXDATELEN + 1);
@@ -1630,11 +1631,30 @@ JsonEncodeDateTime(char *buf, Datum value, Oid typid)
const char *tzn = NULL;
timestamp = DatumGetTimestampTz(value);
+
+ /*
+ * If a time zone is specified, we apply the time-zone shift,
+ * convert timestamptz to pg_tm as if it were without a time
+ * zone, and then use the specified time zone for converting
+ * the timestamp into a string.
+ */
+ if (tzp)
+ {
+ tz = *tzp;
+ timestamp -= (TimestampTz) tz * USECS_PER_SEC;
+ }
+
/* Same as timestamptz_out(), but forcing DateStyle */
if (TIMESTAMP_NOT_FINITE(timestamp))
EncodeSpecialTimestamp(timestamp, buf);
- else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
+ else if (timestamp2tm(timestamp, tzp ? NULL : &tz, &tm, &fsec,
+ tzp ? NULL : &tzn, NULL) == 0)
+ {
+ if (tzp)
+ tm.tm_isdst = 1; /* set time-zone presence flag */
+
EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
+ }
else
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 69f41ab455..74b4bbe44c 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -206,6 +206,24 @@ JsonbTypeName(JsonbValue *jbv)
return "boolean";
case jbvNull:
return "null";
+ case jbvDatetime:
+ switch (jbv->val.datetime.typid)
+ {
+ case DATEOID:
+ return "date";
+ case TIMEOID:
+ return "time without time zone";
+ case TIMETZOID:
+ return "time with time zone";
+ case TIMESTAMPOID:
+ return "timestamp without time zone";
+ case TIMESTAMPTZOID:
+ return "timestamp with time zone";
+ default:
+ elog(ERROR, "unrecognized jsonb value datetime type: %d",
+ jbv->val.datetime.typid);
+ }
+ return "unknown";
default:
elog(ERROR, "unrecognized jsonb value type: %d", jbv->type);
return "unknown";
@@ -805,17 +823,20 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
break;
case JSONBTYPE_DATE:
jb.type = jbvString;
- jb.val.string.val = JsonEncodeDateTime(NULL, val, DATEOID);
+ jb.val.string.val = JsonEncodeDateTime(NULL, val,
+ DATEOID, NULL);
jb.val.string.len = strlen(jb.val.string.val);
break;
case JSONBTYPE_TIMESTAMP:
jb.type = jbvString;
- jb.val.string.val = JsonEncodeDateTime(NULL, val, TIMESTAMPOID);
+ jb.val.string.val = JsonEncodeDateTime(NULL, val,
+ TIMESTAMPOID, NULL);
jb.val.string.len = strlen(jb.val.string.val);
break;
case JSONBTYPE_TIMESTAMPTZ:
jb.type = jbvString;
- jb.val.string.val = JsonEncodeDateTime(NULL, val, TIMESTAMPTZOID);
+ jb.val.string.val = JsonEncodeDateTime(NULL, val,
+ TIMESTAMPTZOID, NULL);
jb.val.string.len = strlen(jb.val.string.val);
break;
case JSONBTYPE_JSONCAST:
diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c
index 7e0d9de7f0..f7f79eb965 100644
--- a/src/backend/utils/adt/jsonb_util.c
+++ b/src/backend/utils/adt/jsonb_util.c
@@ -14,9 +14,12 @@
#include "postgres.h"
#include "catalog/pg_collation.h"
+#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "utils/builtins.h"
+#include "utils/datetime.h"
#include "utils/hashutils.h"
+#include "utils/jsonapi.h"
#include "utils/jsonb.h"
#include "utils/memutils.h"
#include "utils/varlena.h"
@@ -244,6 +247,8 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
break;
case jbvBinary:
elog(ERROR, "unexpected jbvBinary value");
+ case jbvDatetime:
+ elog(ERROR, "unexpected jbvDatetime value");
}
}
else
@@ -1786,6 +1791,22 @@ convertJsonbScalar(StringInfo buffer, JEntry *jentry, JsonbValue *scalarVal)
JENTRY_ISBOOL_TRUE : JENTRY_ISBOOL_FALSE;
break;
+ case jbvDatetime:
+ {
+ char buf[MAXDATELEN + 1];
+ size_t len;
+
+ JsonEncodeDateTime(buf,
+ scalarVal->val.datetime.value,
+ scalarVal->val.datetime.typid,
+ &scalarVal->val.datetime.tz);
+ len = strlen(buf);
+ appendToBuffer(buffer, buf, len);
+
+ *jentry = len;
+ }
+ break;
+
default:
elog(ERROR, "invalid jsonb scalar type");
}