*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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,
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);
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",
sprintf(str + strlen(str), ":%02d", tm->tm_sec);
if (tzp != NULL)
- EncodeTimezone(str, *tzp);
+ EncodeTimezone(str, *tzp, style);
return TRUE;
} /* EncodeTimeOnly() */
* 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
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
* 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");
if (*tzn != NULL)
sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
else
- EncodeTimezone(str, *tzp);
+ EncodeTimezone(str, *tzp, style);
}
if (tm->tm_year <= 0)
if (*tzn != NULL)
sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
else
- EncodeTimezone(str, *tzp);
+ EncodeTimezone(str, *tzp, style);
}
if (tm->tm_year <= 0)
* the date/time parser later. - thomas 2001-10-19
*/
sprintf(str + strlen(str), " ");
- EncodeTimezone(str, *tzp);
+ EncodeTimezone(str, *tzp, style);
}
}
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
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);
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;
* 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.
#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