@@ -1503,12 +1503,70 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
15031503 pfree (outputstr );
15041504 break ;
15051505 case JSONTYPE_DATE :
1506+ {
1507+ char buf [MAXDATELEN + 1 ];
1508+
1509+ JsonEncodeDateTime (buf , val , DATEOID );
1510+ appendStringInfo (result , "\"%s\"" , buf );
1511+ }
1512+ break ;
1513+ case JSONTYPE_TIMESTAMP :
1514+ {
1515+ char buf [MAXDATELEN + 1 ];
1516+
1517+ JsonEncodeDateTime (buf , val , TIMESTAMPOID );
1518+ appendStringInfo (result , "\"%s\"" , buf );
1519+ }
1520+ break ;
1521+ case JSONTYPE_TIMESTAMPTZ :
1522+ {
1523+ char buf [MAXDATELEN + 1 ];
1524+
1525+ JsonEncodeDateTime (buf , val , TIMESTAMPTZOID );
1526+ appendStringInfo (result , "\"%s\"" , buf );
1527+ }
1528+ break ;
1529+ case JSONTYPE_JSON :
1530+ /* JSON and JSONB output will already be escaped */
1531+ outputstr = OidOutputFunctionCall (outfuncoid , val );
1532+ appendStringInfoString (result , outputstr );
1533+ pfree (outputstr );
1534+ break ;
1535+ case JSONTYPE_CAST :
1536+ /* outfuncoid refers to a cast function, not an output function */
1537+ jsontext = DatumGetTextPP (OidFunctionCall1 (outfuncoid , val ));
1538+ outputstr = text_to_cstring (jsontext );
1539+ appendStringInfoString (result , outputstr );
1540+ pfree (outputstr );
1541+ pfree (jsontext );
1542+ break ;
1543+ default :
1544+ outputstr = OidOutputFunctionCall (outfuncoid , val );
1545+ escape_json (result , outputstr );
1546+ pfree (outputstr );
1547+ break ;
1548+ }
1549+ }
1550+
1551+ /*
1552+ * Encode 'value' of datetime type 'typid' into JSON string in ISO format using
1553+ * optionally preallocated buffer 'buf'.
1554+ */
1555+ char *
1556+ JsonEncodeDateTime (char * buf , Datum value , Oid typid )
1557+ {
1558+ if (!buf )
1559+ buf = palloc (MAXDATELEN + 1 );
1560+
1561+ switch (typid )
1562+ {
1563+ case DATEOID :
15061564 {
15071565 DateADT date ;
15081566 struct pg_tm tm ;
1509- char buf [MAXDATELEN + 1 ];
15101567
1511- date = DatumGetDateADT (val );
1568+ date = DatumGetDateADT (value );
1569+
15121570 /* Same as date_out(), but forcing DateStyle */
15131571 if (DATE_NOT_FINITE (date ))
15141572 EncodeSpecialDate (date , buf );
@@ -1518,17 +1576,40 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
15181576 & (tm .tm_year ), & (tm .tm_mon ), & (tm .tm_mday ));
15191577 EncodeDateOnly (& tm , USE_XSD_DATES , buf );
15201578 }
1521- appendStringInfo (result , "\"%s\"" , buf );
15221579 }
15231580 break ;
1524- case JSONTYPE_TIMESTAMP :
1581+ case TIMEOID :
1582+ {
1583+ TimeADT time = DatumGetTimeADT (value );
1584+ struct pg_tm tt ,
1585+ * tm = & tt ;
1586+ fsec_t fsec ;
1587+
1588+ /* Same as time_out(), but forcing DateStyle */
1589+ time2tm (time , tm , & fsec );
1590+ EncodeTimeOnly (tm , fsec , false, 0 , USE_XSD_DATES , buf );
1591+ }
1592+ break ;
1593+ case TIMETZOID :
1594+ {
1595+ TimeTzADT * time = DatumGetTimeTzADTP (value );
1596+ struct pg_tm tt ,
1597+ * tm = & tt ;
1598+ fsec_t fsec ;
1599+ int tz ;
1600+
1601+ /* Same as timetz_out(), but forcing DateStyle */
1602+ timetz2tm (time , tm , & fsec , & tz );
1603+ EncodeTimeOnly (tm , fsec , true, tz , USE_XSD_DATES , buf );
1604+ }
1605+ break ;
1606+ case TIMESTAMPOID :
15251607 {
15261608 Timestamp timestamp ;
15271609 struct pg_tm tm ;
15281610 fsec_t fsec ;
1529- char buf [MAXDATELEN + 1 ];
15301611
1531- timestamp = DatumGetTimestamp (val );
1612+ timestamp = DatumGetTimestamp (value );
15321613 /* Same as timestamp_out(), but forcing DateStyle */
15331614 if (TIMESTAMP_NOT_FINITE (timestamp ))
15341615 EncodeSpecialTimestamp (timestamp , buf );
@@ -1538,19 +1619,17 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
15381619 ereport (ERROR ,
15391620 (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
15401621 errmsg ("timestamp out of range" )));
1541- appendStringInfo (result , "\"%s\"" , buf );
15421622 }
15431623 break ;
1544- case JSONTYPE_TIMESTAMPTZ :
1624+ case TIMESTAMPTZOID :
15451625 {
15461626 TimestampTz timestamp ;
15471627 struct pg_tm tm ;
15481628 int tz ;
15491629 fsec_t fsec ;
15501630 const char * tzn = NULL ;
1551- char buf [MAXDATELEN + 1 ];
15521631
1553- timestamp = DatumGetTimestampTz (val );
1632+ timestamp = DatumGetTimestampTz (value );
15541633 /* Same as timestamptz_out(), but forcing DateStyle */
15551634 if (TIMESTAMP_NOT_FINITE (timestamp ))
15561635 EncodeSpecialTimestamp (timestamp , buf );
@@ -1560,29 +1639,14 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
15601639 ereport (ERROR ,
15611640 (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
15621641 errmsg ("timestamp out of range" )));
1563- appendStringInfo (result , "\"%s\"" , buf );
15641642 }
15651643 break ;
1566- case JSONTYPE_JSON :
1567- /* JSON and JSONB output will already be escaped */
1568- outputstr = OidOutputFunctionCall (outfuncoid , val );
1569- appendStringInfoString (result , outputstr );
1570- pfree (outputstr );
1571- break ;
1572- case JSONTYPE_CAST :
1573- /* outfuncoid refers to a cast function, not an output function */
1574- jsontext = DatumGetTextPP (OidFunctionCall1 (outfuncoid , val ));
1575- outputstr = text_to_cstring (jsontext );
1576- appendStringInfoString (result , outputstr );
1577- pfree (outputstr );
1578- pfree (jsontext );
1579- break ;
15801644 default :
1581- outputstr = OidOutputFunctionCall (outfuncoid , val );
1582- escape_json (result , outputstr );
1583- pfree (outputstr );
1584- break ;
1645+ elog (ERROR , "unknown jsonb value datetime type oid %d" , typid );
1646+ return NULL ;
15851647 }
1648+
1649+ return buf ;
15861650}
15871651
15881652/*
0 commit comments