Skip to content

Commit 7b76bfb

Browse files
committed
Fix date/time formats for XML Schema output.
Pavel Stehule
1 parent 9f652d4 commit 7b76bfb

File tree

3 files changed

+100
-19
lines changed

3 files changed

+100
-19
lines changed

src/backend/utils/adt/datetime.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.177 2007/02/19 17:41:39 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.178 2007/03/01 14:52:03 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -3153,7 +3153,7 @@ datebsearch(const char *key, const datetkn *base, int nel)
31533153
* Append representation of a numeric timezone offset to str.
31543154
*/
31553155
static void
3156-
EncodeTimezone(char *str, int tz)
3156+
EncodeTimezone(char *str, int tz, int style)
31573157
{
31583158
int hour,
31593159
min,
@@ -3171,7 +3171,7 @@ EncodeTimezone(char *str, int tz)
31713171

31723172
if (sec != 0)
31733173
sprintf(str, "%02d:%02d:%02d", hour, min, sec);
3174-
else if (min != 0)
3174+
else if (min != 0 || style == USE_XSD_DATES)
31753175
sprintf(str, "%02d:%02d", hour, min);
31763176
else
31773177
sprintf(str, "%02d", hour);
@@ -3189,6 +3189,7 @@ EncodeDateOnly(struct pg_tm * tm, int style, char *str)
31893189
switch (style)
31903190
{
31913191
case USE_ISO_DATES:
3192+
case USE_XSD_DATES:
31923193
/* compatible with ISO date formats */
31933194
if (tm->tm_year > 0)
31943195
sprintf(str, "%04d-%02d-%02d",
@@ -3266,7 +3267,7 @@ EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str)
32663267
sprintf(str + strlen(str), ":%02d", tm->tm_sec);
32673268

32683269
if (tzp != NULL)
3269-
EncodeTimezone(str, *tzp);
3270+
EncodeTimezone(str, *tzp, style);
32703271

32713272
return TRUE;
32723273
} /* EncodeTimeOnly() */
@@ -3279,6 +3280,7 @@ EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str)
32793280
* SQL - mm/dd/yyyy hh:mm:ss.ss tz
32803281
* ISO - yyyy-mm-dd hh:mm:ss+/-tz
32813282
* German - dd.mm.yyyy hh:mm:ss tz
3283+
* XSD - yyyy-mm-ddThh:mm:ss.ss+/-tz
32823284
* Variants (affects order of month and day for Postgres and SQL styles):
32833285
* US - mm/dd/yyyy
32843286
* European - dd/mm/yyyy
@@ -3297,11 +3299,18 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
32973299
switch (style)
32983300
{
32993301
case USE_ISO_DATES:
3302+
case USE_XSD_DATES:
33003303
/* Compatible with ISO-8601 date formats */
33013304

3302-
sprintf(str, "%04d-%02d-%02d %02d:%02d",
3305+
if (style == USE_ISO_DATES)
3306+
sprintf(str, "%04d-%02d-%02d %02d:%02d",
33033307
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
33043308
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
3309+
else
3310+
sprintf(str, "%04d-%02d-%02dT%02d:%02d",
3311+
(tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
3312+
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
3313+
33053314

33063315
/*
33073316
* 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,
33333342
* a valid time zone translation.
33343343
*/
33353344
if (tzp != NULL && tm->tm_isdst >= 0)
3336-
EncodeTimezone(str, *tzp);
3345+
EncodeTimezone(str, *tzp, style);
33373346

33383347
if (tm->tm_year <= 0)
33393348
sprintf(str + strlen(str), " BC");
@@ -3379,7 +3388,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
33793388
if (*tzn != NULL)
33803389
sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
33813390
else
3382-
EncodeTimezone(str, *tzp);
3391+
EncodeTimezone(str, *tzp, style);
33833392
}
33843393

33853394
if (tm->tm_year <= 0)
@@ -3423,7 +3432,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
34233432
if (*tzn != NULL)
34243433
sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
34253434
else
3426-
EncodeTimezone(str, *tzp);
3435+
EncodeTimezone(str, *tzp, style);
34273436
}
34283437

34293438
if (tm->tm_year <= 0)
@@ -3486,7 +3495,7 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
34863495
* the date/time parser later. - thomas 2001-10-19
34873496
*/
34883497
sprintf(str + strlen(str), " ");
3489-
EncodeTimezone(str, *tzp);
3498+
EncodeTimezone(str, *tzp, style);
34903499
}
34913500
}
34923501

src/backend/utils/adt/xml.c

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.32 2007/02/27 23:48:09 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.33 2007/03/01 14:52:04 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -63,6 +63,8 @@
6363
#include "parser/parse_expr.h"
6464
#include "utils/array.h"
6565
#include "utils/builtins.h"
66+
#include "utils/date.h"
67+
#include "utils/datetime.h"
6668
#include "utils/lsyscache.h"
6769
#include "utils/memutils.h"
6870
#include "utils/xml.h"
@@ -1513,12 +1515,81 @@ map_sql_value_to_xml_value(Datum value, Oid type)
15131515
bool isvarlena;
15141516
char *p, *str;
15151517

1516-
if (type == BOOLOID)
1518+
/*
1519+
* Special XSD formatting for some data types
1520+
*/
1521+
switch (type)
15171522
{
1518-
if (DatumGetBool(value))
1519-
return "true";
1520-
else
1521-
return "false";
1523+
case BOOLOID:
1524+
if (DatumGetBool(value))
1525+
return "true";
1526+
else
1527+
return "false";
1528+
1529+
case DATEOID:
1530+
{
1531+
DateADT date;
1532+
struct pg_tm tm;
1533+
char buf[MAXDATELEN + 1];
1534+
1535+
date = DatumGetDateADT(value);
1536+
j2date(date + POSTGRES_EPOCH_JDATE,
1537+
&(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
1538+
EncodeDateOnly(&tm, USE_XSD_DATES, buf);
1539+
1540+
return pstrdup(buf);
1541+
}
1542+
1543+
case TIMESTAMPOID:
1544+
{
1545+
Timestamp timestamp;
1546+
struct pg_tm tm;
1547+
fsec_t fsec;
1548+
char *tzn = NULL;
1549+
char buf[MAXDATELEN + 1];
1550+
1551+
timestamp = DatumGetTimestamp(value);
1552+
1553+
/* XSD doesn't support infinite values */
1554+
if (TIMESTAMP_NOT_FINITE(timestamp))
1555+
ereport(ERROR,
1556+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1557+
errmsg("timestamp out of range")));
1558+
else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
1559+
EncodeDateTime(&tm, fsec, NULL, &tzn, USE_XSD_DATES, buf);
1560+
else
1561+
ereport(ERROR,
1562+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1563+
errmsg("timestamp out of range")));
1564+
1565+
return pstrdup(buf);
1566+
}
1567+
1568+
case TIMESTAMPTZOID:
1569+
{
1570+
TimestampTz timestamp;
1571+
struct pg_tm tm;
1572+
int tz;
1573+
fsec_t fsec;
1574+
char *tzn = NULL;
1575+
char buf[MAXDATELEN + 1];
1576+
1577+
timestamp = DatumGetTimestamp(value);
1578+
1579+
/* XSD doesn't support infinite values */
1580+
if (TIMESTAMP_NOT_FINITE(timestamp))
1581+
ereport(ERROR,
1582+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1583+
errmsg("timestamp out of range")));
1584+
else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
1585+
EncodeDateTime(&tm, fsec, &tz, &tzn, USE_XSD_DATES, buf);
1586+
else
1587+
ereport(ERROR,
1588+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1589+
errmsg("timestamp out of range")));
1590+
1591+
return pstrdup(buf);
1592+
}
15221593
}
15231594

