#include "utils/typcache.h"
 #include "utils/syscache.h"
 
+/* String to output for infinite dates and timestamps */
+#define DT_INFINITY "\"infinity\""
+
 /*
  * The context of the parser is maintained by the recursive descent
  * mechanism, but is passed explicitly to the error reporting routine
 
                date = DatumGetDateADT(val);
 
-               /* XSD doesn't support infinite values */
                if (DATE_NOT_FINITE(date))
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("date out of range"),
-                            errdetail("JSON does not support infinite date values.")));
+               {
+                   /* we have to format infinity ourselves */
+                   appendStringInfoString(result,DT_INFINITY);
+               }
                else
                {
                    j2date(date + POSTGRES_EPOCH_JDATE,
                           &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
                    EncodeDateOnly(&tm, USE_XSD_DATES, buf);
+                   appendStringInfo(result, "\"%s\"", buf);
                }
-
-               appendStringInfo(result, "\"%s\"", buf);
            }
            break;
        case JSONTYPE_TIMESTAMP:
 
                timestamp = DatumGetTimestamp(val);
 
-               /* XSD doesn't support infinite values */
                if (TIMESTAMP_NOT_FINITE(timestamp))
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("timestamp out of range"),
-                            errdetail("JSON does not support infinite timestamp values.")));
+               {
+                   /* we have to format infinity ourselves */
+                   appendStringInfoString(result,DT_INFINITY);
+               }
                else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
+               {
                    EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
+                   appendStringInfo(result, "\"%s\"", buf);
+               }
                else
                    ereport(ERROR,
                            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                             errmsg("timestamp out of range")));
-
-               appendStringInfo(result, "\"%s\"", buf);
            }
            break;
        case JSONTYPE_TIMESTAMPTZ:
 
                timestamp = DatumGetTimestamp(val);
 
-               /* XSD doesn't support infinite values */
                if (TIMESTAMP_NOT_FINITE(timestamp))
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("timestamp out of range"),
-                            errdetail("JSON does not support infinite timestamp values.")));
+               {
+                   /* we have to format infinity ourselves */
+                   appendStringInfoString(result,DT_INFINITY);
+               }
                else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
+               {
                    EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
+                   appendStringInfo(result, "\"%s\"", buf);
+               }
                else
                    ereport(ERROR,
                            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                             errmsg("timestamp out of range")));
-
-               appendStringInfo(result, "\"%s\"", buf);
            }
            break;
        case JSONTYPE_JSON:
 
 #include "utils/syscache.h"
 #include "utils/typcache.h"
 
+/*
+ * String to output for infinite dates and timestamps.
+ * Note the we don't use embedded quotes, unlike for json, because
+ * we store jsonb strings dequoted.
+ */
+
+#define DT_INFINITY "infinity"
+
 typedef struct JsonbInState
 {
    JsonbParseState *parseState;
                char        buf[MAXDATELEN + 1];
 
                date = DatumGetDateADT(val);
+               jb.type = jbvString;
 
-               /* XSD doesn't support infinite values */
                if (DATE_NOT_FINITE(date))
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("date out of range"),
-                            errdetail("JSON does not support infinite date values.")));
+               {
+                   jb.val.string.len = strlen(DT_INFINITY);
+                   jb.val.string.val = pstrdup(DT_INFINITY);
+               }
                else
                {
                    j2date(date + POSTGRES_EPOCH_JDATE,
                           &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
                    EncodeDateOnly(&tm, USE_XSD_DATES, buf);
+                   jb.val.string.len = strlen(buf);
+                   jb.val.string.val = pstrdup(buf);
                }
-
-               jb.type = jbvString;
-               jb.val.string.len = strlen(buf);
-               jb.val.string.val = pstrdup(buf);
            }
            break;
            case JSONBTYPE_TIMESTAMP:
                    char        buf[MAXDATELEN + 1];
 
                    timestamp = DatumGetTimestamp(val);
+                   jb.type = jbvString;
 
-                   /* XSD doesn't support infinite values */
                    if (TIMESTAMP_NOT_FINITE(timestamp))
-                       ereport(ERROR,
-                               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                                errmsg("timestamp out of range"),
-                                errdetail("JSON does not support infinite timestamp values.")));
+                   {
+                       jb.val.string.len = strlen(DT_INFINITY);
+                       jb.val.string.val = pstrdup(DT_INFINITY);
+                   }
                    else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
+                   {
+
                        EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
+                       jb.val.string.len = strlen(buf);
+                       jb.val.string.val = pstrdup(buf);
+                   }
                    else
                        ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range")));
