1
1
/* -----------------------------------------------------------------------
2
2
* formatting.c
3
3
*
4
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.23 2000/10/29 13:17:34 petere Exp $
4
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.24 2000/11/25 05:00:29 momjian Exp $
5
5
*
6
6
*
7
7
* Portions Copyright (c) 1999-2000, PostgreSQL, Inc
@@ -127,6 +127,7 @@ typedef struct
127
127
int len , /* keyword length */
128
128
(* action ) (),
129
129
id ; /* keyword id */
130
+ bool isdigit ; /* is expected output/input digit */
130
131
} KeyWord ;
131
132
132
133
typedef struct
@@ -344,14 +345,16 @@ static int NUMCounter = 0;
344
345
* ----------
345
346
*/
346
347
typedef struct {
347
- int hh , am , pm , mi , ss , ssss , d , dd , ddd , mm , yyyy , bc , iw , ww , w , cc , q , j ;
348
+ int hh , am , pm , mi , ss , ssss , d , dd , ddd , mm , yyyy , yyy , yy , y ,
349
+ bc , iw , ww , w , cc , q , j ;
348
350
} TmFromChar ;
349
351
350
352
#define ZERO_tmfc ( _X ) \
351
353
do { \
352
354
(_X)->hh= (_X)->am= (_X)->pm= (_X)->mi= (_X)->ss= (_X)->ssss= \
353
- (_X)->d= (_X)->dd= (_X)->ddd= (_X)->mm= (_X)->yyyy= (_X)->bc= \
354
- (_X)->iw= (_X)->ww= (_X)->w= (_X)->cc= (_X)->q= (_X)->j= 0; \
355
+ (_X)->d= (_X)->dd= (_X)->ddd= (_X)->mm= (_X)->yyyy= (_X)->yyy= \
356
+ (_X)->yy= (_X)->y= (_X)->bc= (_X)->iw= (_X)->ww= (_X)->w= \
357
+ (_X)->cc= (_X)->q= (_X)->j= 0; \
355
358
} while(0)
356
359
357
360
#ifdef DEBUG_TO_FROM_CHAR
@@ -453,7 +456,7 @@ static KeySuffix DCH_suff[] = {
453
456
* it is not good.
454
457
*
455
458
* (!)
456
- * Position for the keyword is simular as position in the enum DCH/NUM_poz
459
+ * - Position for the keyword is simular as position in the enum DCH/NUM_poz.
457
460
* (!)
458
461
*
459
462
* For fast search is used the 'int index[]', index is ascii table from position
@@ -598,88 +601,88 @@ typedef enum
598
601
* ----------
599
602
*/
600
603
static KeyWord DCH_keywords [] = {
601
- /* keyword,len,func. type is in Index */
602
- {"A.D." , 4 , dch_date , DCH_A_D }, /* A */
603
- {"A.M." , 4 , dch_time , DCH_A_M },
604
- {"AD" , 2 , dch_date , DCH_AD },
605
- {"AM" , 2 , dch_time , DCH_AM },
606
- {"B.C." , 4 , dch_date , DCH_B_C }, /* B */
607
- {"BC" , 2 , dch_date , DCH_BC },
608
- {"CC" , 2 , dch_date , DCH_CC }, /* C */
609
- {"DAY" , 3 , dch_date , DCH_DAY }, /* D */
610
- {"DDD" , 3 , dch_date , DCH_DDD },
611
- {"DD" , 2 , dch_date , DCH_DD },
612
- {"DY" , 2 , dch_date , DCH_DY },
613
- {"Day" , 3 , dch_date , DCH_Day },
614
- {"Dy" , 2 , dch_date , DCH_Dy },
615
- {"D" , 1 , dch_date , DCH_D },
616
- {"FX" , 2 , dch_global , DCH_FX }, /* F */
617
- {"HH24" , 4 , dch_time , DCH_HH24 }, /* H */
618
- {"HH12" , 4 , dch_time , DCH_HH12 },
619
- {"HH" , 2 , dch_time , DCH_HH },
620
- {"IW" , 2 , dch_date , DCH_IW }, /* I */
621
- {"J" , 1 , dch_date , DCH_J }, /* J */
622
- {"MI" , 2 , dch_time , DCH_MI },
623
- {"MM" , 2 , dch_date , DCH_MM },
624
- {"MONTH" , 5 , dch_date , DCH_MONTH },
625
- {"MON" , 3 , dch_date , DCH_MON },
626
- {"Month" , 5 , dch_date , DCH_Month },
627
- {"Mon" , 3 , dch_date , DCH_Mon },
628
- {"P.M." , 4 , dch_time , DCH_P_M }, /* P */
629
- {"PM" , 2 , dch_time , DCH_PM },
630
- {"Q" , 1 , dch_date , DCH_Q }, /* Q */
631
- {"RM" , 2 , dch_date , DCH_RM }, /* R */
632
- {"SSSS" , 4 , dch_time , DCH_SSSS }, /* S */
633
- {"SS" , 2 , dch_time , DCH_SS },
634
- {"TZ" , 2 , dch_time , DCH_TZ }, /* T */
635
- {"WW" , 2 , dch_date , DCH_WW }, /* W */
636
- {"W" , 1 , dch_date , DCH_W },
637
- {"Y,YYY" , 5 , dch_date , DCH_Y_YYY }, /* Y */
638
- {"YYYY" , 4 , dch_date , DCH_YYYY },
639
- {"YYY" , 3 , dch_date , DCH_YYY },
640
- {"YY" , 2 , dch_date , DCH_YY },
641
- {"Y" , 1 , dch_date , DCH_Y },
642
- {"a.d." , 4 , dch_date , DCH_a_d }, /* a */
643
- {"a.m." , 4 , dch_time , DCH_a_m },
644
- {"ad" , 2 , dch_date , DCH_ad },
645
- {"am" , 2 , dch_time , DCH_am },
646
- {"b.c." , 4 , dch_date , DCH_b_c }, /* b */
647
- {"bc" , 2 , dch_date , DCH_bc },
648
- {"cc" , 2 , dch_date , DCH_CC }, /* c */
649
- {"day" , 3 , dch_date , DCH_day }, /* d */
650
- {"ddd" , 3 , dch_date , DCH_DDD },
651
- {"dd" , 2 , dch_date , DCH_DD },
652
- {"dy" , 2 , dch_date , DCH_dy },
653
- {"d" , 1 , dch_date , DCH_D },
654
- {"fx" , 2 , dch_global , DCH_FX }, /* f */
655
- {"hh24" , 4 , dch_time , DCH_HH24 }, /* h */
656
- {"hh12" , 4 , dch_time , DCH_HH12 },
657
- {"hh" , 2 , dch_time , DCH_HH },
658
- {"iw" , 2 , dch_date , DCH_IW }, /* i */
659
- {"j" , 1 , dch_time , DCH_J }, /* j */
660
- {"mi" , 2 , dch_time , DCH_MI }, /* m */
661
- {"mm" , 2 , dch_date , DCH_MM },
662
- {"month" , 5 , dch_date , DCH_month },
663
- {"mon" , 3 , dch_date , DCH_mon },
664
- {"p.m." , 4 , dch_time , DCH_p_m }, /* p */
665
- {"pm" , 2 , dch_time , DCH_pm },
666
- {"q" , 1 , dch_date , DCH_Q }, /* q */
667
- {"rm" , 2 , dch_date , DCH_rm }, /* r */
668
- {"ssss" , 4 , dch_time , DCH_SSSS }, /* s */
669
- {"ss" , 2 , dch_time , DCH_SS },
670
- {"tz" , 2 , dch_time , DCH_tz }, /* t */
671
- {"ww" , 2 , dch_date , DCH_WW }, /* w */
672
- {"w" , 1 , dch_date , DCH_W },
673
- {"y,yyy" , 5 , dch_date , DCH_Y_YYY }, /* y */
674
- {"yyyy" , 4 , dch_date , DCH_YYYY },
675
- {"yyy" , 3 , dch_date , DCH_YYY },
676
- {"yy" , 2 , dch_date , DCH_YY },
677
- {"y" , 1 , dch_date , DCH_Y },
604
+ /* keyword, len, func, type, isdigit is in Index */
605
+ {"A.D." , 4 , dch_date , DCH_A_D , FALSE }, /* A */
606
+ {"A.M." , 4 , dch_time , DCH_A_M , FALSE },
607
+ {"AD" , 2 , dch_date , DCH_AD , FALSE },
608
+ {"AM" , 2 , dch_time , DCH_AM , FALSE },
609
+ {"B.C." , 4 , dch_date , DCH_B_C , FALSE }, /* B */
610
+ {"BC" , 2 , dch_date , DCH_BC , FALSE },
611
+ {"CC" , 2 , dch_date , DCH_CC , TRUE }, /* C */
612
+ {"DAY" , 3 , dch_date , DCH_DAY , FALSE }, /* D */
613
+ {"DDD" , 3 , dch_date , DCH_DDD , TRUE },
614
+ {"DD" , 2 , dch_date , DCH_DD , TRUE },
615
+ {"DY" , 2 , dch_date , DCH_DY , FALSE },
616
+ {"Day" , 3 , dch_date , DCH_Day , FALSE },
617
+ {"Dy" , 2 , dch_date , DCH_Dy , FALSE },
618
+ {"D" , 1 , dch_date , DCH_D , TRUE },
619
+ {"FX" , 2 , dch_global , DCH_FX , FALSE }, /* F */
620
+ {"HH24" , 4 , dch_time , DCH_HH24 , TRUE}, /* H */
621
+ {"HH12" , 4 , dch_time , DCH_HH12 , TRUE },
622
+ {"HH" , 2 , dch_time , DCH_HH , TRUE },
623
+ {"IW" , 2 , dch_date , DCH_IW , TRUE }, /* I */
624
+ {"J" , 1 , dch_date , DCH_J , TRUE }, /* J */
625
+ {"MI" , 2 , dch_time , DCH_MI , TRUE },
626
+ {"MM" , 2 , dch_date , DCH_MM , TRUE },
627
+ {"MONTH" , 5 , dch_date , DCH_MONTH , FALSE },
628
+ {"MON" , 3 , dch_date , DCH_MON , FALSE },
629
+ {"Month" , 5 , dch_date , DCH_Month , FALSE },
630
+ {"Mon" , 3 , dch_date , DCH_Mon , FALSE },
631
+ {"P.M." , 4 , dch_time , DCH_P_M , FALSE }, /* P */
632
+ {"PM" , 2 , dch_time , DCH_PM , FALSE },
633
+ {"Q" , 1 , dch_date , DCH_Q , TRUE }, /* Q */
634
+ {"RM" , 2 , dch_date , DCH_RM , FALSE }, /* R */
635
+ {"SSSS" , 4 , dch_time , DCH_SSSS , TRUE }, /* S */
636
+ {"SS" , 2 , dch_time , DCH_SS , TRUE },
637
+ {"TZ" , 2 , dch_time , DCH_TZ , FALSE }, /* T */
638
+ {"WW" , 2 , dch_date , DCH_WW , TRUE }, /* W */
639
+ {"W" , 1 , dch_date , DCH_W , TRUE },
640
+ {"Y,YYY" , 5 , dch_date , DCH_Y_YYY , TRUE }, /* Y */
641
+ {"YYYY" , 4 , dch_date , DCH_YYYY , TRUE },
642
+ {"YYY" , 3 , dch_date , DCH_YYY , TRUE },
643
+ {"YY" , 2 , dch_date , DCH_YY , TRUE },
644
+ {"Y" , 1 , dch_date , DCH_Y , TRUE },
645
+ {"a.d." , 4 , dch_date , DCH_a_d , FALSE }, /* a */
646
+ {"a.m." , 4 , dch_time , DCH_a_m , FALSE },
647
+ {"ad" , 2 , dch_date , DCH_ad , FALSE },
648
+ {"am" , 2 , dch_time , DCH_am , FALSE },
649
+ {"b.c." , 4 , dch_date , DCH_b_c , FALSE }, /* b */
650
+ {"bc" , 2 , dch_date , DCH_bc , FALSE },
651
+ {"cc" , 2 , dch_date , DCH_CC , TRUE }, /* c */
652
+ {"day" , 3 , dch_date , DCH_day , FALSE }, /* d */
653
+ {"ddd" , 3 , dch_date , DCH_DDD , TRUE },
654
+ {"dd" , 2 , dch_date , DCH_DD , TRUE },
655
+ {"dy" , 2 , dch_date , DCH_dy , FALSE },
656
+ {"d" , 1 , dch_date , DCH_D , TRUE },
657
+ {"fx" , 2 , dch_global , DCH_FX , FALSE }, /* f */
658
+ {"hh24" , 4 , dch_time , DCH_HH24 , TRUE}, /* h */
659
+ {"hh12" , 4 , dch_time , DCH_HH12 , TRUE },
660
+ {"hh" , 2 , dch_time , DCH_HH , TRUE },
661
+ {"iw" , 2 , dch_date , DCH_IW , TRUE }, /* i */
662
+ {"j" , 1 , dch_time , DCH_J , TRUE }, /* j */
663
+ {"mi" , 2 , dch_time , DCH_MI , TRUE }, /* m */
664
+ {"mm" , 2 , dch_date , DCH_MM , TRUE },
665
+ {"month" , 5 , dch_date , DCH_month , FALSE },
666
+ {"mon" , 3 , dch_date , DCH_mon , FALSE },
667
+ {"p.m." , 4 , dch_time , DCH_p_m , FALSE }, /* p */
668
+ {"pm" , 2 , dch_time , DCH_pm , FALSE },
669
+ {"q" , 1 , dch_date , DCH_Q , TRUE }, /* q */
670
+ {"rm" , 2 , dch_date , DCH_rm , FALSE }, /* r */
671
+ {"ssss" , 4 , dch_time , DCH_SSSS , TRUE }, /* s */
672
+ {"ss" , 2 , dch_time , DCH_SS , TRUE },
673
+ {"tz" , 2 , dch_time , DCH_tz , FALSE }, /* t */
674
+ {"ww" , 2 , dch_date , DCH_WW , TRUE }, /* w */
675
+ {"w" , 1 , dch_date , DCH_W , TRUE },
676
+ {"y,yyy" , 5 , dch_date , DCH_Y_YYY , TRUE }, /* y */
677
+ {"yyyy" , 4 , dch_date , DCH_YYYY , TRUE },
678
+ {"yyy" , 3 , dch_date , DCH_YYY , TRUE },
679
+ {"yy" , 2 , dch_date , DCH_YY , TRUE },
680
+ {"y" , 1 , dch_date , DCH_Y , TRUE },
678
681
/* last */
679
682
{NULL , 0 , NULL , 0 }};
680
683
681
684
/* ----------
682
- * KeyWords for NUMBER version
685
+ * KeyWords for NUMBER version (now, isdigit info is not needful here..)
683
686
* ----------
684
687
*/
685
688
static KeyWord NUM_keywords [] = {
@@ -1230,7 +1233,7 @@ DCH_processor(FormatNode *node, char *inout, int flag)
1230
1233
* Skip blank space in FROM_CHAR's input
1231
1234
* ----------
1232
1235
*/
1233
- if (isspace (n -> character ) && IS_FX == 0 )
1236
+ if (isspace (n -> character ) && IS_FX == 0 )
1234
1237
{
1235
1238
while (* s != '\0' && isspace ((int ) * (s + 1 )))
1236
1239
++ s ;
@@ -1526,6 +1529,40 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node)
1526
1529
return -1 ;
1527
1530
}
1528
1531
1532
+ /* ----------
1533
+ * Return TRUE if next format picture is not digit value
1534
+ * ----------
1535
+ */
1536
+ static bool
1537
+ is_next_separator (FormatNode * n )
1538
+ {
1539
+ if (n -> type == NODE_TYPE_END )
1540
+ return FALSE;
1541
+
1542
+ if (n -> type == NODE_TYPE_ACTION && S_THth (n -> suffix ))
1543
+ return TRUE;
1544
+
1545
+ /*
1546
+ * Next node
1547
+ */
1548
+ n ++ ;
1549
+
1550
+ if (n -> type == NODE_TYPE_END )
1551
+ return FALSE;
1552
+
1553
+ if (n -> type == NODE_TYPE_ACTION )
1554
+ {
1555
+ if (n -> key -> isdigit )
1556
+ return FALSE;
1557
+
1558
+ return TRUE;
1559
+ }
1560
+ else if (isdigit (n -> character ))
1561
+ return FALSE;
1562
+
1563
+ return TRUE; /* some non-digit input (separator) */
1564
+ }
1565
+
1529
1566
#define AMPM_ERROR elog(ERROR, "to_timestamp(): bad AM/PM string")
1530
1567
1531
1568
/* ----------
@@ -1736,7 +1773,10 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
1736
1773
}
1737
1774
else if (flag == FROM_CHAR )
1738
1775
{
1739
- sscanf (inout , "%d" , & tmfc -> ssss );
1776
+ if (is_next_separator (node ))
1777
+ sscanf (inout , "%d" , & tmfc -> ssss );
1778
+ else
1779
+ sscanf (inout , "%05d" , & tmfc -> ssss );
1740
1780
return int4len ((int4 ) tmfc -> ssss ) - 1 + SKIP_THth (suf );
1741
1781
}
1742
1782
break ;
@@ -2192,7 +2232,11 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
2192
2232
}
2193
2233
else if (flag == FROM_CHAR )
2194
2234
{
2195
- sscanf (inout , "%d" , & tmfc -> yyyy );
2235
+ if (is_next_separator (node ))
2236
+ sscanf (inout , "%d" , & tmfc -> yyyy );
2237
+ else
2238
+ sscanf (inout , "%04d" , & tmfc -> yyyy );
2239
+
2196
2240
if (!S_FM (suf ) && tmfc -> yyyy <= 9999 && tmfc -> yyyy >= -9999 )
2197
2241
len = 4 ;
2198
2242
else
@@ -2217,7 +2261,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
2217
2261
}
2218
2262
else if (flag == FROM_CHAR )
2219
2263
{
2220
- sscanf (inout , "%03d" , & tmfc -> yyyy );
2264
+ sscanf (inout , "%03d" , & tmfc -> yyy );
2221
2265
return 2 + SKIP_THth (suf );
2222
2266
}
2223
2267
break ;
@@ -2237,7 +2281,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
2237
2281
}
2238
2282
else if (flag == FROM_CHAR )
2239
2283
{
2240
- sscanf (inout , "%02d" , & tmfc -> yyyy );
2284
+ sscanf (inout , "%02d" , & tmfc -> yy );
2241
2285
return 1 + SKIP_THth (suf );
2242
2286
}
2243
2287
break ;
@@ -2257,7 +2301,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
2257
2301
}
2258
2302
else if (flag == FROM_CHAR )
2259
2303
{
2260
- sscanf (inout , "%1d" , & tmfc -> yyyy );
2304
+ sscanf (inout , "%1d" , & tmfc -> y );
2261
2305
return 0 + SKIP_THth (suf );
2262
2306
}
2263
2307
break ;
@@ -2725,15 +2769,55 @@ to_timestamp(PG_FUNCTION_ARGS)
2725
2769
2726
2770
if (tmfc -> yyyy )
2727
2771
tm -> tm_year = tmfc -> yyyy ;
2772
+
2773
+ else if (tmfc -> y )
2774
+ {
2775
+ /*
2776
+ * 1-digit year:
2777
+ * always +2000
2778
+ */
2779
+ tm -> tm_year = tmfc -> y + 2000 ;
2780
+ }
2781
+ else if (tmfc -> yy )
2782
+ {
2783
+ /*
2784
+ * 2-digit year:
2785
+ * '00' ... '69' = 2000 ... 2069
2786
+ * '70' ... '99' = 1970 ... 1999
2787
+ */
2788
+ tm -> tm_year = tmfc -> yy ;
2728
2789
2729
- if (tmfc -> j )
2730
- j2date (tmfc -> j , & tm -> tm_year , & tm -> tm_mon , & tm -> tm_mday );
2790
+ if (tm -> tm_year < 70 )
2791
+ tm -> tm_year += 2000 ;
2792
+ else
2793
+ tm -> tm_year += 1900 ;
2794
+ }
2795
+ else if (tmfc -> yyy )
2796
+ {
2797
+ /*
2798
+ * 3-digit year:
2799
+ * '100' ... '999' = 1100 ... 1999
2800
+ * '000' ... '099' = 2000 ... 2099
2801
+ */
2802
+ tm -> tm_year = tmfc -> yyy ;
2731
2803
2732
- if (tmfc -> bc && tm -> tm_year > 0 )
2733
- tm -> tm_year = - (tm -> tm_year );
2804
+ if (tm -> tm_year >= 100 )
2805
+ tm -> tm_year += 1000 ;
2806
+ else
2807
+ tm -> tm_year += 2000 ;
2808
+ }
2809
+
2810
+
2811
+ if (tmfc -> bc )
2812
+ {
2813
+ if (tm -> tm_year > 0 )
2814
+ tm -> tm_year = - (tm -> tm_year - 1 );
2815
+ else
2816
+ elog (ERROR , "Inconsistant use of year %04d and 'BC'" , tm -> tm_year );
2817
+ }
2734
2818
2735
- if (tm -> tm_year < 0 )
2736
- tm -> tm_year = tm -> tm_year + 1 ;
2819
+ if (tmfc -> j )
2820
+ j2date ( tmfc -> j , & tm -> tm_year , & tm -> tm_mon , & tm -> tm_mday ) ;
2737
2821
2738
2822
if (tmfc -> iw )
2739
2823
isoweek2date (tmfc -> iw , & tm -> tm_year , & tm -> tm_mon , & tm -> tm_mday );
0 commit comments