summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas G. Lockhart <lockhart@fourpalms.org>1997-11-17 16:23:33 +0000
committerThomas G. Lockhart <lockhart@fourpalms.org>1997-11-17 16:23:33 +0000
commite7946a53ad08137ef50d38c55c40fc7083d579a3 (patch)
tree14bf449d8aea43c6f22e0fac13fabe00efbf086d
parent55a6b7a9be54289fd9feef589cbe2e8d4f52ed4e (diff)
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().
-rw-r--r--src/backend/utils/adt/dt.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c
index 070e25230fb..b3b826fab8b 100644
--- a/src/backend/utils/adt/dt.c
+++ b/src/backend/utils/adt/dt.c
@@ -7,7 +7,7 @@
*
*
* 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));
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:
elog(WARN, "Datetime units '%s' not supported", lowunits);
*result = 0;
@@ -2101,6 +2109,7 @@ static datetkn datetktbl[] = {
{"december", MONTH, 12},
{"dnt", TZ, 6}, /* Dansk Normal Tid */
{"dow", RESERV, DTK_DOW}, /* day of week */
+ {"doy", RESERV, DTK_DOY}, /* day of year */
{"dst", DTZMOD, 6},
{"east", TZ, NEG(60)}, /* East Australian Std Time */
{"edt", DTZ, NEG(24)}, /* Eastern Daylight Time */
@@ -2674,7 +2683,7 @@ ParseDateTime(char *timestr, char *lowstr,
field[nf] = lp;
/* leading digit? then date or time */
- if (isdigit(*cp))
+ if (isdigit(*cp) || (*cp == '.'))
{
*lp++ = *cp++;
while (isdigit(*cp))
@@ -2686,29 +2695,23 @@ ParseDateTime(char *timestr, char *lowstr,
while (isdigit(*cp) || (*cp == ':') || (*cp == '.'))
*lp++ = *cp++;
- /* date field? allow embedded text month */
}
+ /* date field? allow embedded text month */
else if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
{
ftype[nf] = DTK_DATE;
while (isalnum(*cp) || (*cp == '-') || (*cp == '/') || (*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
{
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))
{
ftype[nf] = DTK_STRING;
@@ -3696,6 +3699,9 @@ DecodeSpecial(int field, char *lowtoken, int *val)
* Interpret previously parsed fields for general time interval.
* 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,
* then use READ_FORWARD-bracketed code to allow sign
* 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;
#endif
+ char *cp;
int fmask = 0,
tmask,
type;
@@ -3716,7 +3723,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
ii;
int flen,
val;
- char *cp;
+ double fval;
double sec;
*dtype = DTK_DELTA;
@@ -3774,6 +3781,7 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
is_neg = (*field[i] == '-');
#endif
+ case DTK_DATE:
case DTK_NUMBER:
val = strtol(field[i], &cp, 10);
#if READ_FORWARD
@@ -3782,70 +3790,102 @@ DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm,
#endif
if (*cp == '.')
{
+ fval = strtod(cp, &cp);
+ if (*cp != '\0')
+ return -1;
+
+ if (val < 0)
+ fval = -(fval);
+#if FALSE
*fsec = strtod(cp, NULL);
if (val < 0)
*fsec = -(*fsec);
+#endif
}
+ else if (*cp == '\0')
+ fval = 0;
+ else
+ return -1;
+
flen = strlen(field[i]);
tmask = 0; /* DTK_M(type); */
switch (type)
{
case DTK_MICROSEC:
- *fsec += (val * 1e-6);
+ *fsec += ((val + fval) * 1e-6);
break;
case DTK_MILLISEC:
- *fsec += (val * 1e-3);
+ *fsec += ((val +fval) * 1e-3);
break;
case DTK_SECOND:
tm->tm_sec += val;
+ *fsec += fval;
tmask = DTK_M(SECOND);
break;
case DTK_MINUTE:
tm->tm_min += val;
+ if (fval != 0)
+ tm->tm_sec += (fval * 60);
tmask = DTK_M(MINUTE);
break;
case DTK_HOUR:
tm->tm_hour += val;
+ if (fval != 0)
+ tm->tm_sec += (fval * 3600);
tmask = DTK_M(HOUR);
break;
case DTK_DAY:
tm->tm_mday += val;
+ if (fval != 0)
+ tm->tm_sec += (fval * 86400);
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));
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));
tmask = DTK_M(MONTH);
break;
case DTK_YEAR:
tm->tm_year += val;
+ if (fval != 0)
+ tm->tm_mon += (fval * 12);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break;
case DTK_DECADE:
tm->tm_year += val * 10;
+ if (fval != 0)
+ tm->tm_mon += (fval * 120);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break;
case DTK_CENTURY:
tm->tm_year += val * 100;
+ if (fval != 0)
+ tm->tm_mon += (fval * 1200);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break;
case DTK_MILLENIUM:
tm->tm_year += val * 1000;
+ if (fval != 0)
+ tm->tm_mon += (fval * 12000);
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
break;