-
-                   jb.type = jbvString;
-                   jb.val.string.len = strlen(buf);
-                   jb.val.string.val = pstrdup(buf);
                }
                break;
            case JSONBTYPE_TIMESTAMPTZ:
                    char        buf[MAXDATELEN + 1];
 
                    timestamp = DatumGetTimestamp(val);
+                   jb.type = jbvString;
 
-                   /* XSD doesn't support infinite values */
                    if (TIMESTAMP_NOT_FINITE(timestamp))
-                       ereport(ERROR,
-                               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                                errmsg("timestamp out of range"),
-                                errdetail("JSON does not support infinite timestamp values.")));
+                   {
+                       jb.val.string.len = strlen(DT_INFINITY);
+                       jb.val.string.val = pstrdup(DT_INFINITY);
+                   }
                    else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
+                   {
                        EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
+                       jb.val.string.len = strlen(buf);
+                       jb.val.string.val = pstrdup(buf);
+                   }
                    else
                        ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range")));
-
-                   jb.type = jbvString;
-                   jb.val.string.len = strlen(buf);
-                   jb.val.string.val = pstrdup(buf);
                }
                break;
            case JSONBTYPE_JSONCAST:
 
 (1 row)
 
 COMMIT;
+select to_json(date '2014-05-28');
+   to_json    
+--------------
+ "2014-05-28"
+(1 row)
+
+select to_json(date 'Infinity');
+  to_json   
+------------
+ "infinity"
+(1 row)
+
+select to_json(timestamp 'Infinity');
+  to_json   
+------------
+ "infinity"
+(1 row)
+
+select to_json(timestamptz 'Infinity');
+  to_json   
+------------
+ "infinity"
+(1 row)
+
 --json_agg
 SELECT json_agg(q)
   FROM ( SELECT $$a$$ || x AS b, y AS c,
 
 (1 row)
 
 COMMIT;
+select to_json(date '2014-05-28');
+   to_json    
+--------------
+ "2014-05-28"
+(1 row)
+
+select to_json(date 'Infinity');
+  to_json   
+------------
+ "infinity"
+(1 row)
+
+select to_json(timestamp 'Infinity');
+  to_json   
+------------
+ "infinity"
+(1 row)
+
+select to_json(timestamptz 'Infinity');
+  to_json   
+------------
+ "infinity"
+(1 row)
+
 --json_agg
 SELECT json_agg(q)
   FROM ( SELECT $$a$$ || x AS b, y AS c,
 
 (1 row)
 
 COMMIT;
+select to_jsonb(date '2014-05-28');
+   to_jsonb   
+--------------
+ "2014-05-28"
+(1 row)
+
+select to_jsonb(date 'Infinity');
+  to_jsonb  
+------------
+ "infinity"
+(1 row)
+
+select to_jsonb(timestamp 'Infinity');
+  to_jsonb  
+------------
+ "infinity"
+(1 row)
+
+select to_jsonb(timestamptz 'Infinity');
+  to_jsonb  
+------------
+ "infinity"
+(1 row)
+
 --jsonb_agg
 CREATE TEMP TABLE rows AS
 SELECT x, 'txt' || x as y
 
 (1 row)
 
 COMMIT;
+select to_jsonb(date '2014-05-28');
+   to_jsonb   
+--------------
+ "2014-05-28"
+(1 row)
+
+select to_jsonb(date 'Infinity');
+  to_jsonb  
+------------
+ "infinity"
+(1 row)
+
+select to_jsonb(timestamp 'Infinity');
+  to_jsonb  
+------------
+ "infinity"
+(1 row)
+
+select to_jsonb(timestamptz 'Infinity');
+  to_jsonb  
+------------
+ "infinity"
+(1 row)
+
 --jsonb_agg
 CREATE TEMP TABLE rows AS
 SELECT x, 'txt' || x as y
 
 select to_json(timestamptz '2014-05-28 12:22:35.614298-04');
 COMMIT;
 
+select to_json(date '2014-05-28');
+
+select to_json(date 'Infinity');
+select to_json(timestamp 'Infinity');
+select to_json(timestamptz 'Infinity');
+
 --json_agg
 
 SELECT json_agg(q)
 
 select to_jsonb(timestamptz '2014-05-28 12:22:35.614298-04');
 COMMIT;
 
+select to_jsonb(date '2014-05-28');
+
+select to_jsonb(date 'Infinity');
+select to_jsonb(timestamp 'Infinity');
+select to_jsonb(timestamptz 'Infinity');
+
 --jsonb_agg
 
 CREATE TEMP TABLE rows AS