diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 6154c96b9c257f0483c01707fc7555b758239763..1be6e091632967dd4671cfbd5a0ff51321eebec5 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -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);
 				}
 			}
 
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index c12522cfe4537d7ce73b197408e883a69b427c3b..547d98df1e64be443850cb7b0ed4bb36e9337346 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -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;
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 29a450cab60e087c75d5668f6e58563021de2984..ca5cc799c519140ad2341969f4e76ba80ed5b11a 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -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