Commit 7b76bfbe authored by Peter Eisentraut's avatar Peter Eisentraut

Fix date/time formats for XML Schema output.

Pavel Stehule
parent 9f652d43
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -3153,7 +3153,7 @@ datebsearch(const char *key, const datetkn *base, int nel)
* Append representation of a numeric timezone offset to str. * Append representation of a numeric timezone offset to str.
*/ */
static void static void
EncodeTimezone(char *str, int tz) EncodeTimezone(char *str, int tz, int style)
{ {
int hour, int hour,
min, min,
...@@ -3171,7 +3171,7 @@ EncodeTimezone(char *str, int tz) ...@@ -3171,7 +3171,7 @@ EncodeTimezone(char *str, int tz)
if (sec != 0) if (sec != 0)
sprintf(str, "%02d:%02d:%02d", hour, min, sec); 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); sprintf(str, "%02d:%02d", hour, min);
else else
sprintf(str, "%02d", hour); sprintf(str, "%02d", hour);
...@@ -3189,6 +3189,7 @@ EncodeDateOnly(struct pg_tm * tm, int style, char *str) ...@@ -3189,6 +3189,7 @@ EncodeDateOnly(struct pg_tm * tm, int style, char *str)
switch (style) switch (style)
{ {
case USE_ISO_DATES: case USE_ISO_DATES:
case USE_XSD_DATES:
/* compatible with ISO date formats */ /* compatible with ISO date formats */
if (tm->tm_year > 0) if (tm->tm_year > 0)
sprintf(str, "%04d-%02d-%02d", sprintf(str, "%04d-%02d-%02d",
...@@ -3266,7 +3267,7 @@ EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str) ...@@ -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); sprintf(str + strlen(str), ":%02d", tm->tm_sec);
if (tzp != NULL) if (tzp != NULL)
EncodeTimezone(str, *tzp); EncodeTimezone(str, *tzp, style);
return TRUE; return TRUE;
} /* EncodeTimeOnly() */ } /* EncodeTimeOnly() */
...@@ -3279,6 +3280,7 @@ EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str) ...@@ -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 * SQL - mm/dd/yyyy hh:mm:ss.ss tz
* ISO - yyyy-mm-dd hh:mm:ss+/-tz * ISO - yyyy-mm-dd hh:mm:ss+/-tz
* German - dd.mm.yyyy 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): * Variants (affects order of month and day for Postgres and SQL styles):
* US - mm/dd/yyyy * US - mm/dd/yyyy
* European - dd/mm/yyyy * European - dd/mm/yyyy
...@@ -3297,11 +3299,18 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, ...@@ -3297,11 +3299,18 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
switch (style) switch (style)
{ {
case USE_ISO_DATES: case USE_ISO_DATES:
case USE_XSD_DATES:
/* Compatible with ISO-8601 date formats */ /* 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_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); 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 * 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, ...@@ -3333,7 +3342,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
* a valid time zone translation. * a valid time zone translation.
*/ */
if (tzp != NULL && tm->tm_isdst >= 0) if (tzp != NULL && tm->tm_isdst >= 0)
EncodeTimezone(str, *tzp); EncodeTimezone(str, *tzp, style);
if (tm->tm_year <= 0) if (tm->tm_year <= 0)
sprintf(str + strlen(str), " BC"); sprintf(str + strlen(str), " BC");
...@@ -3379,7 +3388,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, ...@@ -3379,7 +3388,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
if (*tzn != NULL) if (*tzn != NULL)
sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn); sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
else else
EncodeTimezone(str, *tzp); EncodeTimezone(str, *tzp, style);
} }
if (tm->tm_year <= 0) if (tm->tm_year <= 0)
...@@ -3423,7 +3432,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, ...@@ -3423,7 +3432,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
if (*tzn != NULL) if (*tzn != NULL)
sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn); sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
else else
EncodeTimezone(str, *tzp); EncodeTimezone(str, *tzp, style);
} }
if (tm->tm_year <= 0) if (tm->tm_year <= 0)
...@@ -3486,7 +3495,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, ...@@ -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 * the date/time parser later. - thomas 2001-10-19
*/ */
sprintf(str + strlen(str), " "); sprintf(str + strlen(str), " ");
EncodeTimezone(str, *tzp); EncodeTimezone(str, *tzp, style);
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -63,6 +63,8 @@
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "utils/array.h" #include "utils/array.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/xml.h" #include "utils/xml.h"
...@@ -1513,12 +1515,81 @@ map_sql_value_to_xml_value(Datum value, Oid type) ...@@ -1513,12 +1515,81 @@ map_sql_value_to_xml_value(Datum value, Oid type)
bool isvarlena; bool isvarlena;
char *p, *str; char *p, *str;
if (type == BOOLOID) /*
* Special XSD formatting for some data types
*/
switch (type)
{ {
if (DatumGetBool(value)) case BOOLOID:
return "true"; if (DatumGetBool(value))
else return "true";
return "false"; 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); getTypeOutputInfo(type, &typeOut, &isvarlena);
...@@ -2234,17 +2305,17 @@ map_sql_type_to_xmlschema_type(Oid typeoid, int typmod) ...@@ -2234,17 +2305,17 @@ map_sql_type_to_xmlschema_type(Oid typeoid, int typmod)
if (typmod == -1) if (typmod == -1)
appendStringInfo(&result, 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: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); " </xsd:restriction>\n", tz);
else if (typmod == 0) else if (typmod == 0)
appendStringInfo(&result, 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: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); " </xsd:restriction>\n", tz);
else else
appendStringInfo(&result, 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: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); " </xsd:restriction>\n", typmod - VARHDRSZ, tz);
break; break;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * NOTES
* some of the information in this file should be moved to other files. * some of the information in this file should be moved to other files.
...@@ -178,6 +178,7 @@ extern DLLIMPORT Oid MyDatabaseTableSpace; ...@@ -178,6 +178,7 @@ extern DLLIMPORT Oid MyDatabaseTableSpace;
#define USE_ISO_DATES 1 #define USE_ISO_DATES 1
#define USE_SQL_DATES 2 #define USE_SQL_DATES 2
#define USE_GERMAN_DATES 3 #define USE_GERMAN_DATES 3
#define USE_XSD_DATES 4
/* valid DateOrder values */ /* valid DateOrder values */
#define DATEORDER_YMD 0 #define DATEORDER_YMD 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment