Improve EncodeDateTime and EncodeTimeOnly APIs
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 14 Mar 2012 21:03:34 +0000 (23:03 +0200)
committerPeter Eisentraut <peter_e@gmx.net>
Wed, 14 Mar 2012 21:03:34 +0000 (23:03 +0200)
Use an explicit argument to tell whether to include the time zone in
the output, rather than using some undocumented pointer magic.

src/backend/utils/adt/date.c
src/backend/utils/adt/datetime.c
src/backend/utils/adt/nabstime.c
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/xml.c
src/include/utils/datetime.h
src/interfaces/ecpg/pgtypeslib/dt.h
src/interfaces/ecpg/pgtypeslib/dt_common.c
src/interfaces/ecpg/pgtypeslib/timestamp.c

index 85e8fd00ff231c86bfcf3cee25e3f0fbb4963cf3..2da4e04a28b0355e5be9694b569e931a218abb41 100644 (file)
@@ -1131,7 +1131,7 @@ time_out(PG_FUNCTION_ARGS)
        char            buf[MAXDATELEN + 1];
 
        time2tm(time, tm, &fsec);
-       EncodeTimeOnly(tm, fsec, NULL, DateStyle, buf);
+       EncodeTimeOnly(tm, fsec, false, 0, DateStyle, buf);
 
        result = pstrdup(buf);
        PG_RETURN_CSTRING(result);
@@ -1918,7 +1918,7 @@ timetz_out(PG_FUNCTION_ARGS)
        char            buf[MAXDATELEN + 1];
 
        timetz2tm(time, tm, &fsec, &tz);
-       EncodeTimeOnly(tm, fsec, &tz, DateStyle, buf);
+       EncodeTimeOnly(tm, fsec, true, tz, DateStyle, buf);
 
        result = pstrdup(buf);
        PG_RETURN_CSTRING(result);
index f495c3f01092d8f2382db87314eb34db4a234b91..56515f15b9d4248d03cab7f4b394bb0074d34810 100644 (file)
@@ -3679,39 +3679,54 @@ EncodeDateOnly(struct pg_tm * tm, int style, char *str)
 
 /* EncodeTimeOnly()
  * Encode time fields only.
+ *
+ * tm and fsec are the value to encode, print_tz determines whether to include
+ * a time zone (the difference between time and timetz types), tz is the
+ * numeric time zone offset, style is the date style, str is where to write the
+ * output.
  */
 void
-EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str)
+EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
 {
        sprintf(str, "%02d:%02d:", tm->tm_hour, tm->tm_min);
        str += strlen(str);
 
        AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
 
-       if (tzp != NULL)
-               EncodeTimezone(str, *tzp, style);
+       if (print_tz)
+               EncodeTimezone(str, tz, style);
 }
 
 
 /* EncodeDateTime()
  * Encode date and time interpreted as local time.
- * Support several date styles:
+ *
+ * tm and fsec are the value to encode, print_tz determines whether to include
+ * a time zone (the difference between timestamp and timestamptz types), tz is
+ * the numeric time zone offset, tzn is the textual time zone, which if
+ * specified will be used instead of tz by some styles, style is the date
+ * style, str is where to write the output.
+ *
+ * Supported date styles:
  *     Postgres - day mon hh:mm:ss yyyy tz
  *     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
  */
 void
-EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str)
+EncodeDateTime(struct pg_tm * tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
 {
        int                     day;
 
        Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
 
+       /*
+        * Negative tm_isdst means we have no valid time zone translation.
+        */
+       if (tm->tm_isdst < 0)
+               print_tz = false;
+
        switch (style)
        {
                case USE_ISO_DATES:
@@ -3729,14 +3744,8 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
 
                        AppendTimestampSeconds(str + strlen(str), tm, fsec);
 
-                       /*
-                        * tzp == NULL indicates that we don't want *any* time zone info
-                        * in the output string. *tzn != NULL indicates that we have alpha
-                        * time zone info available. tm_isdst != -1 indicates that we have
-                        * a valid time zone translation.
-                        */
-                       if (tzp != NULL && tm->tm_isdst >= 0)
-                               EncodeTimezone(str, *tzp, style);
+                       if (print_tz)
+                               EncodeTimezone(str, tz, style);
 
                        if (tm->tm_year <= 0)
                                sprintf(str + strlen(str), " BC");
@@ -3762,12 +3771,12 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
                         * TZ abbreviations in the Olson database are plain ASCII.
                         */
 
-                       if (tzp != NULL && tm->tm_isdst >= 0)
+                       if (print_tz)
                        {
-                               if (*tzn != NULL)
-                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
+                               if (tzn)
+                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                else
-                                       EncodeTimezone(str, *tzp, style);
+                                       EncodeTimezone(str, tz, style);
                        }
 
                        if (tm->tm_year <= 0)
@@ -3785,12 +3794,12 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
 
                        AppendTimestampSeconds(str + strlen(str), tm, fsec);
 
-                       if (tzp != NULL && tm->tm_isdst >= 0)
+                       if (print_tz)
                        {
-                               if (*tzn != NULL)
-                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
+                               if (tzn)
+                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                else
-                                       EncodeTimezone(str, *tzp, style);
+                                       EncodeTimezone(str, tz, style);
                        }
 
                        if (tm->tm_year <= 0)
@@ -3819,10 +3828,10 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
                        sprintf(str + strlen(str), " %04d",
                                        (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1));
 
-                       if (tzp != NULL && tm->tm_isdst >= 0)
+                       if (print_tz)
                        {
-                               if (*tzn != NULL)
-                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
+                               if (tzn)
+                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                else
                                {
                                        /*
@@ -3832,7 +3841,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, style);
+                                       EncodeTimezone(str, tz, style);
                                }
                        }
 
index d35645df33ebf75f1da5a284ca15cd3209dac6a5..dbd9e926c22c35300ef4da41b19653a6d130f7dc 100644 (file)
@@ -311,7 +311,7 @@ abstimeout(PG_FUNCTION_ARGS)
                        break;
                default:
                        abstime2tm(time, &tz, tm, &tzn);
-                       EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
+                       EncodeDateTime(tm, fsec, true, tz, tzn, DateStyle, buf);
                        break;
        }
 
index db434dcb3cc685758e009adcea9ba60c7f4abe77..edcce5f31ef42dd1c4b734cbe78668e7f4924f2a 100644 (file)
@@ -215,13 +215,12 @@ timestamp_out(PG_FUNCTION_ARGS)
        struct pg_tm tt,
                           *tm = &tt;
        fsec_t          fsec;
-       char       *tzn = NULL;
        char            buf[MAXDATELEN + 1];
 
        if (TIMESTAMP_NOT_FINITE(timestamp))
                EncodeSpecialTimestamp(timestamp, buf);
        else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
-               EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf);
+               EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf);
        else
                ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
@@ -501,7 +500,7 @@ timestamptz_out(PG_FUNCTION_ARGS)
        if (TIMESTAMP_NOT_FINITE(dt))
                EncodeSpecialTimestamp(dt, buf);
        else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0)
-               EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
+               EncodeDateTime(tm, fsec, true, tz, tzn, DateStyle, buf);
        else
                ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
@@ -1422,7 +1421,7 @@ timestamptz_to_str(TimestampTz t)
        if (TIMESTAMP_NOT_FINITE(t))
                EncodeSpecialTimestamp(t, buf);
        else if (timestamp2tm(t, &tz, tm, &fsec, &tzn, NULL) == 0)
-               EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf);
+               EncodeDateTime(tm, fsec, true, tz, tzn, USE_ISO_DATES, buf);
        else
                strlcpy(buf, "(timestamp out of range)", sizeof(buf));
 
index d7b637c1c437c51ad5f802b85779999464bd994c..b042e6b36b16c325afe223eaedcd9ab3b9fa5a83 100644 (file)
@@ -1987,7 +1987,6 @@ map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
                                        Timestamp       timestamp;
                                        struct pg_tm tm;
                                        fsec_t          fsec;
-                                       char       *tzn = NULL;
                                        char            buf[MAXDATELEN + 1];
 
                                        timestamp = DatumGetTimestamp(value);
@@ -1999,7 +1998,7 @@ map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
                                                                 errmsg("timestamp out of range"),
                                                                 errdetail("XML does not support infinite timestamp values.")));
                                        else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
-                                               EncodeDateTime(&tm, fsec, NULL, &tzn, USE_XSD_DATES, buf);
+                                               EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
                                        else
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
@@ -2026,7 +2025,7 @@ map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
                                                                 errmsg("timestamp out of range"),
                                                                 errdetail("XML does not support infinite timestamp values.")));
                                        else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
-                                               EncodeDateTime(&tm, fsec, &tz, &tzn, USE_XSD_DATES, buf);
+                                               EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
                                        else
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
index 358e2a67b0263c3ab6d012899e761c40073f303d..d73cc8dcfe8bc254764a46d812613c488c3ae5cb 100644 (file)
@@ -290,8 +290,8 @@ extern void DateTimeParseError(int dterr, const char *str,
 extern int     DetermineTimeZoneOffset(struct pg_tm * tm, pg_tz *tzp);
 
 extern void EncodeDateOnly(struct pg_tm * tm, int style, char *str);
-extern void EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, int *tzp, int style, char *str);
-extern void EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str);
+extern void EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, bool print_tz, int tz, int style, char *str);
+extern void EncodeDateTime(struct pg_tm * tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str);
 extern void EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str);
 
 extern int     DecodeSpecial(int field, char *lowtoken, int *val);
index ca9f5effcc4f2bb3b9270d514946ab50e3cd56c8..269af7822b15d57287109aa5f97ee52aedfcf0c5 100644 (file)
@@ -334,12 +334,12 @@ do { \
 
 int                    DecodeInterval(char **, int *, int, int *, struct tm *, fsec_t *);
 int                    DecodeTime(char *, int *, struct tm *, fsec_t *);
-int                    EncodeDateTime(struct tm *, fsec_t, int *, char **, int, char *, bool);
-int                    EncodeInterval(struct tm *, fsec_t, int, char *);
+int                    EncodeDateTime(struct tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str, bool EuroDates);
+int                    EncodeInterval(struct tm *tm, fsec_t fsec, int style, char *str);
 int                    tm2timestamp(struct tm *, fsec_t, int *, timestamp *);
 int                    DecodeUnits(int field, char *lowtoken, int *val);
 bool           CheckDateTokenTables(void);
-int                    EncodeDateOnly(struct tm *, int, char *, bool);
+int                    EncodeDateOnly(struct tm *tm, int style, char *str, bool EuroDates);
 int                    GetEpochTime(struct tm *);
 int                    ParseDateTime(char *, char *, char **, int *, int *, char **);
 int                    DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, bool);
index 45f1f8affd578ee18824a582c5e9873121e79f12..ff533400794217e387f8708e9575a9c6946763c1 100644 (file)
@@ -759,7 +759,14 @@ TrimTrailingZeros(char *str)
 
 /* EncodeDateTime()
  * Encode date and time interpreted as local time.
- * Support several date styles:
+ *
+ * tm and fsec are the value to encode, print_tz determines whether to include
+ * a time zone (the difference between timestamp and timestamptz types), tz is
+ * the numeric time zone offset, tzn is the textual time zone, which if
+ * specified will be used instead of tz by some styles, style is the date
+ * style, str is where to write the output.
+ *
+ * Supported date styles:
  *     Postgres - day mon hh:mm:ss yyyy tz
  *     SQL - mm/dd/yyyy hh:mm:ss.ss tz
  *     ISO - yyyy-mm-dd hh:mm:ss+/-tz
@@ -769,12 +776,18 @@ TrimTrailingZeros(char *str)
  *     European - dd/mm/yyyy
  */
 int
-EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool EuroDates)
+EncodeDateTime(struct tm * tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str, bool EuroDates)
 {
        int                     day,
                                hour,
                                min;
 
+       /*
+        * Negative tm_isdst means we have no valid time zone translation.
+        */
+       if (tm->tm_isdst < 0)
+               print_tz = false;
+
        switch (style)
        {
                case USE_ISO_DATES:
@@ -808,16 +821,10 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                        if (tm->tm_year <= 0)
                                sprintf(str + strlen(str), " BC");
 
-                       /*
-                        * tzp == NULL indicates that we don't want *any* time zone info
-                        * in the output string. *tzn != NULL indicates that we have alpha
-                        * time zone info available. tm_isdst != -1 indicates that we have
-                        * a valid time zone translation.
-                        */
-                       if (tzp != NULL && tm->tm_isdst >= 0)
+                       if (print_tz)
                        {
-                               hour = -(*tzp / SECS_PER_HOUR);
-                               min = (abs(*tzp) / MINS_PER_HOUR) % MINS_PER_HOUR;
+                               hour = -(tz / SECS_PER_HOUR);
+                               min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
                                if (min != 0)
                                        sprintf(str + strlen(str), "%+03d:%02d", hour, min);
                                else
@@ -867,14 +874,14 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                         * TZ abbreviations in the Olson database are plain ASCII.
                         */
 
-                       if (tzp != NULL && tm->tm_isdst >= 0)
+                       if (print_tz)
                        {
-                               if (*tzn != NULL)
-                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
+                               if (tzn)
+                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                else
                                {
-                                       hour = -(*tzp / SECS_PER_HOUR);
-                                       min = (abs(*tzp) / MINS_PER_HOUR) % MINS_PER_HOUR;
+                                       hour = -(tz / SECS_PER_HOUR);
+                                       min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
                                        if (min != 0)
                                                sprintf(str + strlen(str), "%+03d:%02d", hour, min);
                                        else
@@ -916,14 +923,14 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                        if (tm->tm_year <= 0)
                                sprintf(str + strlen(str), " BC");
 
-                       if (tzp != NULL && tm->tm_isdst >= 0)
+                       if (print_tz)
                        {
-                               if (*tzn != NULL)
-                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
+                               if (tzn)
+                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                else
                                {
-                                       hour = -(*tzp / SECS_PER_HOUR);
-                                       min = (abs(*tzp) / MINS_PER_HOUR) % MINS_PER_HOUR;
+                                       hour = -(tz / SECS_PER_HOUR);
+                                       min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
                                        if (min != 0)
                                                sprintf(str + strlen(str), "%+03d:%02d", hour, min);
                                        else
@@ -975,10 +982,10 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                        if (tm->tm_year <= 0)
                                sprintf(str + strlen(str), " BC");
 
-                       if (tzp != NULL && tm->tm_isdst >= 0)
+                       if (print_tz)
                        {
-                               if (*tzn != NULL)
-                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, *tzn);
+                               if (tzn)
+                                       sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                else
                                {
                                        /*
@@ -987,8 +994,8 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
                                         * avoid formatting something which would be rejected by
                                         * the date/time parser later. - thomas 2001-10-19
                                         */
-                                       hour = -(*tzp / SECS_PER_HOUR);
-                                       min = (abs(*tzp) / MINS_PER_HOUR) % MINS_PER_HOUR;
+                                       hour = -(tz / SECS_PER_HOUR);
+                                       min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
                                        if (min != 0)
                                                sprintf(str + strlen(str), " %+03d:%02d", hour, min);
                                        else
index dc5ff72b601715ec40c2bb460d3ac3288a16bd2d..b0e99766f5bc1f7604ed0118078eb7932a3247d0 100644 (file)
@@ -354,7 +354,6 @@ PGTYPEStimestamp_to_asc(timestamp tstamp)
        struct tm       tt,
                           *tm = &tt;
        char            buf[MAXDATELEN + 1];
-       char       *tzn = NULL;
        fsec_t          fsec;
        int                     DateStyle = 1;  /* this defaults to ISO_DATES, shall we make
                                                                 * it an option? */
@@ -362,7 +361,7 @@ PGTYPEStimestamp_to_asc(timestamp tstamp)
        if (TIMESTAMP_NOT_FINITE(tstamp))
                EncodeSpecialTimestamp(tstamp, buf);
        else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0)
-               EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0);
+               EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf, 0);
        else
        {
                errno = PGTYPES_TS_BAD_TIMESTAMP;