15241595
getTypeOutputInfo(type, &typeOut, &isvarlena);
@@ -2234,17 +2305,17 @@ map_sql_type_to_xmlschema_type(Oid typeoid, int typmod)
22342305

22352306
if (typmod == -1)
22362307
appendStringInfo(&result,
2237-
" <xsd:restriction base=\"xsd:time\">\n"
2308+
" <xsd:restriction base=\"xsd:dateTime\">\n"
22382309
" <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"
22392310
" </xsd:restriction>\n", tz);
22402311
else if (typmod == 0)
22412312
appendStringInfo(&result,
2242-
" <xsd:restriction base=\"xsd:time\">\n"
2313+
" <xsd:restriction base=\"xsd:dateTime\">\n"
22432314
" <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
22442315
" </xsd:restriction>\n", tz);
22452316
else
22462317
appendStringInfo(&result,
2247-
" <xsd:restriction base=\"xsd:time\">\n"
2318+
" <xsd:restriction base=\"xsd:dateTime\">\n"
22482319
" <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"
22492320
" </xsd:restriction>\n", typmod - VARHDRSZ, tz);
22502321
break;

src/include/miscadmin.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
1414
* Portions Copyright (c) 1994, Regents of the University of California
1515
*
16-
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.192 2007/02/15 23:23:23 alvherre Exp $
16+
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.193 2007/03/01 14:52:04 petere Exp $
1717
*
1818
* NOTES
1919
* some of the information in this file should be moved to other files.
@@ -178,6 +178,7 @@ extern DLLIMPORT Oid MyDatabaseTableSpace;
178178
#define USE_ISO_DATES 1
179179
#define USE_SQL_DATES 2
180180
#define USE_GERMAN_DATES 3
181+
#define USE_XSD_DATES 4
181182

182183
/* valid DateOrder values */
183184
#define DATEORDER_YMD 0

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy