Loading mysql-test/r/date_formats.result +65 −7 Original line number Diff line number Diff line Loading @@ -90,16 +90,23 @@ insert into t1 values ('2003-01-02 11:11:12Pm', '%Y-%m-%d %h:%i:%S%p'), ('10:20:10', '%H:%i:%s'), ('10:20:10', '%h:%i:%s.%f'), ('10:20:10', '%T'), ('10:20:10AM', '%h:%i:%s%p'), ('10:20:10AM', '%r'), ('10:20:10.44AM', '%h:%i:%s.%f%p'), ('15-01-2001 12:59:58', '%d-%m-%Y %H:%i:%S'), ('15 September 2001', '%d %M %Y'), ('15 SEPTEMB 2001', '%d %M %Y'), ('15 MAY 2001', '%d %b %Y'), ('15th May 2001', '%D %b %Y'), ('Sunday 15 MAY 2001', '%W %d %b %Y'), ('Sund 15 MAY 2001', '%W %d %b %Y'), ('Tuesday 00 2002', '%W %U %Y'), ('Thursday 53 1998', '%W %u %Y'), ('Sunday 01 2001', '%W %v %x'), ('Tuesday 52 2001', '%W %V %X'), ('060 2004', '%j %Y'), ('4 53 1998', '%w %u %Y'), ('15-01-2001', '%d-%m-%Y %H:%i:%S'), ('15-01-20', '%d-%m-%y'), ('15-2001-1', '%d-%Y-%c'); Loading @@ -114,16 +121,23 @@ date format str_to_date 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12 10:20:10 %H:%i:%s 0000-00-00 10:20:10 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 10:20:10 %T 0000-00-00 10:20:10 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10 10:20:10AM %r 0000-00-00 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58 15 September 2001 %d %M %Y 2001-09-15 00:00:00 15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00 15 MAY 2001 %d %b %Y 2001-05-15 00:00:00 15th May 2001 %D %b %Y 2001-05-15 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Tuesday 00 2002 %W %U %Y 2002-01-01 00:00:00 Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00 Sunday 01 2001 %W %v %x 2001-01-07 00:00:00 Tuesday 52 2001 %W %V %X 2002-01-01 00:00:00 060 2004 %j %Y 2004-02-29 00:00:00 4 53 1998 %w %u %Y 1998-12-31 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 00:00:00 15-01-20 %d-%m-%y 2020-01-15 00:00:00 15-2001-1 %d-%Y-%c 2001-01-15 00:00:00 Loading @@ -138,16 +152,23 @@ date format con 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12 10:20:10 %H:%i:%s 0000-00-00 10:20:10 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 10:20:10 %T 0000-00-00 10:20:10 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10 10:20:10AM %r 0000-00-00 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58 15 September 2001 %d %M %Y 2001-09-15 00:00:00 15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00 15 MAY 2001 %d %b %Y 2001-05-15 00:00:00 15th May 2001 %D %b %Y 2001-05-15 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Tuesday 00 2002 %W %U %Y 2002-01-01 00:00:00 Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00 Sunday 01 2001 %W %v %x 2001-01-07 00:00:00 Tuesday 52 2001 %W %V %X 2002-01-01 00:00:00 060 2004 %j %Y 2004-02-29 00:00:00 4 53 1998 %w %u %Y 1998-12-31 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 00:00:00 15-01-20 %d-%m-%y 2020-01-15 00:00:00 15-2001-1 %d-%Y-%c 2001-01-15 00:00:00 Loading @@ -162,16 +183,23 @@ date format datetime 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12 10:20:10 %H:%i:%s 0000-00-00 10:20:10 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 10:20:10 %T 0000-00-00 10:20:10 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10 10:20:10AM %r 0000-00-00 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58 15 September 2001 %d %M %Y 2001-09-15 00:00:00 15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00 15 MAY 2001 %d %b %Y 2001-05-15 00:00:00 15th May 2001 %D %b %Y 2001-05-15 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Tuesday 00 2002 %W %U %Y 2002-01-01 00:00:00 Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00 Sunday 01 2001 %W %v %x 2001-01-07 00:00:00 Tuesday 52 2001 %W %V %X 2002-01-01 00:00:00 060 2004 %j %Y 2004-02-29 00:00:00 4 53 1998 %w %u %Y 1998-12-31 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 00:00:00 15-01-20 %d-%m-%y 2020-01-15 00:00:00 15-2001-1 %d-%Y-%c 2001-01-15 00:00:00 Loading @@ -186,16 +214,23 @@ date format date2 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 10:20:10 %H:%i:%s 0000-00-00 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 %T 0000-00-00 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10AM %r 0000-00-00 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 15 September 2001 %d %M %Y 2001-09-15 15 SEPTEMB 2001 %d %M %Y 2001-09-15 15 MAY 2001 %d %b %Y 2001-05-15 15th May 2001 %D %b %Y 2001-05-15 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 Tuesday 00 2002 %W %U %Y 2002-01-01 Thursday 53 1998 %W %u %Y 1998-12-31 Sunday 01 2001 %W %v %x 2001-01-07 Tuesday 52 2001 %W %V %X 2002-01-01 060 2004 %j %Y 2004-02-29 4 53 1998 %w %u %Y 1998-12-31 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 15-01-20 %d-%m-%y 2020-01-15 15-2001-1 %d-%Y-%c 2001-01-15 Loading @@ -210,16 +245,23 @@ date format time 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12 10:20:10 %H:%i:%s 10:20:10 10:20:10 %h:%i:%s.%f 10:20:10 10:20:10 %T 10:20:10 10:20:10AM %h:%i:%s%p 10:20:10 10:20:10AM %r 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58 15 September 2001 %d %M %Y 00:00:00 15 SEPTEMB 2001 %d %M %Y 00:00:00 15 MAY 2001 %d %b %Y 00:00:00 15th May 2001 %D %b %Y 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 00:00:00 Tuesday 00 2002 %W %U %Y 00:00:00 Thursday 53 1998 %W %u %Y 00:00:00 Sunday 01 2001 %W %v %x 00:00:00 Tuesday 52 2001 %W %V %X 00:00:00 060 2004 %j %Y 00:00:00 4 53 1998 %w %u %Y 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00 15-01-20 %d-%m-%y 00:00:00 15-2001-1 %d-%Y-%c 00:00:00 Loading @@ -234,16 +276,23 @@ date format time2 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12 10:20:10 %H:%i:%s 10:20:10 10:20:10 %h:%i:%s.%f 10:20:10 10:20:10 %T 10:20:10 10:20:10AM %h:%i:%s%p 10:20:10 10:20:10AM %r 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58 15 September 2001 %d %M %Y 00:00:00 15 SEPTEMB 2001 %d %M %Y 00:00:00 15 MAY 2001 %d %b %Y 00:00:00 15th May 2001 %D %b %Y 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 00:00:00 Tuesday 00 2002 %W %U %Y 00:00:00 Thursday 53 1998 %W %u %Y 00:00:00 Sunday 01 2001 %W %v %x 00:00:00 Tuesday 52 2001 %W %V %X 00:00:00 060 2004 %j %Y 00:00:00 4 53 1998 %w %u %Y 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00 15-01-20 %d-%m-%y 00:00:00 15-2001-1 %d-%Y-%c 00:00:00 Loading @@ -258,10 +307,13 @@ insert into t1 values ('15 Septembei 2001', '%d %M %Y'), ('15 Ju 2001', '%d %M %Y'), ('Sund 15 MA', '%W %d %b %Y'), ('Sunday 01 2001', '%W %V %X'), ('Thursdai 12 1998', '%W %u %Y'), (NULL, get_format(DATE,'USA')), ('Tuesday 52 2001', '%W %V %X'); ('Sunday 01 2001', '%W %v %X'), ('Tuesday 52 2001', '%W %V %x'), ('Tuesday 52 2001', '%W %V %Y'), ('Tuesday 52 2001', '%W %u %x'), ('7 53 1998', '%w %u %Y'), (NULL, get_format(DATE,'USA')); select date,format,str_to_date(date, format) as str_to_date from t1; date format str_to_date 2003-01-02 10:11:12 PM %Y-%m-%d %H:%i:%S %p NULL Loading @@ -273,10 +325,13 @@ date format str_to_date 15 Septembei 2001 %d %M %Y NULL 15 Ju 2001 %d %M %Y NULL Sund 15 MA %W %d %b %Y NULL Sunday 01 2001 %W %V %X NULL Thursdai 12 1998 %W %u %Y NULL Sunday 01 2001 %W %v %X NULL Tuesday 52 2001 %W %V %x NULL Tuesday 52 2001 %W %V %Y NULL Tuesday 52 2001 %W %u %x NULL 7 53 1998 %w %u %Y NULL NULL %m.%d.%Y NULL Tuesday 52 2001 %W %V %X NULL select date,format,concat(str_to_date(date, format),'') as con from t1; date format con 2003-01-02 10:11:12 PM %Y-%m-%d %H:%i:%S %p NULL Loading @@ -288,10 +343,13 @@ date format con 15 Septembei 2001 %d %M %Y NULL 15 Ju 2001 %d %M %Y NULL Sund 15 MA %W %d %b %Y NULL Sunday 01 2001 %W %V %X NULL Thursdai 12 1998 %W %u %Y NULL Sunday 01 2001 %W %v %X NULL Tuesday 52 2001 %W %V %x NULL Tuesday 52 2001 %W %V %Y NULL Tuesday 52 2001 %W %u %x NULL 7 53 1998 %w %u %Y NULL NULL %m.%d.%Y NULL Tuesday 52 2001 %W %V %X NULL truncate table t1; insert into t1 values ('10:20:10AM', '%h:%i:%s'), Loading mysql-test/t/date_formats.test +14 −4 Original line number Diff line number Diff line Loading @@ -132,16 +132,23 @@ insert into t1 values ('2003-01-02 11:11:12Pm', '%Y-%m-%d %h:%i:%S%p'), ('10:20:10', '%H:%i:%s'), ('10:20:10', '%h:%i:%s.%f'), ('10:20:10', '%T'), ('10:20:10AM', '%h:%i:%s%p'), ('10:20:10AM', '%r'), ('10:20:10.44AM', '%h:%i:%s.%f%p'), ('15-01-2001 12:59:58', '%d-%m-%Y %H:%i:%S'), ('15 September 2001', '%d %M %Y'), ('15 SEPTEMB 2001', '%d %M %Y'), ('15 MAY 2001', '%d %b %Y'), ('15th May 2001', '%D %b %Y'), ('Sunday 15 MAY 2001', '%W %d %b %Y'), ('Sund 15 MAY 2001', '%W %d %b %Y'), ('Tuesday 00 2002', '%W %U %Y'), ('Thursday 53 1998', '%W %u %Y'), ('Sunday 01 2001', '%W %v %x'), ('Tuesday 52 2001', '%W %V %X'), ('060 2004', '%j %Y'), ('4 53 1998', '%w %u %Y'), ('15-01-2001', '%d-%m-%Y %H:%i:%S'), ('15-01-20', '%d-%m-%y'), ('15-2001-1', '%d-%Y-%c'); Loading @@ -156,7 +163,7 @@ select date,format,DATE(str_to_date(date, format)) as date2 from t1; select date,format,TIME(str_to_date(date, format)) as time from t1; select date,format,concat(TIME(str_to_date(date, format))) as time2 from t1; # Test wrong dates # Test wrong dates or converion specifiers truncate table t1; insert into t1 values Loading @@ -169,10 +176,13 @@ insert into t1 values ('15 Septembei 2001', '%d %M %Y'), ('15 Ju 2001', '%d %M %Y'), ('Sund 15 MA', '%W %d %b %Y'), ('Sunday 01 2001', '%W %V %X'), ('Thursdai 12 1998', '%W %u %Y'), (NULL, get_format(DATE,'USA')), ('Tuesday 52 2001', '%W %V %X'); ('Sunday 01 2001', '%W %v %X'), ('Tuesday 52 2001', '%W %V %x'), ('Tuesday 52 2001', '%W %V %Y'), ('Tuesday 52 2001', '%W %u %x'), ('7 53 1998', '%w %u %Y'), (NULL, get_format(DATE,'USA')); select date,format,str_to_date(date, format) as str_to_date from t1; select date,format,concat(str_to_date(date, format),'') as con from t1; Loading sql/item_timefunc.cc +110 −30 Original line number Diff line number Diff line Loading @@ -113,6 +113,12 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, } /* Date formats corresponding to compound %r and %T conversion specifiers */ static DATE_TIME_FORMAT time_ampm_format= {{}, '\0', 0, {(char *)"%I:%i:%S %p", 11}}; static DATE_TIME_FORMAT time_24hrs_format= {{}, '\0', 0, {(char *)"%H:%i:%S", 8}}; /* Extract datetime value to TIME struct from string value according to format string. Loading @@ -126,6 +132,17 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, cached_timestamp_type It uses to get an appropriate warning in the case when the value is truncated. sub_pattern_end if non-zero then we are parsing string which should correspond compound specifier (like %T or %r) and this parameter is pointer to place where pointer to end of string matching this specifier should be stored. NOTE Possibility to parse strings matching to patterns equivalent to compound specifiers is mainly intended for use from inside of this function in order to understand %T and %r conversion specifiers, so number of conversion specifiers that can be used in such sub-patterns is limited. Also most of checks are skipped in this case. RETURN 0 ok Loading @@ -134,14 +151,18 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, static bool extract_date_time(DATE_TIME_FORMAT *format, const char *val, uint length, TIME *l_time, timestamp_type cached_timestamp_type) timestamp_type cached_timestamp_type, const char **sub_pattern_end) { int weekday= 0, yearday= 0, daypart= 0; int week_number= -1; CHARSET_INFO *cs= &my_charset_bin; int error= 0; bool usa_time= 0; bool sunday_first= 0; bool sunday_first_n_first_week_non_iso; bool strict_week_number; int strict_week_number_year= -1; bool strict_week_number_year_type; int frac_part; const char *val_begin= val; const char *val_end= val + length; Loading @@ -149,6 +170,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, const char *end= ptr + format->format.length; DBUG_ENTER("extract_date_time"); LINT_INIT(sunday_first_n_first_week_non_iso); LINT_INIT(strict_week_number); LINT_INIT(strict_week_number_year_type); if (!sub_pattern_end) bzero((char*) l_time, sizeof(*l_time)); for (; ptr != end && val != val_end; ptr++) Loading @@ -160,7 +186,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, char *tmp; /* Skip pre-space between each argument */ while (my_isspace(cs, *val) && val != val_end) while (val != val_end && my_isspace(cs, *val)) val++; val_len= (uint) (val_end - val); Loading Loading @@ -268,9 +294,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, break; case 'w': tmp= (char*) val + 1; if ((weekday= (int) my_strtoll10(val, &tmp, &error)) <= 0 || if ((weekday= (int) my_strtoll10(val, &tmp, &error)) < 0 || weekday >= 7) goto err; /* We should use the same 1 - 7 scale for %w as for %W */ if (!weekday) weekday= 7; val= tmp; break; case 'j': Loading @@ -279,15 +308,45 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, val= tmp; break; /* Week numbers */ case 'V': case 'U': sunday_first= 1; /* Fall through */ case 'v': case 'u': sunday_first_n_first_week_non_iso= (*ptr=='U' || *ptr== 'V'); strict_week_number= (*ptr=='V' || *ptr=='v'); tmp= (char*) val + min(val_len, 2); week_number= (int) my_strtoll10(val, &tmp, &error); if ((week_number= (int) my_strtoll10(val, &tmp, &error)) < 0 || strict_week_number && !week_number || week_number > 53) goto err; val= tmp; break; /* Year used with 'strict' %V and %v week numbers */ case 'X': case 'x': strict_week_number_year_type= (*ptr=='X'); tmp= (char*) val + min(4, val_len); strict_week_number_year= (int) my_strtoll10(val, &tmp, &error); val= tmp; break; /* Time in AM/PM notation */ case 'r': error= extract_date_time(&time_ampm_format, val, (uint)(val_end - val), l_time, cached_timestamp_type, &val); break; /* Time in 24-hour notation */ case 'T': error= extract_date_time(&time_24hrs_format, val, (uint)(val_end - val), l_time, cached_timestamp_type, &val); break; /* Conversion specifiers that match classes of characters */ case '.': while (my_ispunct(cs, *val) && val != val_end) val++; Loading Loading @@ -320,6 +379,16 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, l_time->hour= l_time->hour%12+daypart; } /* If we are recursively called for parsing string matching compound specifiers we are already done. */ if (sub_pattern_end) { *sub_pattern_end= val; DBUG_RETURN(0); } if (yearday > 0) { uint days= calc_daynr(l_time->year,1,1) + yearday - 1; Loading @@ -330,34 +399,45 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, if (week_number >= 0 && weekday) { int days= calc_daynr(l_time->year,1,1); int days; uint weekday_b; if (weekday > 7 || weekday < 0) /* %V,%v require %X,%x resprectively, %U,%u should be used with %Y and not %X or %x */ if (strict_week_number && (strict_week_number_year < 0 || strict_week_number_year_type != sunday_first_n_first_week_non_iso) || !strict_week_number && strict_week_number_year >= 0) goto err; if (sunday_first) weekday = weekday%7; if (week_number == 53) { days+= (week_number - 1)*7; weekday_b= calc_weekday(days, sunday_first); weekday = weekday - weekday_b - !sunday_first; days+= weekday; } else if (week_number == 0) /* Number of days since year 0 till 1st Jan of this year */ days= calc_daynr((strict_week_number ? strict_week_number_year : l_time->year), 1, 1); /* Which day of week is 1st Jan of this year */ weekday_b= calc_weekday(days, sunday_first_n_first_week_non_iso); /* Below we are going to sum: 1) number of days since year 0 till 1st day of 1st week of this year 2) number of days between 1st week and our week 3) and position of our day in the week */ if (sunday_first_n_first_week_non_iso) { weekday_b= calc_weekday(days, sunday_first); weekday = weekday - weekday_b - !sunday_first; days+= weekday; days+= ((weekday_b == 0) ? 0 : 7) - weekday_b + (week_number - 1) * 7 + weekday % 7; } else { days+= (week_number - !sunday_first)*7; weekday_b= calc_weekday(days, sunday_first); weekday =weekday - weekday_b - !sunday_first; days+= weekday; days+= ((weekday_b <= 3) ? 0 : 7) - weekday_b + (week_number - 1) * 7 + (weekday - 1); } if (days <= 0 || days >= MAX_DAY_NUMBER) goto err; get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); Loading Loading @@ -2599,7 +2679,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date) date_time_format.format.str= (char*) format->ptr(); date_time_format.format.length= format->length(); if (extract_date_time(&date_time_format, val->ptr(), val->length(), ltime, cached_timestamp_type)) ltime, cached_timestamp_type, 0)) goto null_date; if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day) { Loading Loading
mysql-test/r/date_formats.result +65 −7 Original line number Diff line number Diff line Loading @@ -90,16 +90,23 @@ insert into t1 values ('2003-01-02 11:11:12Pm', '%Y-%m-%d %h:%i:%S%p'), ('10:20:10', '%H:%i:%s'), ('10:20:10', '%h:%i:%s.%f'), ('10:20:10', '%T'), ('10:20:10AM', '%h:%i:%s%p'), ('10:20:10AM', '%r'), ('10:20:10.44AM', '%h:%i:%s.%f%p'), ('15-01-2001 12:59:58', '%d-%m-%Y %H:%i:%S'), ('15 September 2001', '%d %M %Y'), ('15 SEPTEMB 2001', '%d %M %Y'), ('15 MAY 2001', '%d %b %Y'), ('15th May 2001', '%D %b %Y'), ('Sunday 15 MAY 2001', '%W %d %b %Y'), ('Sund 15 MAY 2001', '%W %d %b %Y'), ('Tuesday 00 2002', '%W %U %Y'), ('Thursday 53 1998', '%W %u %Y'), ('Sunday 01 2001', '%W %v %x'), ('Tuesday 52 2001', '%W %V %X'), ('060 2004', '%j %Y'), ('4 53 1998', '%w %u %Y'), ('15-01-2001', '%d-%m-%Y %H:%i:%S'), ('15-01-20', '%d-%m-%y'), ('15-2001-1', '%d-%Y-%c'); Loading @@ -114,16 +121,23 @@ date format str_to_date 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12 10:20:10 %H:%i:%s 0000-00-00 10:20:10 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 10:20:10 %T 0000-00-00 10:20:10 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10 10:20:10AM %r 0000-00-00 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58 15 September 2001 %d %M %Y 2001-09-15 00:00:00 15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00 15 MAY 2001 %d %b %Y 2001-05-15 00:00:00 15th May 2001 %D %b %Y 2001-05-15 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Tuesday 00 2002 %W %U %Y 2002-01-01 00:00:00 Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00 Sunday 01 2001 %W %v %x 2001-01-07 00:00:00 Tuesday 52 2001 %W %V %X 2002-01-01 00:00:00 060 2004 %j %Y 2004-02-29 00:00:00 4 53 1998 %w %u %Y 1998-12-31 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 00:00:00 15-01-20 %d-%m-%y 2020-01-15 00:00:00 15-2001-1 %d-%Y-%c 2001-01-15 00:00:00 Loading @@ -138,16 +152,23 @@ date format con 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12 10:20:10 %H:%i:%s 0000-00-00 10:20:10 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 10:20:10 %T 0000-00-00 10:20:10 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10 10:20:10AM %r 0000-00-00 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58 15 September 2001 %d %M %Y 2001-09-15 00:00:00 15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00 15 MAY 2001 %d %b %Y 2001-05-15 00:00:00 15th May 2001 %D %b %Y 2001-05-15 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Tuesday 00 2002 %W %U %Y 2002-01-01 00:00:00 Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00 Sunday 01 2001 %W %v %x 2001-01-07 00:00:00 Tuesday 52 2001 %W %V %X 2002-01-01 00:00:00 060 2004 %j %Y 2004-02-29 00:00:00 4 53 1998 %w %u %Y 1998-12-31 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 00:00:00 15-01-20 %d-%m-%y 2020-01-15 00:00:00 15-2001-1 %d-%Y-%c 2001-01-15 00:00:00 Loading @@ -162,16 +183,23 @@ date format datetime 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12 10:20:10 %H:%i:%s 0000-00-00 10:20:10 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 10:20:10 %T 0000-00-00 10:20:10 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10 10:20:10AM %r 0000-00-00 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58 15 September 2001 %d %M %Y 2001-09-15 00:00:00 15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00 15 MAY 2001 %d %b %Y 2001-05-15 00:00:00 15th May 2001 %D %b %Y 2001-05-15 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 00:00:00 Tuesday 00 2002 %W %U %Y 2002-01-01 00:00:00 Thursday 53 1998 %W %u %Y 1998-12-31 00:00:00 Sunday 01 2001 %W %v %x 2001-01-07 00:00:00 Tuesday 52 2001 %W %V %X 2002-01-01 00:00:00 060 2004 %j %Y 2004-02-29 00:00:00 4 53 1998 %w %u %Y 1998-12-31 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 00:00:00 15-01-20 %d-%m-%y 2020-01-15 00:00:00 15-2001-1 %d-%Y-%c 2001-01-15 00:00:00 Loading @@ -186,16 +214,23 @@ date format date2 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 10:20:10 %H:%i:%s 0000-00-00 10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 %T 0000-00-00 10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10AM %r 0000-00-00 10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 15 September 2001 %d %M %Y 2001-09-15 15 SEPTEMB 2001 %d %M %Y 2001-09-15 15 MAY 2001 %d %b %Y 2001-05-15 15th May 2001 %D %b %Y 2001-05-15 Sunday 15 MAY 2001 %W %d %b %Y 2001-05-15 Sund 15 MAY 2001 %W %d %b %Y 2001-05-15 Tuesday 00 2002 %W %U %Y 2002-01-01 Thursday 53 1998 %W %u %Y 1998-12-31 Sunday 01 2001 %W %v %x 2001-01-07 Tuesday 52 2001 %W %V %X 2002-01-01 060 2004 %j %Y 2004-02-29 4 53 1998 %w %u %Y 1998-12-31 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 15-01-20 %d-%m-%y 2020-01-15 15-2001-1 %d-%Y-%c 2001-01-15 Loading @@ -210,16 +245,23 @@ date format time 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12 10:20:10 %H:%i:%s 10:20:10 10:20:10 %h:%i:%s.%f 10:20:10 10:20:10 %T 10:20:10 10:20:10AM %h:%i:%s%p 10:20:10 10:20:10AM %r 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58 15 September 2001 %d %M %Y 00:00:00 15 SEPTEMB 2001 %d %M %Y 00:00:00 15 MAY 2001 %d %b %Y 00:00:00 15th May 2001 %D %b %Y 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 00:00:00 Tuesday 00 2002 %W %U %Y 00:00:00 Thursday 53 1998 %W %u %Y 00:00:00 Sunday 01 2001 %W %v %x 00:00:00 Tuesday 52 2001 %W %V %X 00:00:00 060 2004 %j %Y 00:00:00 4 53 1998 %w %u %Y 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00 15-01-20 %d-%m-%y 00:00:00 15-2001-1 %d-%Y-%c 00:00:00 Loading @@ -234,16 +276,23 @@ date format time2 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12 10:20:10 %H:%i:%s 10:20:10 10:20:10 %h:%i:%s.%f 10:20:10 10:20:10 %T 10:20:10 10:20:10AM %h:%i:%s%p 10:20:10 10:20:10AM %r 10:20:10 10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58 15 September 2001 %d %M %Y 00:00:00 15 SEPTEMB 2001 %d %M %Y 00:00:00 15 MAY 2001 %d %b %Y 00:00:00 15th May 2001 %D %b %Y 00:00:00 Sunday 15 MAY 2001 %W %d %b %Y 00:00:00 Sund 15 MAY 2001 %W %d %b %Y 00:00:00 Tuesday 00 2002 %W %U %Y 00:00:00 Thursday 53 1998 %W %u %Y 00:00:00 Sunday 01 2001 %W %v %x 00:00:00 Tuesday 52 2001 %W %V %X 00:00:00 060 2004 %j %Y 00:00:00 4 53 1998 %w %u %Y 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00 15-01-20 %d-%m-%y 00:00:00 15-2001-1 %d-%Y-%c 00:00:00 Loading @@ -258,10 +307,13 @@ insert into t1 values ('15 Septembei 2001', '%d %M %Y'), ('15 Ju 2001', '%d %M %Y'), ('Sund 15 MA', '%W %d %b %Y'), ('Sunday 01 2001', '%W %V %X'), ('Thursdai 12 1998', '%W %u %Y'), (NULL, get_format(DATE,'USA')), ('Tuesday 52 2001', '%W %V %X'); ('Sunday 01 2001', '%W %v %X'), ('Tuesday 52 2001', '%W %V %x'), ('Tuesday 52 2001', '%W %V %Y'), ('Tuesday 52 2001', '%W %u %x'), ('7 53 1998', '%w %u %Y'), (NULL, get_format(DATE,'USA')); select date,format,str_to_date(date, format) as str_to_date from t1; date format str_to_date 2003-01-02 10:11:12 PM %Y-%m-%d %H:%i:%S %p NULL Loading @@ -273,10 +325,13 @@ date format str_to_date 15 Septembei 2001 %d %M %Y NULL 15 Ju 2001 %d %M %Y NULL Sund 15 MA %W %d %b %Y NULL Sunday 01 2001 %W %V %X NULL Thursdai 12 1998 %W %u %Y NULL Sunday 01 2001 %W %v %X NULL Tuesday 52 2001 %W %V %x NULL Tuesday 52 2001 %W %V %Y NULL Tuesday 52 2001 %W %u %x NULL 7 53 1998 %w %u %Y NULL NULL %m.%d.%Y NULL Tuesday 52 2001 %W %V %X NULL select date,format,concat(str_to_date(date, format),'') as con from t1; date format con 2003-01-02 10:11:12 PM %Y-%m-%d %H:%i:%S %p NULL Loading @@ -288,10 +343,13 @@ date format con 15 Septembei 2001 %d %M %Y NULL 15 Ju 2001 %d %M %Y NULL Sund 15 MA %W %d %b %Y NULL Sunday 01 2001 %W %V %X NULL Thursdai 12 1998 %W %u %Y NULL Sunday 01 2001 %W %v %X NULL Tuesday 52 2001 %W %V %x NULL Tuesday 52 2001 %W %V %Y NULL Tuesday 52 2001 %W %u %x NULL 7 53 1998 %w %u %Y NULL NULL %m.%d.%Y NULL Tuesday 52 2001 %W %V %X NULL truncate table t1; insert into t1 values ('10:20:10AM', '%h:%i:%s'), Loading
mysql-test/t/date_formats.test +14 −4 Original line number Diff line number Diff line Loading @@ -132,16 +132,23 @@ insert into t1 values ('2003-01-02 11:11:12Pm', '%Y-%m-%d %h:%i:%S%p'), ('10:20:10', '%H:%i:%s'), ('10:20:10', '%h:%i:%s.%f'), ('10:20:10', '%T'), ('10:20:10AM', '%h:%i:%s%p'), ('10:20:10AM', '%r'), ('10:20:10.44AM', '%h:%i:%s.%f%p'), ('15-01-2001 12:59:58', '%d-%m-%Y %H:%i:%S'), ('15 September 2001', '%d %M %Y'), ('15 SEPTEMB 2001', '%d %M %Y'), ('15 MAY 2001', '%d %b %Y'), ('15th May 2001', '%D %b %Y'), ('Sunday 15 MAY 2001', '%W %d %b %Y'), ('Sund 15 MAY 2001', '%W %d %b %Y'), ('Tuesday 00 2002', '%W %U %Y'), ('Thursday 53 1998', '%W %u %Y'), ('Sunday 01 2001', '%W %v %x'), ('Tuesday 52 2001', '%W %V %X'), ('060 2004', '%j %Y'), ('4 53 1998', '%w %u %Y'), ('15-01-2001', '%d-%m-%Y %H:%i:%S'), ('15-01-20', '%d-%m-%y'), ('15-2001-1', '%d-%Y-%c'); Loading @@ -156,7 +163,7 @@ select date,format,DATE(str_to_date(date, format)) as date2 from t1; select date,format,TIME(str_to_date(date, format)) as time from t1; select date,format,concat(TIME(str_to_date(date, format))) as time2 from t1; # Test wrong dates # Test wrong dates or converion specifiers truncate table t1; insert into t1 values Loading @@ -169,10 +176,13 @@ insert into t1 values ('15 Septembei 2001', '%d %M %Y'), ('15 Ju 2001', '%d %M %Y'), ('Sund 15 MA', '%W %d %b %Y'), ('Sunday 01 2001', '%W %V %X'), ('Thursdai 12 1998', '%W %u %Y'), (NULL, get_format(DATE,'USA')), ('Tuesday 52 2001', '%W %V %X'); ('Sunday 01 2001', '%W %v %X'), ('Tuesday 52 2001', '%W %V %x'), ('Tuesday 52 2001', '%W %V %Y'), ('Tuesday 52 2001', '%W %u %x'), ('7 53 1998', '%w %u %Y'), (NULL, get_format(DATE,'USA')); select date,format,str_to_date(date, format) as str_to_date from t1; select date,format,concat(str_to_date(date, format),'') as con from t1; Loading
sql/item_timefunc.cc +110 −30 Original line number Diff line number Diff line Loading @@ -113,6 +113,12 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, } /* Date formats corresponding to compound %r and %T conversion specifiers */ static DATE_TIME_FORMAT time_ampm_format= {{}, '\0', 0, {(char *)"%I:%i:%S %p", 11}}; static DATE_TIME_FORMAT time_24hrs_format= {{}, '\0', 0, {(char *)"%H:%i:%S", 8}}; /* Extract datetime value to TIME struct from string value according to format string. Loading @@ -126,6 +132,17 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, cached_timestamp_type It uses to get an appropriate warning in the case when the value is truncated. sub_pattern_end if non-zero then we are parsing string which should correspond compound specifier (like %T or %r) and this parameter is pointer to place where pointer to end of string matching this specifier should be stored. NOTE Possibility to parse strings matching to patterns equivalent to compound specifiers is mainly intended for use from inside of this function in order to understand %T and %r conversion specifiers, so number of conversion specifiers that can be used in such sub-patterns is limited. Also most of checks are skipped in this case. RETURN 0 ok Loading @@ -134,14 +151,18 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, static bool extract_date_time(DATE_TIME_FORMAT *format, const char *val, uint length, TIME *l_time, timestamp_type cached_timestamp_type) timestamp_type cached_timestamp_type, const char **sub_pattern_end) { int weekday= 0, yearday= 0, daypart= 0; int week_number= -1; CHARSET_INFO *cs= &my_charset_bin; int error= 0; bool usa_time= 0; bool sunday_first= 0; bool sunday_first_n_first_week_non_iso; bool strict_week_number; int strict_week_number_year= -1; bool strict_week_number_year_type; int frac_part; const char *val_begin= val; const char *val_end= val + length; Loading @@ -149,6 +170,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, const char *end= ptr + format->format.length; DBUG_ENTER("extract_date_time"); LINT_INIT(sunday_first_n_first_week_non_iso); LINT_INIT(strict_week_number); LINT_INIT(strict_week_number_year_type); if (!sub_pattern_end) bzero((char*) l_time, sizeof(*l_time)); for (; ptr != end && val != val_end; ptr++) Loading @@ -160,7 +186,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, char *tmp; /* Skip pre-space between each argument */ while (my_isspace(cs, *val) && val != val_end) while (val != val_end && my_isspace(cs, *val)) val++; val_len= (uint) (val_end - val); Loading Loading @@ -268,9 +294,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, break; case 'w': tmp= (char*) val + 1; if ((weekday= (int) my_strtoll10(val, &tmp, &error)) <= 0 || if ((weekday= (int) my_strtoll10(val, &tmp, &error)) < 0 || weekday >= 7) goto err; /* We should use the same 1 - 7 scale for %w as for %W */ if (!weekday) weekday= 7; val= tmp; break; case 'j': Loading @@ -279,15 +308,45 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, val= tmp; break; /* Week numbers */ case 'V': case 'U': sunday_first= 1; /* Fall through */ case 'v': case 'u': sunday_first_n_first_week_non_iso= (*ptr=='U' || *ptr== 'V'); strict_week_number= (*ptr=='V' || *ptr=='v'); tmp= (char*) val + min(val_len, 2); week_number= (int) my_strtoll10(val, &tmp, &error); if ((week_number= (int) my_strtoll10(val, &tmp, &error)) < 0 || strict_week_number && !week_number || week_number > 53) goto err; val= tmp; break; /* Year used with 'strict' %V and %v week numbers */ case 'X': case 'x': strict_week_number_year_type= (*ptr=='X'); tmp= (char*) val + min(4, val_len); strict_week_number_year= (int) my_strtoll10(val, &tmp, &error); val= tmp; break; /* Time in AM/PM notation */ case 'r': error= extract_date_time(&time_ampm_format, val, (uint)(val_end - val), l_time, cached_timestamp_type, &val); break; /* Time in 24-hour notation */ case 'T': error= extract_date_time(&time_24hrs_format, val, (uint)(val_end - val), l_time, cached_timestamp_type, &val); break; /* Conversion specifiers that match classes of characters */ case '.': while (my_ispunct(cs, *val) && val != val_end) val++; Loading Loading @@ -320,6 +379,16 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, l_time->hour= l_time->hour%12+daypart; } /* If we are recursively called for parsing string matching compound specifiers we are already done. */ if (sub_pattern_end) { *sub_pattern_end= val; DBUG_RETURN(0); } if (yearday > 0) { uint days= calc_daynr(l_time->year,1,1) + yearday - 1; Loading @@ -330,34 +399,45 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, if (week_number >= 0 && weekday) { int days= calc_daynr(l_time->year,1,1); int days; uint weekday_b; if (weekday > 7 || weekday < 0) /* %V,%v require %X,%x resprectively, %U,%u should be used with %Y and not %X or %x */ if (strict_week_number && (strict_week_number_year < 0 || strict_week_number_year_type != sunday_first_n_first_week_non_iso) || !strict_week_number && strict_week_number_year >= 0) goto err; if (sunday_first) weekday = weekday%7; if (week_number == 53) { days+= (week_number - 1)*7; weekday_b= calc_weekday(days, sunday_first); weekday = weekday - weekday_b - !sunday_first; days+= weekday; } else if (week_number == 0) /* Number of days since year 0 till 1st Jan of this year */ days= calc_daynr((strict_week_number ? strict_week_number_year : l_time->year), 1, 1); /* Which day of week is 1st Jan of this year */ weekday_b= calc_weekday(days, sunday_first_n_first_week_non_iso); /* Below we are going to sum: 1) number of days since year 0 till 1st day of 1st week of this year 2) number of days between 1st week and our week 3) and position of our day in the week */ if (sunday_first_n_first_week_non_iso) { weekday_b= calc_weekday(days, sunday_first); weekday = weekday - weekday_b - !sunday_first; days+= weekday; days+= ((weekday_b == 0) ? 0 : 7) - weekday_b + (week_number - 1) * 7 + weekday % 7; } else { days+= (week_number - !sunday_first)*7; weekday_b= calc_weekday(days, sunday_first); weekday =weekday - weekday_b - !sunday_first; days+= weekday; days+= ((weekday_b <= 3) ? 0 : 7) - weekday_b + (week_number - 1) * 7 + (weekday - 1); } if (days <= 0 || days >= MAX_DAY_NUMBER) goto err; get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); Loading Loading @@ -2599,7 +2679,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date) date_time_format.format.str= (char*) format->ptr(); date_time_format.format.length= format->length(); if (extract_date_time(&date_time_format, val->ptr(), val->length(), ltime, cached_timestamp_type)) ltime, cached_timestamp_type, 0)) goto null_date; if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day) { Loading