88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.118 2003/09/25 06:58:03 petere Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.119 2003/11/16 20:29:16 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2525#include "utils/guc.h"
2626
2727
28- static int DecodeNumber (int flen ,char * field ,
28+ static int DecodeNumber (int flen ,char * field ,bool haveTextMonth ,
2929int fmask ,int * tmask ,
3030struct tm * tm ,fsec_t * fsec ,int * is2digits );
3131static int DecodeNumberField (int len ,char * str ,
@@ -924,7 +924,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
924924int val ;
925925int dterr ;
926926int mer = HR24 ;
927- int haveTextMonth = FALSE;
927+ bool haveTextMonth = FALSE;
928928int is2digits = FALSE;
929929int bc = FALSE;
930930
@@ -1281,7 +1281,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
12811281/* otherwise it is a single date/time field... */
12821282else
12831283{
1284- dterr = DecodeNumber (flen ,field [i ],fmask ,
1284+ dterr = DecodeNumber (flen ,field [i ],
1285+ haveTextMonth ,fmask ,
12851286& tmask ,tm ,
12861287fsec ,& is2digits );
12871288if (dterr )
@@ -2032,6 +2033,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
20322033else
20332034{
20342035dterr = DecodeNumber (flen ,field [i ],
2036+ FALSE,
20352037 (fmask |DTK_DATE_M ),
20362038& tmask ,tm ,
20372039fsec ,& is2digits );
@@ -2229,6 +2231,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
22292231int i ,
22302232len ;
22312233int dterr ;
2234+ bool haveTextMonth = FALSE;
22322235int bc = FALSE;
22332236int is2digits = FALSE;
22342237int type ,
@@ -2283,6 +2286,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
22832286{
22842287case MONTH :
22852288tm -> tm_mon = val ;
2289+ haveTextMonth = TRUE;
22862290break ;
22872291
22882292case ADBC :
@@ -2312,7 +2316,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
23122316if ((len = strlen (field [i ])) <=0 )
23132317return DTERR_BAD_FORMAT ;
23142318
2315- dterr = DecodeNumber (len ,field [i ],fmask ,
2319+ dterr = DecodeNumber (len ,field [i ],haveTextMonth , fmask ,
23162320& dmask ,tm ,
23172321& fsec ,& is2digits );
23182322if (dterr )
@@ -2444,7 +2448,7 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec)
24442448 * Return 0 if okay, a DTERR code if not.
24452449 */
24462450static int
2447- DecodeNumber (int flen ,char * str ,int fmask ,
2451+ DecodeNumber (int flen ,char * str ,bool haveTextMonth , int fmask ,
24482452int * tmask ,struct tm * tm ,fsec_t * fsec ,int * is2digits )
24492453{
24502454int val ;
@@ -2534,10 +2538,59 @@ DecodeNumber(int flen, char *str, int fmask,
25342538tm -> tm_mon = val ;
25352539break ;
25362540
2541+ case (DTK_M (MONTH )):
2542+ if (haveTextMonth )
2543+ {
2544+ /*
2545+ * We are at the first numeric field of a date that included
2546+ * a textual month name. We want to support the variants
2547+ * MON-DD-YYYY, DD-MON-YYYY, and YYYY-MON-DD as unambiguous
2548+ * inputs. We will also accept MON-DD-YY or DD-MON-YY in
2549+ * either DMY or MDY modes, as well as YY-MON-DD in YMD mode.
2550+ */
2551+ if (flen >=3 || DateOrder == DATEORDER_YMD )
2552+ {
2553+ * tmask = DTK_M (YEAR );
2554+ tm -> tm_year = val ;
2555+ }
2556+ else
2557+ {
2558+ * tmask = DTK_M (DAY );
2559+ tm -> tm_mday = val ;
2560+ }
2561+ }
2562+ else
2563+ {
2564+ /* Must be at second field of MM-DD-YY */
2565+ * tmask = DTK_M (DAY );
2566+ tm -> tm_mday = val ;
2567+ }
2568+ break ;
2569+
25372570case (DTK_M (YEAR ) |DTK_M (MONTH )):
2538- /* Must be at third field of YY-MM-DD */
2539- * tmask = DTK_M (DAY );
2540- tm -> tm_mday = val ;
2571+ if (haveTextMonth )
2572+ {
2573+ /* Need to accept DD-MON-YYYY even in YMD mode */
2574+ if (flen >=3 && * is2digits )
2575+ {
2576+ /* Guess that first numeric field is day was wrong */
2577+ * tmask = DTK_M (DAY );/* YEAR is already set */
2578+ tm -> tm_mday = tm -> tm_year ;
2579+ tm -> tm_year = val ;
2580+ * is2digits = FALSE;
2581+ }
2582+ else
2583+ {
2584+ * tmask = DTK_M (DAY );
2585+ tm -> tm_mday = val ;
2586+ }
2587+ }
2588+ else
2589+ {
2590+ /* Must be at third field of YY-MM-DD */
2591+ * tmask = DTK_M (DAY );
2592+ tm -> tm_mday = val ;
2593+ }
25412594break ;
25422595
25432596case (DTK_M (DAY )):
@@ -2552,12 +2605,6 @@ DecodeNumber(int flen, char *str, int fmask,
25522605tm -> tm_year = val ;
25532606break ;
25542607
2555- case (DTK_M (MONTH )):
2556- /* Must be at second field of MM-DD-YY */
2557- * tmask = DTK_M (DAY );
2558- tm -> tm_mday = val ;
2559- break ;
2560-
25612608case (DTK_M (YEAR ) |DTK_M (MONTH ) |DTK_M (DAY )):
25622609/* we have all the date, so it must be a time field */
25632610dterr = DecodeNumberField (flen ,str ,fmask ,
@@ -2574,10 +2621,10 @@ DecodeNumber(int flen, char *str, int fmask,
25742621
25752622/*
25762623 * When processing a year field, mark it for adjustment if it's
2577- *exactly two digits.
2624+ *only one or two digits.
25782625 */
25792626if (* tmask == DTK_M (YEAR ))
2580- * is2digits = (flen = =2 );
2627+ * is2digits = (flen < =2 );
25812628
25822629return 0 ;
25832630}