8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -448,7 +448,7 @@ TrimTrailingZeros(char *str)
448
448
* DTK_TIME - digits, colon delimiters, and possibly a decimal point
449
449
* DTK_STRING - text (no digits or punctuation)
450
450
* 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 ':', '.', '- ')
452
452
*
453
453
* Note that some field types can hold unexpected items:
454
454
* DTK_NUMBER can hold date fields (yy.ddd)
@@ -610,12 +610,13 @@ ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
610
610
while (isspace ((unsigned char ) * cp ))
611
611
cp ++ ;
612
612
/* numeric timezone? */
613
+ /* note that "DTK_TZ" could also be a signed float or yyyy-mm */
613
614
if (isdigit ((unsigned char ) * cp ))
614
615
{
615
616
ftype [nf ] = DTK_TZ ;
616
617
APPEND_CHAR (bufp , bufend , * cp ++ );
617
618
while (isdigit ((unsigned char ) * cp ) ||
618
- * cp == ':' || * cp == '.' )
619
+ * cp == ':' || * cp == '.' || * cp == '-' )
619
620
APPEND_CHAR (bufp , bufend , * cp ++ );
620
621
}
621
622
/* special? */
@@ -2774,19 +2775,17 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
2774
2775
2775
2776
/*
2776
2777
* 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.
2778
2780
*/
2779
2781
Assert (* field [i ] == '-' || * field [i ] == '+' );
2780
2782
2781
2783
/*
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 .
2785
2787
*/
2786
- cp = field [i ] + 1 ;
2787
- while (* cp != '\0' && * cp != ':' && * cp != '.' )
2788
- cp ++ ;
2789
- if (* cp == ':' &&
2788
+ if (strchr (field [i ] + 1 , ':' ) != NULL &&
2790
2789
DecodeTime (field [i ] + 1 , fmask , INTERVAL_FULL_RANGE ,
2791
2790
& tmask , tm , fsec ) == 0 )
2792
2791
{
@@ -2808,32 +2807,13 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
2808
2807
tmask = DTK_M (TZ );
2809
2808
break ;
2810
2809
}
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
- }
2830
2810
/* FALL THROUGH */
2831
2811
2832
2812
case DTK_DATE :
2833
2813
case DTK_NUMBER :
2834
2814
if (type == IGNORE_DTF )
2835
2815
{
2836
- /* use typmod to decide what rightmost integer field is */
2816
+ /* use typmod to decide what rightmost field is */
2837
2817
switch (range )
2838
2818
{
2839
2819
case INTERVAL_MASK (YEAR ):
@@ -2883,6 +2863,8 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
2883
2863
if (* cp != '\0' )
2884
2864
return DTERR_BAD_FORMAT ;
2885
2865
type = DTK_MONTH ;
2866
+ if (val < 0 )
2867
+ val2 = - val2 ;
2886
2868
val = val * MONTHS_PER_YEAR + val2 ;
2887
2869
fval = 0 ;
2888
2870
}
0 commit comments