summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/datetime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/datetime.c')
-rw-r--r--src/backend/utils/adt/datetime.c556
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