Commit e7946a53 authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Allow fractional values for delta times (e.g. '2.5 days').

Check valid numeric input more carefully for delta times.
Implement day of year as possible input to datetime_part().
parent 55a6b7a9
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.43 1997/10/25 05:18:17 thomas Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.44 1997/11/17 16:23:33 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1803,6 +1803,14 @@ datetime_part(text *units, DateTime *datetime) ...@@ -1803,6 +1803,14 @@ datetime_part(text *units, DateTime *datetime)
*result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); *result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
break; break;
case DTK_DOY:
if (datetime2tm(dt, &tz, tm, &fsec, &tzn) != 0)
elog(WARN, "Unable to encode datetime", NULL);
*result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
- date2j(tm->tm_year, 1, 1) + 1);
break;
default: default:
elog(WARN, "Datetime units '%s' not supported", lowunits); elog(WARN, "Datetime units '%s' not supported", lowunits);
*result = 0; *result = 0;
...@@ -2101,6 +2109,7 @@ static datetkn datetktbl[] = { ...@@ -2101,6 +2109,7 @@ static datetkn datetktbl[] = {
{"december", MONTH, 12}, {"december", MONTH, 12},
{"dnt", TZ, 6}, /* Dansk Normal Tid */ {"dnt", TZ, 6}, /* Dansk Normal Tid */
{"dow", RESERV, DTK_DOW}, /* day of week */ {"dow", RESERV, DTK_DOW}, /* day of week */
{"doy", RESERV, DTK_DOY}, /* day of year */
{"dst", DTZMOD, 6}, {"dst", DTZMOD, 6},
{"east", TZ, NEG(60)}, /* East Australian Std Time */ {"east", TZ, NEG(60)}, /* East Australian Std Time */
{"edt", DTZ, NEG(24)}, /* Eastern Daylight Time */ {"edt", DTZ, NEG(24)}, /* Eastern Daylight Time */
...@@ -2674,7 +2683,7 @@ ParseDateTime(char *timestr, char *lowstr, ...@@ -2674,7 +2683,7 @@ ParseDateTime(char *timestr, char *lowstr,
field[nf] = lp; field[nf] = lp;
/* leading digit? then date or time */ /* leading digit? then date or time */
if (isdigit(*cp)) if (isdigit(*cp) || (*cp == '.'))
{ {
*lp++ = *cp++; *lp++ = *cp++;
while (isdigit(*cp)) while (isdigit(*cp))
...@@ -2686,29 +2695,23 @@ ParseDateTime(char *timestr, char *lowstr, ...@@ -2686,29 +2695,23 @@ ParseDateTime(char *timestr, char *lowstr,
while (isdigit(*cp) || (*cp == ':') || (*cp == '.')) while (isdigit(*cp) || (*cp == ':') || (*cp == '.'))
*lp++ = *cp++; *lp++ = *cp++;
/* date field? allow embedded text month */
} }
/* date field? allow embedded text month */
else if ((*cp == '-') || (*cp == '/') || (*cp == '.')) else if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
{ {
ftype[nf] = DTK_DATE; ftype[nf] = DTK_DATE;
while (isalnum(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.')) while (isalnum(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.'))
*lp++ = tolower(*cp++); *lp++ = tolower(*cp++);
/*
* otherwise, number only and will determine year, month,
* or day later
*/
} }
/* otherwise, number only and will determine year, month, or day later */
else else
{ {
ftype[nf] = DTK_NUMBER; ftype[nf] = DTK_NUMBER;
} }
/*
* text? then date string, month, day of week, special, or
* timezone
*/
} }
/* text? then date string, month, day of week, special, or timezone */
else if (isalpha(*cp)) else if (isalpha(*cp))
{ {
ftype[nf] = DTK_STRING; ftype[nf] = DTK_STRING;
...@@ -3696,6 +3699,9 @@ DecodeSpecial(int field, char *lowtoken, int *val) ...@@ -3696,6 +3699,9 @@ DecodeSpecial(int field, char *lowtoken, int *val)
* Interpret previously parsed fields for general time interval. * Interpret previously parsed fields for general time interval.
* Return 0 if decoded and -1 if problems. * Return 0 if decoded and -1 if problems.
* *
* Allow "date" field DTK_DATE since this could be just
* an unsigned floating point number. - thomas 1997-11-16
*
* If code is changed to read fields from first to last, * If code is changed to read fields from first to last,
* then use READ_FORWARD-bracketed code to allow sign * then use READ_FORWARD-bracketed code to allow sign
* to persist to subsequent unsigned fields. * to persist to subsequent unsigned fields.
...@@ -3709,6 +3715,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3709,6 +3715,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
int is_neg = FALSE; int is_neg = FALSE;
#endif #endif
char *cp;
int fmask = 0, int fmask = 0,
tmask, tmask,
type; type;
...@@ -3716,7 +3723,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3716,7 +3723,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
ii; ii;
int flen, int flen,
val; val;
char *cp; double fval;
double sec; double sec;
*dtype = DTK_DELTA; *dtype = DTK_DELTA;
...@@ -3774,6 +3781,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3774,6 +3781,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
is_neg = (*field[i] == '-'); is_neg = (*field[i] == '-');
#endif #endif
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 READ_FORWARD
...@@ -3782,70 +3790,102 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, ...@@ -3782,70 +3790,102 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
#endif #endif
if (*cp == '.') if (*cp == '.')
{ {
fval = strtod(cp, &cp);
if (*cp != '\0')
return -1;
if (val < 0)
fval = -(fval);
#if FALSE
*fsec = strtod(cp, NULL); *fsec = strtod(cp, NULL);
if (val < 0) if (val < 0)
*fsec = -(*fsec); *fsec = -(*fsec);
#endif
} }
else if (*cp == '\0')
fval = 0;
else
return -1;
flen = strlen(field[i]); flen = strlen(field[i]);
tmask = 0; /* DTK_M(type); */ tmask = 0; /* DTK_M(type); */
switch (type) switch (type)
{ {
case DTK_MICROSEC: case DTK_MICROSEC:
*fsec += (val * 1e-6); *fsec += ((val + fval) * 1e-6);
break; break;
case DTK_MILLISEC: case DTK_MILLISEC:
*fsec += (val * 1e-3); *fsec += ((val +fval) * 1e-3);
break; break;
case DTK_SECOND: case DTK_SECOND:
tm->tm_sec += val; tm->tm_sec += val;
*fsec += fval;
tmask = DTK_M(SECOND); tmask = DTK_M(SECOND);
break; break;
case DTK_MINUTE: case DTK_MINUTE:
tm->tm_min += val; tm->tm_min += val;
if (fval != 0)
tm->tm_sec += (fval * 60);
tmask = DTK_M(MINUTE); tmask = DTK_M(MINUTE);
break; break;
case DTK_HOUR: case DTK_HOUR:
tm->tm_hour += val; tm->tm_hour += val;
if (fval != 0)
tm->tm_sec += (fval * 3600);
tmask = DTK_M(HOUR); tmask = DTK_M(HOUR);
break; break;
case DTK_DAY: case DTK_DAY:
tm->tm_mday += val; tm->tm_mday += val;
if (fval != 0)
tm->tm_sec += (fval * 86400);
tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY)); tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY));
break; break;
case DTK_WEEK: case DTK_WEEK:
tm->tm_mday += val * 7; tm->tm_mday += val * 7;
if (fval != 0)
tm->tm_sec += (fval * (7*86400));
tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY)); tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY));
break; break;
case DTK_MONTH: case DTK_MONTH:
tm->tm_mon += val; tm->tm_mon += val;
if (fval != 0)
tm->tm_sec += (fval * (30*86400));
tmask = DTK_M(MONTH); tmask = DTK_M(MONTH);
break; break;
case DTK_YEAR: case DTK_YEAR:
tm->tm_year += val; tm->tm_year += val;
if (fval != 0)
tm->tm_mon += (fval * 12);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break; break;
case DTK_DECADE: case DTK_DECADE:
tm->tm_year += val * 10; tm->tm_year += val * 10;
if (fval != 0)
tm->tm_mon += (fval * 120);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break; break;
case DTK_CENTURY: case DTK_CENTURY:
tm->tm_year += val * 100; tm->tm_year += val * 100;
if (fval != 0)
tm->tm_mon += (fval * 1200);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break; break;
case DTK_MILLENIUM: case DTK_MILLENIUM:
tm->tm_year += val * 1000; tm->tm_year += val * 1000;
if (fval != 0)
tm->tm_mon += (fval * 12000);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR)); tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break; break;
......
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