Commit 8e602a3c authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Define "tz_hour" and "tz_minute" arguments to date_part().

Fix up "ISO-style" timespan decoding and encoding.
parent 3be86c98
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.52 1998/02/26 04:37:02 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.53 1998/05/09 22:38:18 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1241,17 +1241,6 @@ datetime_age(DateTime *datetime1, DateTime *datetime2) ...@@ -1241,17 +1241,6 @@ datetime_age(DateTime *datetime1, DateTime *datetime2)
elog(ERROR, "Unable to decode datetime", NULL); elog(ERROR, "Unable to decode datetime", NULL);
} }
#if FALSE
result->time = (fsec2 - fsec1);
result->time += (tm2->tm_sec - tm1->tm_sec);
result->time += 60 * (tm2->tm_min - tm1->tm_min);
result->time += 3600 * (tm2->tm_hour - tm1->tm_hour);
result->time += 86400 * (tm2->tm_mday - tm1->tm_mday);
result->month = 12 * (tm2->tm_year - tm1->tm_year);
result->month += (tm2->tm_mon - tm1->tm_mon);
#endif
} }
else else
{ {
...@@ -1419,12 +1408,6 @@ datetime_trunc(text *units, DateTime *datetime) ...@@ -1419,12 +1408,6 @@ datetime_trunc(text *units, DateTime *datetime)
*lp = '\0'; *lp = '\0';
type = DecodeUnits(0, lowunits, &val); type = DecodeUnits(0, lowunits, &val);
#if FALSE
if (type == IGNORE)
{
type = DecodeSpecial(0, lowunits, &val);
}
#endif
#ifdef DATEDEBUG #ifdef DATEDEBUG
if (type == IGNORE) if (type == IGNORE)
...@@ -1564,12 +1547,6 @@ timespan_trunc(text *units, TimeSpan *timespan) ...@@ -1564,12 +1547,6 @@ timespan_trunc(text *units, TimeSpan *timespan)
*lp = '\0'; *lp = '\0';
type = DecodeUnits(0, lowunits, &val); type = DecodeUnits(0, lowunits, &val);
#if FALSE
if (type == IGNORE)
{
type = DecodeSpecial(0, lowunits, &val);
}
#endif
#ifdef DATEDEBUG #ifdef DATEDEBUG
if (type == IGNORE) if (type == IGNORE)
...@@ -1676,6 +1653,7 @@ datetime_part(text *units, DateTime *datetime) ...@@ -1676,6 +1653,7 @@ datetime_part(text *units, DateTime *datetime)
char *up, char *up,
*lp, *lp,
lowunits[MAXDATELEN + 1]; lowunits[MAXDATELEN + 1];
double dummy;
double fsec; double fsec;
char *tzn; char *tzn;
struct tm tt, struct tm tt,
...@@ -1725,6 +1703,16 @@ datetime_part(text *units, DateTime *datetime) ...@@ -1725,6 +1703,16 @@ datetime_part(text *units, DateTime *datetime)
*result = tz; *result = tz;
break; break;
case DTK_TZ_MINUTE:
*result = tz / 60;
TMODULO(*result, dummy, 60e0);
break;
case DTK_TZ_HOUR:
dummy = tz;
TMODULO(dummy, *result, 3600e0);
break;
case DTK_MICROSEC: case DTK_MICROSEC:
*result = (fsec * 1000000); *result = (fsec * 1000000);
break; break;
...@@ -2248,8 +2236,7 @@ static datetkn deltatktbl[] = { ...@@ -2248,8 +2236,7 @@ static datetkn deltatktbl[] = {
{"mils", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ {"mils", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */
{"millenia", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */ {"millenia", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */
{DMILLENIUM, UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */ {DMILLENIUM, UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */
{"millisecon", UNITS, DTK_MILLISEC}, /* "millisecond" relative {"millisecon", UNITS, DTK_MILLISEC}, /* relative time units */
* time units */
{"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */ {"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */
{"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */ {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
{"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */ {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
...@@ -2258,29 +2245,25 @@ static datetkn deltatktbl[] = { ...@@ -2258,29 +2245,25 @@ static datetkn deltatktbl[] = {
{"mon", UNITS, DTK_MONTH}, /* "months" relative time units */ {"mon", UNITS, DTK_MONTH}, /* "months" relative time units */
{"mons", UNITS, DTK_MONTH}, /* "months" relative time units */ {"mons", UNITS, DTK_MONTH}, /* "months" relative time units */
{DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */ {DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */
{"months", UNITS, DTK_MONTH}, /* "months" relative time units */ {"months", UNITS, DTK_MONTH},
{"ms", UNITS, DTK_MILLISEC},/* "millisecond" relative time units */ {"ms", UNITS, DTK_MILLISEC},
{"msec", UNITS, DTK_MILLISEC}, /* "millisecond" relative time {"msec", UNITS, DTK_MILLISEC},
* units */ {DMILLISEC, UNITS, DTK_MILLISEC},
{DMILLISEC, UNITS, DTK_MILLISEC}, /* "millisecond" relative time {"mseconds", UNITS, DTK_MILLISEC},
* units */ {"msecs", UNITS, DTK_MILLISEC},
{"mseconds", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time {"qtr", UNITS, DTK_QUARTER}, /* "quarter" relative time */
* units */ {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative time */
{"msecs", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time {"reltime", IGNORE, 0}, /* for pre-v6.1 "Undefined Reltime" */
* units */ {"s", UNITS, DTK_SECOND},
{"qtr", UNITS, DTK_QUARTER},/* "quarter" relative time units */ {"sec", UNITS, DTK_SECOND},
{DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative time units */ {DSECOND, UNITS, DTK_SECOND},
{"reltime", IGNORE, 0}, /* "reltime" for pre-v6.1 "Undefined {"seconds", UNITS, DTK_SECOND},
* Reltime" */ {"secs", UNITS, DTK_SECOND},
{"s", UNITS, DTK_SECOND}, /* "second" relative time units */
{"sec", UNITS, DTK_SECOND}, /* "second" relative time units */
{DSECOND, UNITS, DTK_SECOND}, /* "second" relative time units */
{"seconds", UNITS, DTK_SECOND}, /* "seconds" relative time units */
{"secs", UNITS, DTK_SECOND},/* "seconds" relative time units */
{DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */ {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
{"tz", UNITS, DTK_TZ}, /* "timezone" time offset */ {"tz", UNITS, DTK_TZ}, /* "timezone" time offset */
{"undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid {"tz_hour", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
* time */ {"tz_minute", UNITS, DTK_TZ_MINUTE}, /* timezone minutes units */
{"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
{"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */ {"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */
{"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative time {"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative time
* units */ * units */
...@@ -2444,7 +2427,7 @@ datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn) ...@@ -2444,7 +2427,7 @@ datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
#endif #endif
*fsec = JROUND(sec); *fsec = JROUND(sec);
TMODULO(*fsec, tm->tm_sec, 1); TMODULO(*fsec, tm->tm_sec, 1e0);
#ifdef DATEDEBUG #ifdef DATEDEBUG
printf("datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec); printf("datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec);
...@@ -2455,10 +2438,6 @@ datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn) ...@@ -2455,10 +2438,6 @@ datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
{ {
utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400); utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400);
#if FALSE
if (utime < -1)
utime++;
#endif
#ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME
tx = localtime(&utime); tx = localtime(&utime);
...@@ -2607,7 +2586,7 @@ timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec) ...@@ -2607,7 +2586,7 @@ timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec)
TMODULO(time, tm->tm_mday, 86400e0); TMODULO(time, tm->tm_mday, 86400e0);
TMODULO(time, tm->tm_hour, 3600e0); TMODULO(time, tm->tm_hour, 3600e0);
TMODULO(time, tm->tm_min, 60e0); TMODULO(time, tm->tm_min, 60e0);
TMODULO(time, tm->tm_sec, 1); TMODULO(time, tm->tm_sec, 1e0);
*fsec = time; *fsec = time;
#ifdef DATEDEBUG #ifdef DATEDEBUG
...@@ -3719,26 +3698,19 @@ DecodeSpecial(int field, char *lowtoken, int *val) ...@@ -3719,26 +3698,19 @@ DecodeSpecial(int field, char *lowtoken, int *val)
* Allow "date" field DTK_DATE since this could be just * Allow "date" field DTK_DATE since this could be just
* an unsigned floating point number. - thomas 1997-11-16 * an unsigned floating point number. - thomas 1997-11-16
* *
* If code is changed to read fields from first to last, * Allow ISO-style time span, with implicit units on number of days
* then use READ_FORWARD-bracketed code to allow sign * preceeding an hh:mm:ss field. - thomas 1998-04-30
* to persist to subsequent unsigned fields.
*/ */
int int
DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, double *fsec) DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, double *fsec)
{ {
int is_before = FALSE; int is_before = FALSE;
#if READ_FORWARD
int is_neg = FALSE;
#endif
char *cp; char *cp;
int fmask = 0, int fmask = 0,
tmask, tmask,
type; type;
int i, int i;
ii;
int flen, int flen,
val; val;
double fval; double fval;
...@@ -3755,30 +3727,8 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3755,30 +3727,8 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
tm->tm_sec = 0; tm->tm_sec = 0;
*fsec = 0; *fsec = 0;
/* read through list forwards to pick up initial time fields, if any */ /* read through list backwards to pick up units before values */
for (ii = 0; ii < nf; ii++) for (i = nf - 1; i >= 0; i--)
{
#ifdef DATEDEBUG
printf("DecodeDateDelta- field[%d] is %s (type %d)\n", ii, field[ii], ftype[ii]);
#endif
if (ftype[ii] == DTK_TIME)
{
if (DecodeTime(field[ii], fmask, &tmask, tm, fsec) != 0)
return -1;
fmask |= tmask;
}
else
{
break;
}
}
/*
* read through remaining list backwards to pick up units before
* values
*/
for (i = nf - 1; i >= ii; i--)
{ {
#ifdef DATEDEBUG #ifdef DATEDEBUG
printf("DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]); printf("DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]);
...@@ -3786,27 +3736,18 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3786,27 +3736,18 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
switch (ftype[i]) switch (ftype[i])
{ {
case DTK_TIME: case DTK_TIME:
/* already read in forward-scan above so return error */
#if FALSE
if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)
return -1; return -1;
#endif type = DTK_DAY;
return -1;
break; break;
case DTK_TZ: /* timezone is a token with a leading sign case DTK_TZ:
* character */ /* Timezone is a token with a leading sign character
#if READ_FORWARD * and otherwise the same as a non-signed numeric field
is_neg = (*field[i] == '-'); */
#endif
case DTK_DATE: case DTK_DATE:
case DTK_NUMBER: case DTK_NUMBER:
val = strtol(field[i], &cp, 10); val = strtol(field[i], &cp, 10);
#if READ_FORWARD
if (is_neg && (val > 0))
val = -val;
#endif
if (*cp == '.') if (*cp == '.')
{ {
fval = strtod(cp, &cp); fval = strtod(cp, &cp);
...@@ -3815,11 +3756,6 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3815,11 +3756,6 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
if (val < 0) if (val < 0)
fval = -(fval); fval = -(fval);
#if FALSE
*fsec = strtod(cp, NULL);
if (val < 0)
*fsec = -(*fsec);
#endif
} }
else if (*cp == '\0') else if (*cp == '\0')
fval = 0; fval = 0;
...@@ -3963,7 +3899,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3963,7 +3899,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
if (*fsec != 0) if (*fsec != 0)
{ {
TMODULO(*fsec, sec, 1); TMODULO(*fsec, sec, 1e0);
tm->tm_sec += sec; tm->tm_sec += sec;
} }
...@@ -4380,8 +4316,10 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha ...@@ -4380,8 +4316,10 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
/* EncodeTimeSpan() /* EncodeTimeSpan()
* Interpret time structure as a delta time and convert to string. * Interpret time structure as a delta time and convert to string.
* *
* Pass a flag to specify the style of string, but only implement * Support "traditional Postgres" and ISO-8601 styles.
* the traditional Postgres style for now. - tgl 97/03/27 * Actually, afaik ISO does not address time interval formatting,
* but this looks similar to the spec for absolute date/time.
* - thomas 1998-04-30
*/ */
int int
EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
...@@ -4397,100 +4335,113 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) ...@@ -4397,100 +4335,113 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
break; break;
default: default:
strcpy(cp, "@"); strcpy(cp, "@ ");
cp += strlen(cp); cp += strlen(cp);
break; break;
} }
if (tm->tm_year != 0) if (tm->tm_year != 0)
{ {
is_nonzero = TRUE;
is_before |= (tm->tm_year < 0); is_before |= (tm->tm_year < 0);
sprintf(cp, " %d year%s", abs(tm->tm_year), ((abs(tm->tm_year) != 1) ? "s" : "")); sprintf(cp, "%d year%s",
abs(tm->tm_year), ((abs(tm->tm_year) != 1) ? "s" : ""));
cp += strlen(cp); cp += strlen(cp);
is_nonzero = TRUE;
} }
if (tm->tm_mon != 0) if (tm->tm_mon != 0)
{ {
is_nonzero = TRUE;
is_before |= (tm->tm_mon < 0); is_before |= (tm->tm_mon < 0);
sprintf(cp, " %d mon%s", abs(tm->tm_mon), ((abs(tm->tm_mon) != 1) ? "s" : "")); sprintf(cp, "%s%d mon%s", (is_nonzero? " ": ""),
abs(tm->tm_mon), ((abs(tm->tm_mon) != 1) ? "s" : ""));
cp += strlen(cp); cp += strlen(cp);
}
if (tm->tm_mday != 0)
{
is_nonzero = TRUE; is_nonzero = TRUE;
is_before |= (tm->tm_mday < 0);
sprintf(cp, " %d day%s", abs(tm->tm_mday), ((abs(tm->tm_mday) != 1) ? "s" : ""));
cp += strlen(cp);
} }
switch (style) switch (style)
{ {
/* compatible with ISO date formats */ /* compatible with ISO date formats */
case USE_ISO_DATES: case USE_ISO_DATES:
if ((tm->tm_hour != 0) || (tm->tm_min != 0)) if (tm->tm_mday != 0)
{
is_before |= (tm->tm_mday < 0);
sprintf(cp, "%s%d", (is_nonzero? " ": ""), abs(tm->tm_mday));
cp += strlen(cp);
is_nonzero = TRUE; is_nonzero = TRUE;
}
is_before |= ((tm->tm_hour < 0) || (tm->tm_min < 0)); is_before |= ((tm->tm_hour < 0) || (tm->tm_min < 0));
sprintf(cp, " %02d:%02d", abs(tm->tm_hour), abs(tm->tm_min)); sprintf(cp, "%s%02d:%02d", (is_nonzero? " ": ""),
abs(tm->tm_hour), abs(tm->tm_min));
cp += strlen(cp); cp += strlen(cp);
if ((tm->tm_hour != 0) || (tm->tm_min != 0))
is_nonzero = TRUE;
/* fractional seconds? */ /* fractional seconds? */
if (fsec != 0) if (fsec != 0)
{ {
is_nonzero = TRUE;
fsec += tm->tm_sec; fsec += tm->tm_sec;
is_before |= (fsec < 0); is_before |= (fsec < 0);
sprintf(cp, ":%05.2f", fabs(fsec)); sprintf(cp, ":%05.2f", fabs(fsec));
cp += strlen(cp); cp += strlen(cp);
is_nonzero = TRUE;
/* otherwise, integer seconds only? */ /* otherwise, integer seconds only? */
} }
else if (tm->tm_sec != 0) else if (tm->tm_sec != 0)
{ {
is_nonzero = TRUE;
is_before |= (tm->tm_sec < 0); is_before |= (tm->tm_sec < 0);
sprintf(cp, ":%02d", abs(tm->tm_sec)); sprintf(cp, ":%02d", abs(tm->tm_sec));
cp += strlen(cp); cp += strlen(cp);
is_nonzero = TRUE;
} }
break; break;
case USE_POSTGRES_DATES: case USE_POSTGRES_DATES:
default: default:
if (tm->tm_hour != 0) if (tm->tm_mday != 0)
{ {
is_before |= (tm->tm_mday < 0);
sprintf(cp, "%s%d day%s", (is_nonzero? " ": ""),
abs(tm->tm_mday), ((abs(tm->tm_mday) != 1) ? "s" : ""));
cp += strlen(cp);
is_nonzero = TRUE; is_nonzero = TRUE;
}
if (tm->tm_hour != 0)
{
is_before |= (tm->tm_hour < 0); is_before |= (tm->tm_hour < 0);
sprintf(cp, " %d hour%s", abs(tm->tm_hour), ((abs(tm->tm_hour) != 1) ? "s" : "")); sprintf(cp, "%s%d hour%s", (is_nonzero? " ": ""),
abs(tm->tm_hour), ((abs(tm->tm_hour) != 1) ? "s" : ""));
cp += strlen(cp); cp += strlen(cp);
is_nonzero = TRUE;
} }
if (tm->tm_min != 0) if (tm->tm_min != 0)
{ {
is_nonzero = TRUE;
is_before |= (tm->tm_min < 0); is_before |= (tm->tm_min < 0);
sprintf(cp, " %d min%s", abs(tm->tm_min), ((abs(tm->tm_min) != 1) ? "s" : "")); sprintf(cp, "%s%d min%s", (is_nonzero? " ": ""),
abs(tm->tm_min), ((abs(tm->tm_min) != 1) ? "s" : ""));
cp += strlen(cp); cp += strlen(cp);
is_nonzero = TRUE;
} }
/* fractional seconds? */ /* fractional seconds? */
if (fsec != 0) if (fsec != 0)
{ {
is_nonzero = TRUE;
fsec += tm->tm_sec; fsec += tm->tm_sec;
is_before |= (fsec < 0); is_before |= (fsec < 0);
sprintf(cp, " %.2f secs", fabs(fsec)); sprintf(cp, "%s%.2f secs", (is_nonzero? " ": ""), fabs(fsec));
cp += strlen(cp); cp += strlen(cp);
is_nonzero = TRUE;
/* otherwise, integer seconds only? */ /* otherwise, integer seconds only? */
} }
else if (tm->tm_sec != 0) else if (tm->tm_sec != 0)
{ {
is_nonzero = TRUE;
is_before |= (tm->tm_sec < 0); is_before |= (tm->tm_sec < 0);
sprintf(cp, " %d sec%s", abs(tm->tm_sec), ((abs(tm->tm_sec) != 1) ? "s" : "")); sprintf(cp, "%s%d sec%s", (is_nonzero? " ": ""),
abs(tm->tm_sec), ((abs(tm->tm_sec) != 1) ? "s" : ""));
cp += strlen(cp); cp += strlen(cp);
is_nonzero = TRUE;
} }
break; break;
} }
...@@ -4498,7 +4449,7 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) ...@@ -4498,7 +4449,7 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
/* identically zero? then put in a unitless zero... */ /* identically zero? then put in a unitless zero... */
if (!is_nonzero) if (!is_nonzero)
{ {
strcat(cp, " 0"); strcat(cp, "0");
cp += strlen(cp); cp += strlen(cp);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment