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().
This commit is contained in:
parent
55a6b7a9be
commit
e7946a53ad
@ -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)
|
|||||||
*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[] = {
|
|||||||
{"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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
#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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user