8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
25
25
#include "utils/guc.h"
26
26
27
27
28
- static int DecodeNumber (int flen , char * field ,
28
+ static int DecodeNumber (int flen , char * field , bool haveTextMonth ,
29
29
int fmask , int * tmask ,
30
30
struct tm * tm , fsec_t * fsec , int * is2digits );
31
31
static int DecodeNumberField (int len , char * str ,
@@ -924,7 +924,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
924
924
int val ;
925
925
int dterr ;
926
926
int mer = HR24 ;
927
- int haveTextMonth = FALSE;
927
+ bool haveTextMonth = FALSE;
928
928
int is2digits = FALSE;
929
929
int bc = FALSE;
930
930
@@ -1281,7 +1281,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
1281
1281
/* otherwise it is a single date/time field... */
1282
1282
else
1283
1283
{
1284
- dterr = DecodeNumber (flen , field [i ], fmask ,
1284
+ dterr = DecodeNumber (flen , field [i ],
1285
+ haveTextMonth , fmask ,
1285
1286
& tmask , tm ,
1286
1287
fsec , & is2digits );
1287
1288
if (dterr )
@@ -2032,6 +2033,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
2032
2033
else
2033
2034
{
2034
2035
dterr = DecodeNumber (flen , field [i ],
2036
+ FALSE,
2035
2037
(fmask | DTK_DATE_M ),
2036
2038
& tmask , tm ,
2037
2039
fsec , & is2digits );
@@ -2229,6 +2231,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
2229
2231
int i ,
2230
2232
len ;
2231
2233
int dterr ;
2234
+ bool haveTextMonth = FALSE;
2232
2235
int bc = FALSE;
2233
2236
int is2digits = FALSE;
2234
2237
int type ,
@@ -2283,6 +2286,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
2283
2286
{
2284
2287
case MONTH :
2285
2288
tm -> tm_mon = val ;
2289
+ haveTextMonth = TRUE;
2286
2290
break ;
2287
2291
2288
2292
case ADBC :
@@ -2312,7 +2316,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
2312
2316
if ((len = strlen (field [i ])) <= 0 )
2313
2317
return DTERR_BAD_FORMAT ;
2314
2318
2315
- dterr = DecodeNumber (len , field [i ], fmask ,
2319
+ dterr = DecodeNumber (len , field [i ], haveTextMonth , fmask ,
2316
2320
& dmask , tm ,
2317
2321
& fsec , & is2digits );
2318
2322
if (dterr )
@@ -2444,7 +2448,7 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec)
2444
2448
* Return 0 if okay, a DTERR code if not.
2445
2449
*/
2446
2450
static int
2447
- DecodeNumber (int flen , char * str , int fmask ,
2451
+ DecodeNumber (int flen , char * str , bool haveTextMonth , int fmask ,
2448
2452
int * tmask , struct tm * tm , fsec_t * fsec , int * is2digits )
2449
2453
{
2450
2454
int val ;
@@ -2534,10 +2538,59 @@ DecodeNumber(int flen, char *str, int fmask,
2534
2538
tm -> tm_mon = val ;
2535
2539
break ;
2536
2540
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
+
2537
2570
case (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
+ }
2541
2594
break ;
2542
2595
2543
2596
case (DTK_M (DAY )):
@@ -2552,12 +2605,6 @@ DecodeNumber(int flen, char *str, int fmask,
2552
2605
tm -> tm_year = val ;
2553
2606
break ;
2554
2607
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
-
2561
2608
case (DTK_M (YEAR ) | DTK_M (MONTH ) | DTK_M (DAY )):
2562
2609
/* we have all the date, so it must be a time field */
2563
2610
dterr = DecodeNumberField (flen , str , fmask ,
@@ -2574,10 +2621,10 @@ DecodeNumber(int flen, char *str, int fmask,
2574
2621
2575
2622
/*
2576
2623
* When processing a year field, mark it for adjustment if it's
2577
- * exactly two digits.
2624
+ * only one or two digits.
2578
2625
*/
2579
2626
if (* tmask == DTK_M (YEAR ))
2580
- * is2digits = (flen = = 2 );
2627
+ * is2digits = (flen < = 2 );
2581
2628
2582
2629
return 0 ;
2583
2630
}
0 commit comments