mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
WL#1175: more default_week_formats for iso compatibility
New formats added for 'week()' function and 'default_week_format' option(4 - 7). Next formats is supported now: *Value* *Meaning* `0' Week starts on Sunday; First Sunday of the year starts week 1. Week() returns 0-53. `1' Week starts on Monday; Weeks numbered according to ISO 8601:1988. Week() returns 0-53. `2' Week starts on Sunday; First Sunday of the year starts week 1. Week() returns 1-53. `3' Week starts on Monday; Weeks numbered according to ISO 8601:1988. Week() returns 1-53. `4' Week starts on Sunday; Weeks numbered according to ISO 8601:1988. Week() returns 0-53. `5' Week starts on Monday; First Monday of the year starts week 1. Week() returns 0-53. `6' Week starts on Sunday; Weeks numbered according to ISO 8601:1988. Week() returns 1-53. `7' Week starts on Monday; First Monday of the year starts week 1. Week() returns 1-53.
This commit is contained in:
@@ -95,11 +95,34 @@ week(19981231,2) week(19981231,3) week(20000101,2) week(20000101,3)
|
|||||||
52 53 52 52
|
52 53 52 52
|
||||||
select week(20001231,2),week(20001231,3);
|
select week(20001231,2),week(20001231,3);
|
||||||
week(20001231,2) week(20001231,3)
|
week(20001231,2) week(20001231,3)
|
||||||
1 52
|
53 52
|
||||||
|
select week(19981231,0) as '0', week(19981231,1) as '1', week(19981231,2) as '2', week(19981231,3) as '3', week(19981231,4) as '4', week(19981231,5) as '5', week(19981231,6) as '6', week(19981231,7) as '7';
|
||||||
|
0 1 2 3 4 5 6 7
|
||||||
|
52 53 52 53 52 52 52 52
|
||||||
|
select week(20000101,0) as '0', week(20000101,1) as '1', week(20000101,2) as '2', week(20000101,3) as '3', week(20000101,4) as '4', week(20000101,5) as '5', week(20000101,6) as '6', week(20000101,7) as '7';
|
||||||
|
0 1 2 3 4 5 6 7
|
||||||
|
0 0 52 52 0 0 52 52
|
||||||
|
select week(20000106,0) as '0', week(20000106,1) as '1', week(20000106,2) as '2', week(20000106,3) as '3', week(20000106,4) as '4', week(20000106,5) as '5', week(20000106,6) as '6', week(20000106,7) as '7';
|
||||||
|
0 1 2 3 4 5 6 7
|
||||||
|
1 1 1 1 1 1 1 1
|
||||||
|
select week(20001231,0) as '0', week(20001231,1) as '1', week(20001231,2) as '2', week(20001231,3) as '3', week(20001231,4) as '4', week(20001231,5) as '5', week(20001231,6) as '6', week(20001231,7) as '7';
|
||||||
|
0 1 2 3 4 5 6 7
|
||||||
|
53 52 53 52 53 52 1 52
|
||||||
|
select week(20010101,0) as '0', week(20010101,1) as '1', week(20010101,2) as '2', week(20010101,3) as '3', week(20010101,4) as '4', week(20010101,5) as '5', week(20010101,6) as '6', week(20010101,7) as '7';
|
||||||
|
0 1 2 3 4 5 6 7
|
||||||
|
0 1 53 1 1 1 1 1
|
||||||
|
select yearweek(20001231,0), yearweek(20001231,1), yearweek(20001231,2), yearweek(20001231,3), yearweek(20001231,4), yearweek(20001231,5), yearweek(20001231,6), yearweek(20001231,7);
|
||||||
|
yearweek(20001231,0) yearweek(20001231,1) yearweek(20001231,2) yearweek(20001231,3) yearweek(20001231,4) yearweek(20001231,5) yearweek(20001231,6) yearweek(20001231,7)
|
||||||
|
200053 200052 200053 200052 200101 200052 200101 200052
|
||||||
|
set default_week_format = 6;
|
||||||
|
select week(20001231), week(20001231,6);
|
||||||
|
week(20001231) week(20001231,6)
|
||||||
|
1 1
|
||||||
|
set default_week_format = 0;
|
||||||
set default_week_format = 2;
|
set default_week_format = 2;
|
||||||
select week(20001231),week(20001231,2),week(20001231,0);
|
select week(20001231),week(20001231,2),week(20001231,0);
|
||||||
week(20001231) week(20001231,2) week(20001231,0)
|
week(20001231) week(20001231,2) week(20001231,0)
|
||||||
1 1 53
|
53 53 53
|
||||||
set default_week_format = 0;
|
set default_week_format = 0;
|
||||||
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
|
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
|
||||||
date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v')
|
date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v')
|
||||||
|
@@ -39,6 +39,18 @@ select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', y
|
|||||||
select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
|
select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
|
||||||
select week(20001231,2),week(20001231,3);
|
select week(20001231,2),week(20001231,3);
|
||||||
|
|
||||||
|
select week(19981231,0) as '0', week(19981231,1) as '1', week(19981231,2) as '2', week(19981231,3) as '3', week(19981231,4) as '4', week(19981231,5) as '5', week(19981231,6) as '6', week(19981231,7) as '7';
|
||||||
|
select week(20000101,0) as '0', week(20000101,1) as '1', week(20000101,2) as '2', week(20000101,3) as '3', week(20000101,4) as '4', week(20000101,5) as '5', week(20000101,6) as '6', week(20000101,7) as '7';
|
||||||
|
select week(20000106,0) as '0', week(20000106,1) as '1', week(20000106,2) as '2', week(20000106,3) as '3', week(20000106,4) as '4', week(20000106,5) as '5', week(20000106,6) as '6', week(20000106,7) as '7';
|
||||||
|
select week(20001231,0) as '0', week(20001231,1) as '1', week(20001231,2) as '2', week(20001231,3) as '3', week(20001231,4) as '4', week(20001231,5) as '5', week(20001231,6) as '6', week(20001231,7) as '7';
|
||||||
|
select week(20010101,0) as '0', week(20010101,1) as '1', week(20010101,2) as '2', week(20010101,3) as '3', week(20010101,4) as '4', week(20010101,5) as '5', week(20010101,6) as '6', week(20010101,7) as '7';
|
||||||
|
|
||||||
|
select yearweek(20001231,0), yearweek(20001231,1), yearweek(20001231,2), yearweek(20001231,3), yearweek(20001231,4), yearweek(20001231,5), yearweek(20001231,6), yearweek(20001231,7);
|
||||||
|
|
||||||
|
set default_week_format = 6;
|
||||||
|
select week(20001231), week(20001231,6);
|
||||||
|
set default_week_format = 0;
|
||||||
|
|
||||||
set default_week_format = 2;
|
set default_week_format = 2;
|
||||||
select week(20001231),week(20001231,2),week(20001231,0);
|
select week(20001231),week(20001231,2),week(20001231,0);
|
||||||
set default_week_format = 0;
|
set default_week_format = 0;
|
||||||
|
@@ -175,27 +175,51 @@ longlong Item_func_second::val_int()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
uint week_mode(uint mode)
|
||||||
Returns the week of year.
|
{
|
||||||
|
uint week_format= (mode & 7);
|
||||||
|
if (!(week_format & WEEK_MONDAY_FIRST))
|
||||||
|
week_format^= WEEK_FIRST_WEEKDAY;
|
||||||
|
return week_format;
|
||||||
|
}
|
||||||
|
|
||||||
The bits in week_format has the following meaning:
|
/*
|
||||||
0 If not set: USA format: Sunday is first day of week
|
The bits in week_format(for calc_week() function) has the following meaning:
|
||||||
If set: ISO format: Monday is first day of week
|
WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
|
||||||
1 If not set: Week is in range 0-53
|
If set Monday is first day of week
|
||||||
If set Week is in range 1-53.
|
WEEK_YEAR (1) If not set Week is in range 0-53
|
||||||
|
|
||||||
|
Week 0 is returned for the the last week of the previous year (for
|
||||||
|
a date at start of january) In this case one can get 53 for the
|
||||||
|
first week of next year. This flag ensures that the week is
|
||||||
|
relevant for the given year. Note that this flag is only
|
||||||
|
releveant if WEEK_JANUARY is not set.
|
||||||
|
|
||||||
|
If set Week is in range 1-53.
|
||||||
|
|
||||||
|
In this case one may get week 53 for a date in January (when
|
||||||
|
the week is that last week of previous year) and week 1 for a
|
||||||
|
date in December.
|
||||||
|
|
||||||
|
WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
|
||||||
|
to ISO 8601:1988
|
||||||
|
If set The week that contains the first
|
||||||
|
'first-day-of-week' is week 1.
|
||||||
|
|
||||||
|
ISO 8601:1988 means that if the week containing January 1 has
|
||||||
|
four or more days in the new year, then it is week 1;
|
||||||
|
Otherwise it is the last week of the previous year, and the
|
||||||
|
next week is week 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
longlong Item_func_week::val_int()
|
longlong Item_func_week::val_int()
|
||||||
{
|
{
|
||||||
uint year;
|
uint year;
|
||||||
uint week_format;
|
|
||||||
TIME ltime;
|
TIME ltime;
|
||||||
if (get_arg0_date(<ime,0))
|
if (get_arg0_date(<ime,0))
|
||||||
return 0;
|
return 0;
|
||||||
week_format= (uint) args[1]->val_int();
|
return (longlong) calc_week(<ime,
|
||||||
return (longlong) calc_week(<ime,
|
week_mode((uint) args[1]->val_int()),
|
||||||
(week_format & 2) != 0,
|
|
||||||
(week_format & 1) == 0,
|
|
||||||
&year);
|
&year);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +230,9 @@ longlong Item_func_yearweek::val_int()
|
|||||||
TIME ltime;
|
TIME ltime;
|
||||||
if (get_arg0_date(<ime,0))
|
if (get_arg0_date(<ime,0))
|
||||||
return 0;
|
return 0;
|
||||||
week=calc_week(<ime, 1, (args[1]->val_int() & 1) == 0, &year);
|
week= calc_week(<ime,
|
||||||
|
(week_mode((uint) args[1]->val_int()) | WEEK_YEAR),
|
||||||
|
&year);
|
||||||
return week+year*100;
|
return week+year*100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,7 +870,10 @@ String *Item_func_date_format::val_str(String *str)
|
|||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
uint year;
|
uint year;
|
||||||
sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year));
|
sprintf(intbuff,"%02d",
|
||||||
|
calc_week(&l_time,
|
||||||
|
((*ptr) == 'U' ?
|
||||||
|
WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST) , &year));
|
||||||
str->append(intbuff);
|
str->append(intbuff);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -852,7 +881,11 @@ String *Item_func_date_format::val_str(String *str)
|
|||||||
case 'V':
|
case 'V':
|
||||||
{
|
{
|
||||||
uint year;
|
uint year;
|
||||||
sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year));
|
sprintf(intbuff,"%02d",
|
||||||
|
calc_week(&l_time,
|
||||||
|
((*ptr) == 'V' ? WEEK_YEAR | WEEK_FIRST_WEEKDAY :
|
||||||
|
WEEK_YEAR | WEEK_MONDAY_FIRST),
|
||||||
|
&year));
|
||||||
str->append(intbuff);
|
str->append(intbuff);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -860,7 +893,10 @@ String *Item_func_date_format::val_str(String *str)
|
|||||||
case 'X':
|
case 'X':
|
||||||
{
|
{
|
||||||
uint year;
|
uint year;
|
||||||
(void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
|
(void) calc_week(&l_time,
|
||||||
|
((*ptr) == 'X' ? WEEK_YEAR | WEEK_FIRST_WEEKDAY :
|
||||||
|
WEEK_YEAR | WEEK_MONDAY_FIRST),
|
||||||
|
&year);
|
||||||
sprintf(intbuff,"%04d",year);
|
sprintf(intbuff,"%04d",year);
|
||||||
str->append(intbuff);
|
str->append(intbuff);
|
||||||
}
|
}
|
||||||
|
@@ -247,6 +247,11 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
|
|||||||
#define tmp_file_prefix "#sql" /* Prefix for tmp tables */
|
#define tmp_file_prefix "#sql" /* Prefix for tmp tables */
|
||||||
#define tmp_file_prefix_length 4
|
#define tmp_file_prefix_length 4
|
||||||
|
|
||||||
|
/* Flags for calc_week() function. */
|
||||||
|
#define WEEK_MONDAY_FIRST 1
|
||||||
|
#define WEEK_YEAR 2
|
||||||
|
#define WEEK_FIRST_WEEKDAY 4
|
||||||
|
|
||||||
struct st_table;
|
struct st_table;
|
||||||
class THD;
|
class THD;
|
||||||
|
|
||||||
@@ -806,8 +811,7 @@ ha_rows filesort(TABLE *form,struct st_sort_field *sortorder, uint s_length,
|
|||||||
void change_double_for_sort(double nr,byte *to);
|
void change_double_for_sort(double nr,byte *to);
|
||||||
int get_quick_record(SQL_SELECT *select);
|
int get_quick_record(SQL_SELECT *select);
|
||||||
int calc_weekday(long daynr,bool sunday_first_day_of_week);
|
int calc_weekday(long daynr,bool sunday_first_day_of_week);
|
||||||
uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week,
|
uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
|
||||||
uint *year);
|
|
||||||
void find_date(char *pos,uint *vek,uint flag);
|
void find_date(char *pos,uint *vek,uint flag);
|
||||||
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
|
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
|
||||||
TYPELIB *typelib(List<String> &strings);
|
TYPELIB *typelib(List<String> &strings);
|
||||||
|
@@ -4105,7 +4105,7 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \
|
|||||||
"The default week format used by WEEK() functions.",
|
"The default week format used by WEEK() functions.",
|
||||||
(gptr*) &global_system_variables.default_week_format,
|
(gptr*) &global_system_variables.default_week_format,
|
||||||
(gptr*) &max_system_variables.default_week_format,
|
(gptr*) &max_system_variables.default_week_format,
|
||||||
0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0},
|
0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0},
|
||||||
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
68
sql/time.cc
68
sql/time.cc
@@ -175,42 +175,72 @@ uint calc_days_in_year(uint year)
|
|||||||
366 : 365;
|
366 : 365;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate week. If 'with_year' is not set, then return a week 0-53, where
|
|
||||||
0 means that it's the last week of the previous year.
|
|
||||||
If 'with_year' is set then the week will always be in the range 1-53 and
|
|
||||||
the year out parameter will contain the year for the week */
|
|
||||||
|
|
||||||
uint calc_week(TIME *l_time, bool with_year, bool sunday_first_day_of_week,
|
/*
|
||||||
uint *year)
|
The bits in week_format has the following meaning:
|
||||||
|
WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
|
||||||
|
If set Monday is first day of week
|
||||||
|
WEEK_YEAR (1) If not set Week is in range 0-53
|
||||||
|
|
||||||
|
Week 0 is returned for the the last week of the previous year (for
|
||||||
|
a date at start of january) In this case one can get 53 for the
|
||||||
|
first week of next year. This flag ensures that the week is
|
||||||
|
relevant for the given year. Note that this flag is only
|
||||||
|
releveant if WEEK_JANUARY is not set.
|
||||||
|
|
||||||
|
If set Week is in range 1-53.
|
||||||
|
|
||||||
|
In this case one may get week 53 for a date in January (when
|
||||||
|
the week is that last week of previous year) and week 1 for a
|
||||||
|
date in December.
|
||||||
|
|
||||||
|
WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
|
||||||
|
to ISO 8601:1988
|
||||||
|
If set The week that contains the first
|
||||||
|
'first-day-of-week' is week 1.
|
||||||
|
|
||||||
|
ISO 8601:1988 means that if the week containing January 1 has
|
||||||
|
four or more days in the new year, then it is week 1;
|
||||||
|
Otherwise it is the last week of the previous year, and the
|
||||||
|
next week is week 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint calc_week(TIME *l_time, uint week_behaviour, uint *year)
|
||||||
{
|
{
|
||||||
uint days;
|
uint days;
|
||||||
ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day);
|
ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day);
|
||||||
ulong first_daynr=calc_daynr(l_time->year,1,1);
|
ulong first_daynr=calc_daynr(l_time->year,1,1);
|
||||||
uint weekday=calc_weekday(first_daynr,sunday_first_day_of_week);
|
bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST);
|
||||||
|
bool week_year= test(week_behaviour & WEEK_YEAR);
|
||||||
|
bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY);
|
||||||
|
|
||||||
|
uint weekday=calc_weekday(first_daynr, !monday_first);
|
||||||
*year=l_time->year;
|
*year=l_time->year;
|
||||||
if (l_time->month == 1 && l_time->day <= 7-weekday &&
|
|
||||||
((!sunday_first_day_of_week && weekday >= 4) ||
|
if (l_time->month == 1 && l_time->day <= 7-weekday)
|
||||||
(sunday_first_day_of_week && weekday != 0)))
|
|
||||||
{
|
{
|
||||||
/* Last week of the previous year */
|
if (!week_year &&
|
||||||
if (!with_year)
|
(first_weekday && weekday != 0 ||
|
||||||
|
!first_weekday && weekday >= 4))
|
||||||
return 0;
|
return 0;
|
||||||
with_year=0; // Don't check the week again
|
week_year= 1;
|
||||||
(*year)--;
|
(*year)--;
|
||||||
first_daynr-= (days=calc_days_in_year(*year));
|
first_daynr-= (days=calc_days_in_year(*year));
|
||||||
weekday= (weekday + 53*7- days) % 7;
|
weekday= (weekday + 53*7- days) % 7;
|
||||||
}
|
}
|
||||||
if ((sunday_first_day_of_week && weekday != 0) ||
|
|
||||||
(!sunday_first_day_of_week && weekday >= 4))
|
if ((first_weekday && weekday != 0) ||
|
||||||
|
(!first_weekday && weekday >= 4))
|
||||||
days= daynr - (first_daynr+ (7-weekday));
|
days= daynr - (first_daynr+ (7-weekday));
|
||||||
else
|
else
|
||||||
days= daynr - (first_daynr - weekday);
|
days= daynr - (first_daynr - weekday);
|
||||||
if (with_year && days >= 52*7)
|
|
||||||
|
if (week_year && days >= 52*7)
|
||||||
{
|
{
|
||||||
/* Check if we are on the first week of the next year (or week 53) */
|
|
||||||
weekday= (weekday + calc_days_in_year(*year)) % 7;
|
weekday= (weekday + calc_days_in_year(*year)) % 7;
|
||||||
if (weekday < 4)
|
if (!first_weekday && weekday < 4 ||
|
||||||
{ // We are at first week on next year
|
first_weekday && weekday == 0)
|
||||||
|
{
|
||||||
(*year)++;
|
(*year)++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user