OSDN Git Service

Fix date/time formats for XML Schema output.
authorPeter Eisentraut <peter_e@gmx.net>
Thu, 1 Mar 2007 14:52:04 +0000 (14:52 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Thu, 1 Mar 2007 14:52:04 +0000 (14:52 +0000)
Pavel Stehule

src/backend/utils/adt/datetime.c
src/backend/utils/adt/xml.c
src/include/miscadmin.h

index 6154c96..1be6e09 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.177 2007/02/19 17:41:39 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.178 2007/03/01 14:52:03 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3153,7 +3153,7 @@ datebsearch(const char *key, const datetkn *base, int nel)
  *             Append representation of a numeric timezone offset to str.
  */
 static void
-EncodeTimezone(char *str, int tz)
+EncodeTimezone(char *str, int tz, int style)
 {
        int                     hour,
                                min,
@@ -3171,7 +3171,7 @@ EncodeTimezone(char *str, int tz)
 
        if (sec != 0)
                sprintf(str, "%02d:%02d:%02d", hour, min, sec);
-       else if (min != 0)
+       else if (min != 0 || style == USE_XSD_DATES)
                sprintf(str, "%02d:%02d", hour, min);
        else
                sprintf(str, "%02d", hour);
@@ -3189,6 +3189,7 @@ EncodeDateOnly(struct pg_tm * tm, int style, char *str)
        switch (style)
        {
                case USE_ISO_DATES:
+               case USE_XSD_DATES:
                        /* compatible with ISO date formats */
                        if (tm->tm_year > 0)
                                sprintf(str, "%04d-%02d-%02d",
@@ -3266,7 +3267,7 @@ EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str)
                sprintf(str + strlen(str), ":%02d", tm->tm_sec);
 
        if (tzp != NULL)
-               EncodeTimezone(str, *tzp);
+               EncodeTimezone(str, *tzp, style);
 
        return TRUE;
 }      /* EncodeTimeOnly() */
@@ -3279,6 +3280,7 @@ EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str)
  *     SQL - mm/dd/yyyy hh:mm:ss.ss tz
  *     ISO - yyyy-mm-dd hh:mm:ss+/-tz
  *     German - dd.mm.yyyy hh:mm:ss tz
+ *     XSD - yyyy-mm-ddThh:mm:ss.ss+/-tz
  * Variants (affects order of month and day for Postgres and SQL styles):
  *     US - mm/dd/yyyy
  *     European - dd/mm/yyyy
@@ -3297,11 +3299,18 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
        switch (style)
        {
                case USE_ISO_DATES:
+               case USE_XSD_DATES:
                        /* Compatible with ISO-8601 date formats */
 
-                       sprintf(str, "%04d-%02d-%02d %02d:%02d",
+                       if (style == USE_ISO_DATES)
+                               sprintf(str, "%04d-%02d-%02d %02d:%02d",
                                        (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
                                        tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
+                       else
+                               sprintf(str, "%04d-%02d-%02dT%02d:%02d",
+                                       (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
+                                       tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
+
 
                        /*
                         * Print fractional seconds if any.  The field widths here should
@@ -3333,7 +3342,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
                         * a valid time zone translation.
                         */
                        if (tzp != NULL && tm->tm_isdst >= 0)
-                               EncodeTimezone(str, *tzp);
+                               EncodeTimezone(str, *tzp, style);
 
                        if (tm->tm_year <= 0)
                                sprintf(str + strlen(str), " BC");
@@ -3379,7 +3388,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
                                if (*tzn != NULL)
                                        sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
                                else
-                                       EncodeTimezone(str, *tzp);
+                                       EncodeTimezone(str, *tzp, style);
                        }
 
                        if (tm->tm_year <= 0)
@@ -3423,7 +3432,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
                                if (*tzn != NULL)
                                        sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
                                else
-                                       EncodeTimezone(str, *tzp);
+                                       EncodeTimezone(str, *tzp, style);
                        }
 
                        if (tm->tm_year <= 0)
@@ -3486,7 +3495,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
                                         * the date/time parser later. - thomas 2001-10-19
                                         */
                                        sprintf(str + strlen(str), " ");
-                                       EncodeTimezone(str, *tzp);
+                                       EncodeTimezone(str, *tzp, style);
                                }
                        }
 
index c12522c..547d98d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.32 2007/02/27 23:48:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.33 2007/03/01 14:52:04 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,6 +63,8 @@
 #include "parser/parse_expr.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
+#include "utils/date.h"
+#include "utils/datetime.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/xml.h"
@@ -1513,12 +1515,81 @@ map_sql_value_to_xml_value(Datum value, Oid type)
                bool isvarlena;
                char *p, *str;
 
-               if (type == BOOLOID)
+               /*
+                * Special XSD formatting for some data types
+                */
+               switch (type)
                {
-                       if (DatumGetBool(value))
-                               return "true";
-                       else
-                               return "false";
+                       case BOOLOID:
+                               if (DatumGetBool(value))
+                                       return "true";
+                               else
+                                       return "false";
+
+                       case DATEOID:
+                       {
+                               DateADT         date;
+                               struct pg_tm tm;
+                               char            buf[MAXDATELEN + 1];
+
+                               date = DatumGetDateADT(value);
+                               j2date(date + POSTGRES_EPOCH_JDATE,
+                                          &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
+                               EncodeDateOnly(&tm, USE_XSD_DATES, buf);
+
+                               return pstrdup(buf);
+                       }
+
+                       case TIMESTAMPOID:
+                       {
+                               Timestamp       timestamp;
+                               struct pg_tm tm;
+                               fsec_t          fsec;
+                               char       *tzn = NULL;
+                               char            buf[MAXDATELEN + 1];
+
+                               timestamp = DatumGetTimestamp(value);
+
+                               /* 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")));
+                               else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
+                                       EncodeDateTime(&tm, fsec, NULL, &tzn, USE_XSD_DATES, buf);
+                               else
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                                                        errmsg("timestamp out of range")));
+
+                               return pstrdup(buf);
+                       }
+
+                       case TIMESTAMPTZOID:
+                       {
+                               TimestampTz     timestamp;
+                               struct pg_tm tm;
+                               int                     tz;
+                               fsec_t          fsec;
+                               char       *tzn = NULL;
+                               char            buf[MAXDATELEN + 1];
+
+                               timestamp = DatumGetTimestamp(value);
+
+                               /* 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")));
+                               else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
+                                       EncodeDateTime(&tm, fsec, &tz, &tzn, USE_XSD_DATES, buf);
+                               else
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                                                        errmsg("timestamp out of range")));
+
+                               return pstrdup(buf);
+                       }
                }
 
                getTypeOutputInfo(type, &typeOut, &isvarlena);
@@ -2234,17 +2305,17 @@ map_sql_type_to_xmlschema_type(Oid typeoid, int typmod)
 
                                if (typmod == -1)
                                        appendStringInfo(&result,
-                                                                        "  <xsd:restriction base=\"xsd:time\">\n"
+                                                                        "  <xsd:restriction base=\"xsd:dateTime\">\n"
                                                                         "    <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}(.\\p{Nd}+)?%s\"/>\n"
                                                                         "  </xsd:restriction>\n", tz);
                                else if (typmod == 0)
                                        appendStringInfo(&result,
-                                                                        "  <xsd:restriction base=\"xsd:time\">\n"
+                                                                        "  <xsd:restriction base=\"xsd:dateTime\">\n"
                                                                         "    <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
                                                                         "  </xsd:restriction>\n", tz);
                                else
                                        appendStringInfo(&result,
-                                                                        "  <xsd:restriction base=\"xsd:time\">\n"
+                                                                        "  <xsd:restriction base=\"xsd:dateTime\">\n"
                                                                         "    <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}.\\p{Nd}{%d}%s\"/>\n"
                                                                         "  </xsd:restriction>\n", typmod - VARHDRSZ, tz);
                                break;
index 29a450c..ca5cc79 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.192 2007/02/15 23:23:23 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.193 2007/03/01 14:52:04 petere Exp $
  *
  * NOTES
  *       some of the information in this file should be moved to other files.
@@ -178,6 +178,7 @@ extern DLLIMPORT Oid MyDatabaseTableSpace;
 #define USE_ISO_DATES                  1
 #define USE_SQL_DATES                  2
 #define USE_GERMAN_DATES               3
+#define USE_XSD_DATES                  4
 
 /* valid DateOrder values */
 #define DATEORDER_YMD                  0