88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.192 2008/09/11 15:27:30 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.193 2008/09/16 22:31:21 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -448,7 +448,7 @@ TrimTrailingZeros(char *str)
448448 * DTK_TIME - digits, colon delimiters, and possibly a decimal point
449449 * DTK_STRING - text (no digits or punctuation)
450450 * DTK_SPECIAL - leading "+" or "-" followed by text
451- * DTK_TZ - leading "+" or "-" followed by digits (also eats ':' or '. ')
451+ * DTK_TZ - leading "+" or "-" followed by digits (also eats ':', '.', '- ')
452452 *
453453 * Note that some field types can hold unexpected items:
454454 * DTK_NUMBER can hold date fields (yy.ddd)
@@ -610,12 +610,13 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
610610 while (isspace ((unsigned char ) * cp ))
611611 cp ++ ;
612612 /* numeric timezone? */
613+ /* note that "DTK_TZ" could also be a signed float or yyyy-mm */
613614 if (isdigit ((unsigned char ) * cp ))
614615 {
615616 ftype [nf ] = DTK_TZ ;
616617 APPEND_CHAR (bufp , bufend , * cp ++ );
617618 while (isdigit ((unsigned char ) * cp ) ||
618- * cp == ':' || * cp == '.' )
619+ * cp == ':' || * cp == '.' || * cp == '-' )
619620 APPEND_CHAR (bufp , bufend , * cp ++ );
620621 }
621622 /* special? */
@@ -2774,19 +2775,17 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
27742775
27752776 /*
27762777 * Timezone is a token with a leading sign character and
2777- * otherwise the same as a non-signed time field
2778+ * at least one digit; there could be ':', '.', '-'
2779+ * embedded in it as well.
27782780 */
27792781 Assert (* field [i ] == '-' || * field [i ] == '+' );
27802782
27812783 /*
2782- * A single signed number ends up here, but will be rejected
2783- * by DecodeTime(). So, work this out to drop through to
2784- * DTK_NUMBER, which *can* tolerate this .
2784+ * Try for hh:mm or hh:mm:ss. If not, fall through to
2785+ * DTK_NUMBER case, which can handle signed float numbers
2786+ * and signed year-month values .
27852787 */
2786- cp = field [i ] + 1 ;
2787- while (* cp != '\0' && * cp != ':' && * cp != '.' )
2788- cp ++ ;
2789- if (* cp == ':' &&
2788+ if (strchr (field [i ] + 1 , ':' ) != NULL &&
27902789 DecodeTime (field [i ] + 1 , fmask , INTERVAL_FULL_RANGE ,
27912790 & tmask , tm , fsec ) == 0 )
27922791 {
@@ -2808,32 +2807,13 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
28082807 tmask = DTK_M (TZ );
28092808 break ;
28102809 }
2811- else if (type == IGNORE_DTF )
2812- {
2813- if (* cp == '.' )
2814- {
2815- /*
2816- * Got a decimal point? Then assume some sort of
2817- * seconds specification
2818- */
2819- type = DTK_SECOND ;
2820- }
2821- else if (* cp == '\0' )
2822- {
2823- /*
2824- * Only a signed integer? Then must assume a
2825- * timezone-like usage
2826- */
2827- type = DTK_HOUR ;
2828- }
2829- }
28302810 /* FALL THROUGH */
28312811
28322812 case DTK_DATE :
28332813 case DTK_NUMBER :
28342814 if (type == IGNORE_DTF )
28352815 {
2836- /* use typmod to decide what rightmost integer field is */
2816+ /* use typmod to decide what rightmost field is */
28372817 switch (range )
28382818 {
28392819 case INTERVAL_MASK (YEAR ):
@@ -2883,6 +2863,8 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
28832863 if (* cp != '\0' )
28842864 return DTERR_BAD_FORMAT ;
28852865 type = DTK_MONTH ;
2866+ if (val < 0 )
2867+ val2 = - val2 ;
28862868 val = val * MONTHS_PER_YEAR + val2 ;
28872869 fval = 0 ;
28882870 }
0 commit comments