diff options
Diffstat (limited to 'sql/time.cc')
-rw-r--r-- | sql/time.cc | 140 |
1 files changed, 102 insertions, 38 deletions
diff --git a/sql/time.cc b/sql/time.cc index 321a8ba16e5..b6ca306e523 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -291,13 +291,29 @@ ulong convert_month_to_period(ulong month) } -/***************************************************************************** -** convert a timestamp string to a TIME value. -** At least the following formats are recogniced (based on number of digits) -** YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS -** YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS -** Returns the type of string -*****************************************************************************/ +/* + Convert a timestamp string to a TIME value. + + SYNOPSIS + str_to_TIME() + str String to parse + length Length of string + l_time Date is stored here + fuzzy_date 1 if we should allow dates where one part is zero + + DESCRIPTION + At least the following formats are recogniced (based on number of digits) + YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS + YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS + YYYYMMDDTHHMMSS where T is a the character T (ISO8601) + Also dates where all parts are zero are allowed + + RETURN VALUES + TIMESTAMP_NONE String wasn't a timestamp, like + [DD [HH:[MM:[SS]]]].fraction + TIMESTAMP_DATE DATE string (YY MM and DD parts ok) + TIMESTAMP_FULL Full timestamp +*/ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) @@ -306,53 +322,66 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) uint not_zero_date; const char *pos; const char *end=str+length; + bool found_delimitier= 0; DBUG_ENTER("str_to_TIME"); DBUG_PRINT("enter",("str: %.*s",length,str)); - for (; str != end && !isdigit(*str) ; str++) ; // Skip garbage + // Skip garbage + for (; str != end && !my_isdigit(&my_charset_latin1, *str) ; str++) ; if (str == end) DBUG_RETURN(TIMESTAMP_NONE); /* - ** calculate first number of digits. - ** If length= 8 or >= 14 then year is of format YYYY. - (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS) + Calculate first number of digits. + If length= 8 or >= 14 then year is of format YYYY. + (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS) */ - for (pos=str; pos != end && isdigit(*pos) ; pos++) ; + for (pos=str; pos != end && my_isdigit(&my_charset_latin1,*pos) ; pos++) ; digits= (uint) (pos-str); year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; field_length=year_length-1; not_zero_date= 0; - for (i=0 ; i < 6 && str != end && isdigit(*str) ; i++) + for (i=0 ; i < 6 && str != end && my_isdigit(&my_charset_latin1,*str) ; i++) { uint tmp_value=(uint) (uchar) (*str++ - '0'); - while (str != end && isdigit(str[0]) && field_length--) + while (str != end && my_isdigit(&my_charset_latin1,str[0]) && + field_length--) { tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0'); str++; } + if (found_delimitier && (int) field_length < 0) + { + /* The number can't match any valid date or datetime string */ + DBUG_RETURN(TIMESTAMP_NONE); + } date[i]=tmp_value; not_zero_date|= tmp_value; if (i == 2 && str != end && *str == 'T') str++; // ISO8601: CCYYMMDDThhmmss else if ( i != 5 ) // Skip inter-field delimiters { - while (str != end && (ispunct(*str) || isspace(*str))) + while (str != end && + (my_ispunct(&my_charset_latin1,*str) || + my_isspace(&my_charset_latin1,*str))) { // Only allow space between days and hours - if (isspace(*str) && i != 2) + if (my_isspace(&my_charset_latin1,*str) && i != 2) DBUG_RETURN(TIMESTAMP_NONE); str++; + found_delimitier=1; // Should be a 'normal' date } } field_length=1; // Rest fields can only be 2 } /* Handle second fractions */ - if (i == 6 && (uint) (end-str) >= 2 && *str == '.' && isdigit(str[1])) + if (i == 6 && (uint) (end-str) >= 2 && *str == '.' && + my_isdigit(&my_charset_latin1,str[1])) { str++; uint tmp_value=(uint) (uchar) (*str - '0'); - field_length=3; - while (str++ != end && isdigit(str[0]) && field_length--) + field_length=5; + while (str++ != end && my_isdigit(&my_charset_latin1,str[0]) && + field_length--) tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0'); date[6]=tmp_value; not_zero_date|= tmp_value; @@ -374,7 +403,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) { for (; str != end ; str++) { - if (!isspace(*str)) + if (!my_isspace(&my_charset_latin1, *str)) { not_zero_date= 1; // Give warning break; @@ -389,7 +418,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) { for (; str != end ; str++) { - if (!isspace(*str)) + if (!my_isspace(&my_charset_latin1,*str)) { current_thd->cuted_fields++; break; @@ -437,12 +466,22 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date) } -/***************************************************************************** -** convert a time string to a (ulong) value. -** Can use all full timestamp formats and -** [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, [M]MSS or [S]S -** There may be an optional [.second_part] after seconds -*****************************************************************************/ +/* + Convert a time string to a TIME struct. + + SYNOPSIS + str_to_time() + str A string in full TIMESTAMP format or + [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, + [M]MSS or [S]S + There may be an optional [.second_part] after seconds + length Length of str + l_time Store result here + + RETURN + 0 ok + 1 error +*/ bool str_to_time(const char *str,uint length,TIME *l_time) { @@ -452,7 +491,8 @@ bool str_to_time(const char *str,uint length,TIME *l_time) uint state; l_time->neg=0; - for (; str != end && !isdigit(*str) && *str != '-' ; str++) + for (; str != end && + !my_isdigit(&my_charset_latin1,*str) && *str != '-' ; str++) length--; if (str != end && *str == '-') { @@ -471,25 +511,29 @@ bool str_to_time(const char *str,uint length,TIME *l_time) } /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ - for (value=0; str != end && isdigit(*str) ; str++) + for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); - if (*str == ' ') + /* Move to last space */ + if (str != end && *str == ' ') { - while (++str != end && str[0] == ' ') ; + while (++str != end && str[0] == ' ') + {} str--; } LINT_INIT(state); found_days=found_hours=0; - if ((uint) (end-str) > 1 && (*str == ' ' && isdigit(str[1]))) + if ((uint) (end-str) > 1 && (*str == ' ' && + my_isdigit(&my_charset_latin1,str[1]))) { // days ! date[0]=value; state=1; // Assume next is hours found_days=1; str++; // Skip space; } - else if ((end-str) > 1 && *str == ':' && isdigit(str[1])) + else if ((end-str) > 1 && *str == ':' && + my_isdigit(&my_charset_latin1,str[1])) { date[0]=0; // Assume we found hours date[1]=value; @@ -511,10 +555,11 @@ bool str_to_time(const char *str,uint length,TIME *l_time) /* Read hours, minutes and seconds */ for (;;) { - for (value=0; str != end && isdigit(*str) ; str++) + for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) value=value*10L + (long) (*str - '0'); date[state++]=value; - if (state == 4 || (end-str) < 2 || *str != ':' || !isdigit(str[1])) + if (state == 4 || (end-str) < 2 || *str != ':' || + !my_isdigit(&my_charset_latin1,str[1])) break; str++; // Skip ':' } @@ -534,11 +579,13 @@ bool str_to_time(const char *str,uint length,TIME *l_time) fractional: /* Get fractional second part */ - if ((end-str) >= 2 && *str == '.' && isdigit(str[1])) + if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1])) { uint field_length=3; str++; value=(uint) (uchar) (*str - '0'); - while (++str != end && isdigit(str[0]) && field_length--) + while (++str != end && + my_isdigit(&my_charset_latin1,str[0]) && + field_length--) value=value*10 + (uint) (uchar) (*str - '0'); date[4]=value; } @@ -563,7 +610,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time) { do { - if (!isspace(*str)) + if (!my_isspace(&my_charset_latin1,*str)) { current_thd->cuted_fields++; break; @@ -572,3 +619,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time) } return 0; } + + +/* + Convert a system time structure to TIME +*/ + +void localtime_to_TIME(TIME *to, struct tm *from) +{ + to->neg=0; + to->second_part=0; + to->year= (int) ((from->tm_year+1900) % 10000); + to->month= (int) from->tm_mon+1; + to->day= (int) from->tm_mday; + to->hour= (int) from->tm_hour; + to->minute= (int) from->tm_min; + to->second= (int) from->tm_sec; +} |