8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.111 2003/08/05 17:39:19 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.112 2003/08/05 18:30:21 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -699,30 +699,54 @@ TrimTrailingZeros(char *str)
699
699
700
700
701
701
/* ParseDateTime()
702
- * Break string into tokens based on a date/time context.
702
+ * Break string into tokens based on a date/time context.
703
+ * Returns 0 if successful, -1 if bogus input detected.
704
+ *
705
+ * timestr - the input string
706
+ * lowstr - workspace for field string storage (must be large enough for
707
+ * a copy of the input string, including trailing null)
708
+ * field[] - pointers to field strings are returned in this array
709
+ * ftype[] - field type indicators are returned in this array
710
+ * maxfields - dimensions of the above two arrays
711
+ * *numfields - set to the actual number of fields detected
712
+ *
713
+ * The fields extracted from the input are stored as separate, null-terminated
714
+ * strings in the workspace at lowstr. Any text is converted to lower case.
715
+ *
703
716
* Several field types are assigned:
704
717
* DTK_NUMBER - digits and (possibly) a decimal point
705
718
* DTK_DATE - digits and two delimiters, or digits and text
706
719
* DTK_TIME - digits, colon delimiters, and possibly a decimal point
707
720
* DTK_STRING - text (no digits)
708
721
* DTK_SPECIAL - leading "+" or "-" followed by text
709
722
* DTK_TZ - leading "+" or "-" followed by digits
723
+ *
710
724
* Note that some field types can hold unexpected items:
711
725
* DTK_NUMBER can hold date fields (yy.ddd)
712
726
* DTK_STRING can hold months (January) and time zones (PST)
713
727
* DTK_DATE can hold Posix time zones (GMT-8)
714
728
*/
715
729
int
716
- ParseDateTime (char * timestr , char * lowstr ,
730
+ ParseDateTime (const char * timestr , char * lowstr ,
717
731
char * * field , int * ftype , int maxfields , int * numfields )
718
732
{
719
733
int nf = 0 ;
720
- char * cp = timestr ;
734
+ const char * cp = timestr ;
721
735
char * lp = lowstr ;
722
736
723
737
/* outer loop through fields */
724
738
while (* cp != '\0' )
725
739
{
740
+ /* Ignore spaces between fields */
741
+ if (isspace ((unsigned char ) * cp ))
742
+ {
743
+ cp ++ ;
744
+ continue ;
745
+ }
746
+
747
+ /* Record start of current field */
748
+ if (nf >= maxfields )
749
+ return -1 ;
726
750
field [nf ] = lp ;
727
751
728
752
/* leading digit? then date or time */
@@ -745,32 +769,32 @@ ParseDateTime(char *timestr, char *lowstr,
745
769
else if ((* cp == '-' ) || (* cp == '/' ) || (* cp == '.' ))
746
770
{
747
771
/* save delimiting character to use later */
748
- char * dp = cp ;
772
+ char delim = * cp ;
749
773
750
774
* lp ++ = * cp ++ ;
751
775
/* second field is all digits? then no embedded text month */
752
776
if (isdigit ((unsigned char ) * cp ))
753
777
{
754
- ftype [nf ] = ((* dp == '.' ) ? DTK_NUMBER : DTK_DATE );
778
+ ftype [nf ] = ((delim == '.' ) ? DTK_NUMBER : DTK_DATE );
755
779
while (isdigit ((unsigned char ) * cp ))
756
780
* lp ++ = * cp ++ ;
757
781
758
782
/*
759
783
* insist that the delimiters match to get a
760
784
* three-field date.
761
785
*/
762
- if (* cp == * dp )
786
+ if (* cp == delim )
763
787
{
764
788
ftype [nf ] = DTK_DATE ;
765
789
* lp ++ = * cp ++ ;
766
- while (isdigit ((unsigned char ) * cp ) || (* cp == * dp ))
790
+ while (isdigit ((unsigned char ) * cp ) || (* cp == delim ))
767
791
* lp ++ = * cp ++ ;
768
792
}
769
793
}
770
794
else
771
795
{
772
796
ftype [nf ] = DTK_DATE ;
773
- while (isalnum ((unsigned char ) * cp ) || (* cp == * dp ))
797
+ while (isalnum ((unsigned char ) * cp ) || (* cp == delim ))
774
798
* lp ++ = tolower ((unsigned char ) * cp ++ );
775
799
}
776
800
}
@@ -809,20 +833,14 @@ ParseDateTime(char *timestr, char *lowstr,
809
833
*/
810
834
if ((* cp == '-' ) || (* cp == '/' ) || (* cp == '.' ))
811
835
{
812
- char * dp = cp ;
836
+ char delim = * cp ;
813
837
814
838
ftype [nf ] = DTK_DATE ;
815
839
* lp ++ = * cp ++ ;
816
- while (isdigit ((unsigned char ) * cp ) || (* cp == * dp ))
840
+ while (isdigit ((unsigned char ) * cp ) || (* cp == delim ))
817
841
* lp ++ = * cp ++ ;
818
842
}
819
843
}
820
- /* skip leading spaces */
821
- else if (isspace ((unsigned char ) * cp ))
822
- {
823
- cp ++ ;
824
- continue ;
825
- }
826
844
/* sign? then special or numeric timezone */
827
845
else if ((* cp == '+' ) || (* cp == '-' ))
828
846
{
@@ -851,12 +869,11 @@ ParseDateTime(char *timestr, char *lowstr,
851
869
else
852
870
return -1 ;
853
871
}
854
- /* ignore punctuation but use as delimiter */
872
+ /* ignore other punctuation but use as delimiter */
855
873
else if (ispunct ((unsigned char ) * cp ))
856
874
{
857
875
cp ++ ;
858
876
continue ;
859
-
860
877
}
861
878
/* otherwise, something is not right... */
862
879
else
@@ -865,14 +882,12 @@ ParseDateTime(char *timestr, char *lowstr,
865
882
/* force in a delimiter after each field */
866
883
* lp ++ = '\0' ;
867
884
nf ++ ;
868
- if (nf > MAXDATEFIELDS )
869
- return -1 ;
870
885
}
871
886
872
887
* numfields = nf ;
873
888
874
889
return 0 ;
875
- } /* ParseDateTime() */
890
+ }
876
891
877
892
878
893
/* DecodeDateTime()
0 commit comments