提交 e7946a53 编写于 作者: T 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().
上级 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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册