summaryrefslogtreecommitdiff
path: root/sql/time.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/time.cc')
-rw-r--r--sql/time.cc140
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;
+}