diff options
Diffstat (limited to 'src/backend/utils/adt/datetime.c')
-rw-r--r-- | src/backend/utils/adt/datetime.c | 556 |
1 files changed, 371 insertions, 185 deletions
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 1dd540abb7f..1a908d9d6b7 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.88 2002/02/25 16:17:04 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.89 2002/04/21 19:48:12 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -28,12 +28,12 @@ static int DecodeNumber(int flen, char *field, int fmask, int *tmask, - struct tm * tm, double *fsec, int *is2digits); + struct tm * tm, fsec_t *fsec, int *is2digits); static int DecodeNumberField(int len, char *str, int fmask, int *tmask, - struct tm * tm, double *fsec, int *is2digits); + struct tm * tm, fsec_t *fsec, int *is2digits); static int DecodeTime(char *str, int fmask, int *tmask, - struct tm * tm, double *fsec); + struct tm * tm, fsec_t *fsec); static int DecodeTimezone(char *str, int *tzp); static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel); static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm); @@ -865,7 +865,7 @@ ParseDateTime(char *timestr, char *lowstr, */ int DecodeDateTime(char **field, int *ftype, int nf, - int *dtype, struct tm * tm, double *fsec, int *tzp) + int *dtype, struct tm * tm, fsec_t *fsec, int *tzp) { int fmask = 0, tmask, @@ -1095,9 +1095,15 @@ DecodeDateTime(char **field, int *ftype, int nf, tmask = DTK_M(SECOND); if (*cp == '.') { - *fsec = strtod(cp, &cp); + double frac; + frac = strtod(cp, &cp); if (*cp != '\0') return -1; +#ifdef HAVE_INT64_TIMESTAMP + *fsec = frac * 1000000; +#else + *fsec = frac; +#endif } break; @@ -1113,6 +1119,7 @@ DecodeDateTime(char **field, int *ftype, int nf, ***/ tmask = DTK_DATE_M; j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + /* fractional Julian Day? */ if (*cp == '.') { double time; @@ -1122,9 +1129,11 @@ DecodeDateTime(char **field, int *ftype, int nf, return -1; tmask |= DTK_TIME_M; - dt2time((time*86400), &tm->tm_hour, &tm->tm_min, fsec); - tm->tm_sec = *fsec; - *fsec -= tm->tm_sec; +#ifdef HAVE_INT64_TIMESTAMP + dt2time((time*86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); +#else + dt2time((time*86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); +#endif } break; @@ -1505,7 +1514,7 @@ DetermineLocalTimeZone(struct tm * tm) */ int DecodeTimeOnly(char **field, int *ftype, int nf, - int *dtype, struct tm * tm, double *fsec, int *tzp) + int *dtype, struct tm * tm, fsec_t *fsec, int *tzp) { int fmask = 0, tmask, @@ -1729,9 +1738,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf, return -1; tmask |= DTK_TIME_M; - dt2time((time*86400), &tm->tm_hour, &tm->tm_min, fsec); - tm->tm_sec = *fsec; - *fsec -= tm->tm_sec; +#ifdef HAVE_INT64_TIMESTAMP + dt2time((time*86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); +#else + dt2time((time*86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec); +#endif } break; @@ -1925,10 +1936,18 @@ DecodeTimeOnly(char **field, int *ftype, int nf, else if ((mer == PM) && (tm->tm_hour != 12)) tm->tm_hour += 12; +#ifdef HAVE_INT64_TIMESTAMP + if (((tm->tm_hour < 0) || (tm->tm_hour > 23)) + || ((tm->tm_min < 0) || (tm->tm_min > 59)) + || ((tm->tm_sec < 0) || (tm->tm_sec > 60)) + || (*fsec < INT64CONST(0)) || (*fsec >= INT64CONST(1000000))) + return -1; +#else if (((tm->tm_hour < 0) || (tm->tm_hour > 23)) || ((tm->tm_min < 0) || (tm->tm_min > 59)) || ((tm->tm_sec < 0) || ((tm->tm_sec + *fsec) >= 60))) return -1; +#endif if ((fmask & DTK_TIME_M) != DTK_TIME_M) return -1; @@ -1973,7 +1992,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf, static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm) { - double fsec; + fsec_t fsec; int nf = 0; int i, @@ -2100,7 +2119,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm) * can be used to represent time spans. */ static int -DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec) +DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec) { char *cp; @@ -2115,12 +2134,10 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec) { tm->tm_sec = 0; *fsec = 0; - } else if (*cp != ':') { return -1; - } else { @@ -2130,9 +2147,22 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec) *fsec = 0; else if (*cp == '.') { +#ifdef HAVE_INT64_TIMESTAMP + char fstr[MAXDATELEN + 1]; + + /* OK, we have at most six digits to work with. + * Let's construct a string and then do the conversion + * to an integer. + */ + strncpy(fstr, (cp+1), 7); + strcpy((fstr+strlen(fstr)), "000000"); + *(fstr+6) = '\0'; + *fsec = strtol(fstr, &cp, 10); +#else str = cp; *fsec = strtod(str, &cp); - if (cp == str) +#endif + if (*cp != '\0') return -1; } else @@ -2140,10 +2170,19 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec) } /* do a sanity check */ +#ifdef HAVE_INT64_TIMESTAMP + if ((tm->tm_hour < 0) + || (tm->tm_min < 0) || (tm->tm_min > 59) + || (tm->tm_sec < 0) || (tm->tm_sec > 59) + || (*fsec >= INT64CONST(1000000))) + return -1; +#else if ((tm->tm_hour < 0) || (tm->tm_min < 0) || (tm->tm_min > 59) - || (tm->tm_sec < 0) || (tm->tm_sec > 59)) + || (tm->tm_sec < 0) || (tm->tm_sec > 59) + || (*fsec >= 1)) return -1; +#endif return 0; } /* DecodeTime() */ @@ -2154,7 +2193,7 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec) */ static int DecodeNumber(int flen, char *str, int fmask, - int *tmask, struct tm * tm, double *fsec, int *is2digits) + int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits) { int val; char *cp; @@ -2193,7 +2232,6 @@ DecodeNumber(int flen, char *str, int fmask, tm->tm_yday = val; j2date((date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1), &tm->tm_year, &tm->tm_mon, &tm->tm_mday); - } /*** @@ -2225,7 +2263,6 @@ DecodeNumber(int flen, char *str, int fmask, { *tmask = DTK_M(MONTH); tm->tm_mon = val; - } /* no year and EuroDates enabled? then could be day */ else if ((EuroDates || (fmask & DTK_M(MONTH))) @@ -2275,7 +2312,7 @@ DecodeNumber(int flen, char *str, int fmask, */ static int DecodeNumberField(int len, char *str, int fmask, - int *tmask, struct tm * tm, double *fsec, int *is2digits) + int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits) { char *cp; @@ -2284,7 +2321,20 @@ DecodeNumberField(int len, char *str, int fmask, */ if ((cp = strchr(str, '.')) != NULL) { +#ifdef HAVE_INT64_TIMESTAMP + char fstr[MAXDATELEN + 1]; + + /* OK, we have at most six digits to care about. + * Let's construct a string and then do the conversion + * to an integer. + */ + strcpy(fstr, (cp+1)); + strcpy((fstr+strlen(fstr)), "000000"); + *(fstr+6) = '\0'; + *fsec = strtol(fstr, NULL, 10); +#else *fsec = strtod(cp, NULL); +#endif *cp = '\0'; len = strlen(str); } @@ -2501,7 +2551,7 @@ DecodeSpecial(int field, char *lowtoken, int *val) } /* DecodeSpecial() */ -/* DecodeDateDelta() +/* DecodeInterval() * Interpret previously parsed fields for general time interval. * Return 0 if decoded and -1 if problems. * @@ -2512,7 +2562,7 @@ DecodeSpecial(int field, char *lowtoken, int *val) * preceding an hh:mm:ss field. - thomas 1998-04-30 */ int -DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, double *fsec) +DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fsec_t *fsec) { int is_before = FALSE; @@ -2523,7 +2573,6 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do int i; int val; double fval; - double sec; *dtype = DTK_DELTA; @@ -2631,51 +2680,113 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do switch (type) { case DTK_MICROSEC: +#ifdef HAVE_INT64_TIMESTAMP + *fsec += (val + fval); +#else *fsec += ((val + fval) * 1e-6); +#endif break; case DTK_MILLISEC: +#ifdef HAVE_INT64_TIMESTAMP + *fsec += ((val + fval) * 1000); +#else *fsec += ((val + fval) * 1e-3); +#endif break; case DTK_SECOND: tm->tm_sec += val; +#ifdef HAVE_INT64_TIMESTAMP + *fsec += (fval * 1000000); +#else *fsec += fval; +#endif tmask = DTK_M(SECOND); break; case DTK_MINUTE: tm->tm_min += val; if (fval != 0) - tm->tm_sec += (fval * 60); + { + int sec; + fval *= 60; + sec = fval; + tm->tm_sec += sec; +#ifdef HAVE_INT64_TIMESTAMP + *fsec += ((fval - sec) * 1000000); +#else + *fsec += (fval - sec); +#endif + } tmask = DTK_M(MINUTE); break; case DTK_HOUR: tm->tm_hour += val; if (fval != 0) - tm->tm_sec += (fval * 3600); + { + int sec; + fval *= 3600; + sec = fval; + tm->tm_sec += sec; +#ifdef HAVE_INT64_TIMESTAMP + *fsec += ((fval - sec) * 1000000); +#else + *fsec += (fval - sec); +#endif + } tmask = DTK_M(HOUR); break; case DTK_DAY: tm->tm_mday += val; if (fval != 0) - tm->tm_sec += (fval * 86400); + { + int sec; + fval *= 86400; + sec = fval; + tm->tm_sec += sec; +#ifdef HAVE_INT64_TIMESTAMP + *fsec += ((fval - sec) * 1000000); +#else + *fsec += (fval - sec); +#endif + } tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY)); break; case DTK_WEEK: tm->tm_mday += val * 7; if (fval != 0) - tm->tm_sec += (fval * (7 * 86400)); + { + int sec; + fval *= (7*86400); + sec = fval; + tm->tm_sec += sec; +#ifdef HAVE_INT64_TIMESTAMP + *fsec += ((fval - sec) * 1000000); +#else + *fsec += (fval - sec); +#endif + } tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY)); break; case DTK_MONTH: tm->tm_mon += val; if (fval != 0) - tm->tm_sec += (fval * (30 * 86400)); + { + int sec; + fval *= (30*86400); + sec = fval; + tm->tm_sec += sec; +#ifdef HAVE_INT64_TIMESTAMP + *fsec += ((fval - sec) * 1000000); +#else + *fsec += (fval - sec); +#endif + } tmask = DTK_M(MONTH); break; @@ -2751,7 +2862,14 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do if (*fsec != 0) { + int sec; + +#ifdef HAVE_INT64_TIMESTAMP + sec = (*fsec / INT64CONST(1000000)); + *fsec -= (sec * INT64CONST(1000000)); +#else TMODULO(*fsec, sec, 1e0); +#endif tm->tm_sec += sec; } @@ -2768,7 +2886,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do /* ensure that at least one time field has been found */ return (fmask != 0) ? 0 : -1; -} /* DecodeDateDelta() */ +} /* DecodeInterval() */ /* DecodeUnits() @@ -2899,14 +3017,18 @@ EncodeDateOnly(struct tm * tm, int style, char *str) * Encode time fields only. */ int -EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str) +EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str) { - double sec; +#ifndef HAVE_INT64_TIMESTAMP + fsec_t sec; +#endif if ((tm->tm_hour < 0) || (tm->tm_hour > 24)) return -1; +#ifndef HAVE_INT64_TIMESTAMP sec = (tm->tm_sec + fsec); +#endif sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min); @@ -2919,14 +3041,23 @@ EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str) */ if (fsec != 0) { +#ifdef HAVE_INT64_TIMESTAMP + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + sprintf((str + strlen(str)), ".%06d", fsec); +#else sprintf((str + strlen(str)), ":%013.10f", sec); +#endif /* chop off trailing pairs of zeros... */ while ((strcmp((str + strlen(str) - 2), "00") == 0) && (*(str + strlen(str) - 3) != '.')) *(str + strlen(str) - 2) = '\0'; } else +#ifdef HAVE_INT64_TIMESTAMP + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); +#else sprintf((str + strlen(str)), ":%02.0f", sec); +#endif if (tzp != NULL) { @@ -2954,158 +3085,191 @@ EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str) * European - dd/mm/yyyy */ int -EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, char *str) +EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str) { int day, hour, min; - double sec; +#ifndef HAVE_INT64_TIMESTAMP + fsec_t sec; +#endif - if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) - return -1; + /* Why are we checking only the month field? Change this to an assert... + * if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) + * return -1; + */ + Assert((tm->tm_mon >= 1) && (tm->tm_mon <= 12)); +#ifndef HAVE_INT64_TIMESTAMP sec = (tm->tm_sec + fsec); +#endif switch (style) { - /* compatible with ISO date formats */ - case USE_ISO_DATES: - if (tm->tm_year > 0) - { - sprintf(str, "%04d-%02d-%02d %02d:%02d", - tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); + /* Compatible with ISO-8601 date formats */ - /* - * If we have fractional seconds, then include a decimal - * point We will do up to 6 fractional digits, and we have - * rounded any inputs to eliminate anything to the right - * of 6 digits anyway. If there are no fractional seconds, - * then do not bother printing a decimal point at all. - - * thomas 2001-09-29 - */ - if (fsec != 0) - { - sprintf((str + strlen(str)), ":%013.10f", sec); - TrimTrailingZeros(str); - } - else - sprintf((str + strlen(str)), ":%02.0f", sec); + 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); - /* - * 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)) - { - hour = -(*tzp / 3600); - min = ((abs(*tzp) / 60) % 60); - sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); - } + /* + * If we have fractional seconds, then include a decimal + * point We will do up to 6 fractional digits, and we have + * rounded any inputs to eliminate anything to the right + * of 6 digits anyway. If there are no fractional seconds, + * then do not bother printing a decimal point at all. - + * thomas 2001-09-29 + */ +#ifdef HAVE_INT64_TIMESTAMP + if (fsec != 0) + { + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + sprintf((str + strlen(str)), ".%06d", fsec); +#else + if ((fsec != 0) && (tm->tm_year > 0)) + { + sprintf((str + strlen(str)), ":%013.10f", sec); +#endif + TrimTrailingZeros(str); } else { - if (tm->tm_hour || tm->tm_min) - sprintf(str, "%04d-%02d-%02d %02d:%02d %s", - -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, "BC"); - else - sprintf(str, "%04d-%02d-%02d %s", - -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC"); + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + } + + 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)) + { + hour = -(*tzp / 3600); + min = ((abs(*tzp) / 60) % 60); + sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); } break; - /* compatible with Oracle/Ingres date formats */ case USE_SQL_DATES: + /* Compatible with Oracle/Ingres date formats */ + if (EuroDates) sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon); else sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday); - if (tm->tm_year > 0) + sprintf((str + 5), "/%04d %02d:%02d", + ((tm->tm_year > 0)? tm->tm_year: -(tm->tm_year - 1)), + tm->tm_hour, tm->tm_min); + + /* + * If we have fractional seconds, then include a decimal + * point We will do up to 6 fractional digits, and we have + * rounded any inputs to eliminate anything to the right + * of 6 digits anyway. If there are no fractional seconds, + * then do not bother printing a decimal point at all. - + * thomas 2001-09-29 + */ +#ifdef HAVE_INT64_TIMESTAMP + if (fsec != 0) + { + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + sprintf((str + strlen(str)), ".%06d", fsec); +#else + if ((fsec != 0) && (tm->tm_year > 0)) { - sprintf((str + 5), "/%04d %02d:%02d", - tm->tm_year, tm->tm_hour, tm->tm_min); + sprintf((str + strlen(str)), ":%013.10f", sec); +#endif + TrimTrailingZeros(str); + } + else + { + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + } - /* - * If we have fractional seconds, then include a decimal - * point We will do up to 6 fractional digits, and we have - * rounded any inputs to eliminate anything to the right - * of 6 digits anyway. If there are no fractional seconds, - * then do not bother printing a decimal point at all. - - * thomas 2001-09-29 - */ - if (fsec != 0) - { - sprintf((str + strlen(str)), ":%013.10f", sec); - TrimTrailingZeros(str); - } - else - sprintf((str + strlen(str)), ":%02.0f", sec); + if (tm->tm_year <= 0) + { + sprintf((str + strlen(str)), " BC"); + } - if ((tzp != NULL) && (tm->tm_isdst >= 0)) + if ((tzp != NULL) && (tm->tm_isdst >= 0)) + { + if (*tzn != NULL) + sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); + else { - if (*tzn != NULL) - sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); - else - { - hour = -(*tzp / 3600); - min = ((abs(*tzp) / 60) % 60); - sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); - } + hour = -(*tzp / 3600); + min = ((abs(*tzp) / 60) % 60); + sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); } } - else - sprintf((str + 5), "/%04d %02d:%02d %s", - -(tm->tm_year - 1), tm->tm_hour, tm->tm_min, "BC"); break; - /* German variant on European style */ case USE_GERMAN_DATES: + /* German variant on European style */ + sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon); - if (tm->tm_year > 0) + + sprintf((str + 5), ".%04d %02d:%02d", + ((tm->tm_year > 0)? tm->tm_year: -(tm->tm_year - 1)), + tm->tm_hour, tm->tm_min); + + /* + * If we have fractional seconds, then include a decimal + * point We will do up to 6 fractional digits, and we have + * rounded any inputs to eliminate anything to the right + * of 6 digits anyway. If there are no fractional seconds, + * then do not bother printing a decimal point at all. - + * thomas 2001-09-29 + */ +#ifdef HAVE_INT64_TIMESTAMP + if (fsec != 0) + { + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + sprintf((str + strlen(str)), ".%06d", fsec); +#else + if ((fsec != 0) && (tm->tm_year > 0)) + { + sprintf((str + strlen(str)), ":%013.10f", sec); +#endif + TrimTrailingZeros(str); + } + else { - sprintf((str + 5), ".%04d %02d:%02d", - tm->tm_year, tm->tm_hour, tm->tm_min); + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + } - /* - * If we have fractional seconds, then include a decimal - * point We will do up to 6 fractional digits, and we have - * rounded any inputs to eliminate anything to the right - * of 6 digits anyway. If there are no fractional seconds, - * then do not bother printing a decimal point at all. - - * thomas 2001-09-29 - */ - if (fsec != 0) - { - sprintf((str + strlen(str)), ":%013.10f", sec); - TrimTrailingZeros(str); - } - else - sprintf((str + strlen(str)), ":%02.0f", sec); + if (tm->tm_year <= 0) + { + sprintf((str + strlen(str)), " BC"); + } - if ((tzp != NULL) && (tm->tm_isdst >= 0)) + if ((tzp != NULL) && (tm->tm_isdst >= 0)) + { + if (*tzn != NULL) + sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); + else { - if (*tzn != NULL) - sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); - else - { - hour = -(*tzp / 3600); - min = ((abs(*tzp) / 60) % 60); - sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); - } + hour = -(*tzp / 3600); + min = ((abs(*tzp) / 60) % 60); + sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); } } - else - sprintf((str + 5), ".%04d %02d:%02d %s", - -(tm->tm_year - 1), tm->tm_hour, tm->tm_min, "BC"); break; - /* backward-compatible with traditional Postgres abstime dates */ case USE_POSTGRES_DATES: default: + /* Backward-compatible with traditional Postgres abstime dates */ + day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday); tm->tm_wday = j2day(day); @@ -3117,52 +3281,58 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha else sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday); - if (tm->tm_year > 0) - { - sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min); + sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min); - /* - * If we have fractional seconds, then include a decimal - * point We will do up to 6 fractional digits, and we have - * rounded any inputs to eliminate anything to the right - * of 6 digits anyway. If there are no fractional seconds, - * then do not bother printing a decimal point at all. - - * thomas 2001-09-29 - */ - if (fsec != 0) - { - sprintf((str + strlen(str)), ":%013.10f", sec); - TrimTrailingZeros(str); - } - else - sprintf((str + strlen(str)), ":%02.0f", sec); + /* + * If we have fractional seconds, then include a decimal + * point We will do up to 6 fractional digits, and we have + * rounded any inputs to eliminate anything to the right + * of 6 digits anyway. If there are no fractional seconds, + * then do not bother printing a decimal point at all. - + * thomas 2001-09-29 + */ +#ifdef HAVE_INT64_TIMESTAMP + if (fsec != 0) + { + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + sprintf((str + strlen(str)), ".%06d", fsec); +#else + if ((fsec != 0) && (tm->tm_year > 0)) + { + sprintf((str + strlen(str)), ":%013.10f", sec); +#endif + TrimTrailingZeros(str); + } + else + { + sprintf((str + strlen(str)), ":%02d", tm->tm_sec); + } - sprintf((str + strlen(str)), " %04d", tm->tm_year); + sprintf((str + strlen(str)), " %04d", + ((tm->tm_year > 0)? tm->tm_year: -(tm->tm_year - 1))); + if (tm->tm_year <= 0) + { + sprintf((str + strlen(str)), " BC"); + } - if ((tzp != NULL) && (tm->tm_isdst >= 0)) + if ((tzp != NULL) && (tm->tm_isdst >= 0)) + { + if (*tzn != NULL) + sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); + else { - if (*tzn != NULL) - sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); - else - { - /* - * We have a time zone, but no string version. Use - * the numeric form, but be sure to include a - * leading space to avoid formatting something - * which would be rejected by the date/time parser - * later. - thomas 2001-10-19 - */ - hour = -(*tzp / 3600); - min = ((abs(*tzp) / 60) % 60); - sprintf((str + strlen(str)), ((min != 0) ? " %+03d:%02d" : " %+03d"), hour, min); - } + /* + * We have a time zone, but no string version. Use + * the numeric form, but be sure to include a + * leading space to avoid formatting something + * which would be rejected by the date/time parser + * later. - thomas 2001-10-19 + */ + hour = -(*tzp / 3600); + min = ((abs(*tzp) / 60) % 60); + sprintf((str + strlen(str)), ((min != 0) ? " %+03d:%02d" : " %+03d"), hour, min); } } - else - { - sprintf((str + 10), " %02d:%02d %04d %s", - tm->tm_hour, tm->tm_min, -(tm->tm_year - 1), "BC"); - } break; } @@ -3170,7 +3340,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha } /* EncodeDateTime() */ -/* EncodeTimeSpan() +/* EncodeInterval() * Interpret time structure as a delta time and convert to string. * * Support "traditional Postgres" and ISO-8601 styles. @@ -3179,7 +3349,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha * - thomas 1998-04-30 */ int -EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) +EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str) { int is_before = FALSE; int is_nonzero = FALSE; @@ -3239,8 +3409,14 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) /* fractional seconds? */ if (fsec != 0) { +#ifdef HAVE_INT64_TIMESTAMP + sprintf(cp, ":%02d", abs(tm->tm_sec)); + cp += strlen(cp); + sprintf(cp, ".%06d", ((fsec >= 0)? fsec: -(fsec))); +#else fsec += tm->tm_sec; sprintf(cp, ":%013.10f", fabs(fsec)); +#endif TrimTrailingZeros(cp); cp += strlen(cp); is_nonzero = TRUE; @@ -3336,7 +3512,16 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) /* fractional seconds? */ if (fsec != 0) { - double sec; +#ifdef HAVE_INT64_TIMESTAMP + if (is_before || ((!is_nonzero) && (tm->tm_sec < 0))) + tm->tm_sec = -tm->tm_sec; + sprintf(cp, "%s%d.%02d secs", (is_nonzero ? " " : ""), + tm->tm_sec, (((int) fsec) / 10000)); + cp += strlen(cp); + if (!is_nonzero) + is_before = (fsec < 0); +#else + fsec_t sec; fsec += tm->tm_sec; sec = fsec; @@ -3347,6 +3532,7 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) cp += strlen(cp); if (!is_nonzero) is_before = (fsec < 0); +#endif is_nonzero = TRUE; /* otherwise, integer seconds only? */ @@ -3382,7 +3568,7 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) } return 0; -} /* EncodeTimeSpan() */ +} /* EncodeInterval() */ void |