diff -Nur sql/item_create.cc ../mysql-5.0.21-patched/sql/item_create.cc --- sql/item_create.cc 2006-04-26 20:30:56.000000000 +0200 +++ ../mysql-5.0.21-patched/sql/item_create.cc 2007-05-19 01:00:45.000000000 +0200 @@ -681,6 +681,11 @@ new Item_func_to_days(b)); } +Item *create_func_workdays(Item* a,Item* b) +{ + return new Item_func_workdays(a, b); +} + Item *create_func_weekofyear(Item *a) { return new Item_func_week(a, new Item_int((char*) "0", 3, 1)); diff -Nur sql/item_create.h ../mysql-5.0.21-patched/sql/item_create.h --- sql/item_create.h 2006-04-26 20:30:48.000000000 +0200 +++ ../mysql-5.0.21-patched/sql/item_create.h 2007-05-19 01:06:43.000000000 +0200 @@ -98,6 +98,7 @@ Item *create_func_uuid(void); Item *create_func_version(void); Item *create_func_weekday(Item* a); +Item *create_func_workdays(Item* a, Item* b); Item *create_load_file(Item* a); Item *create_func_is_free_lock(Item* a); Item *create_func_is_used_lock(Item* a); diff -Nur sql/item_timefunc.cc ../mysql-5.0.21-patched/sql/item_timefunc.cc --- sql/item_timefunc.cc 2006-04-26 20:31:09.000000000 +0200 +++ ../mysql-5.0.21-patched/sql/item_timefunc.cc 2007-05-19 01:40:41.000000000 +0200 @@ -875,6 +875,46 @@ } +longlong Item_func_workdays::val_int() +{ + DBUG_ASSERT(fixed == 1); + TIME lstarttime; + TIME lstoptime; + + uint fuzzy_date; + args[0]->get_date(&lstarttime, fuzzy_date); + args[1]->get_date(&lstoptime, fuzzy_date); + + longlong days1 = calc_daynr(lstarttime.year,lstarttime.month,lstarttime.day); + longlong days2 = calc_daynr(lstoptime.year,lstoptime.month,lstoptime.day); + longlong nrofdays = days2 - days1; + + if (nrofdays==0) return (longlong) 1; // e.g. monday - monday = 1 day + + bool neg_nrofdays = (nrofdays < 0); + int dayofweek = calc_weekday((neg_nrofdays ? days2 : days1), 0); + nrofdays = abs(nrofdays)+1; // e.g. diff mon-tue = 1, but takes 2 days + + longlong nrofweekends = (longlong) floor(nrofdays / 7); + int mod = nrofdays % 7; + int add = 0; + + // Correction when the remainder (part of a week) + // fully or partly comprises a weekend. + if (mod) + { + if ((dayofweek)==6) add=1; + else + { + add = mod - (5 - dayofweek); + if (add<0) add = 0; + if (add>1) add = 2; + } + } + + return (longlong) (neg_nrofdays ? -1 : +1)*(nrofdays - ((nrofweekends*2) + add)); +} + longlong Item_func_to_days::val_int() { Binary files sql/.item_timefunc.cc.swp and ../mysql-5.0.21-patched/sql/.item_timefunc.cc.swp differ diff -Nur sql/item_timefunc.h ../mysql-5.0.21-patched/sql/item_timefunc.h --- sql/item_timefunc.h 2006-04-26 20:30:56.000000000 +0200 +++ ../mysql-5.0.21-patched/sql/item_timefunc.h 2007-05-19 01:10:32.000000000 +0200 @@ -67,6 +67,21 @@ } }; +class Item_func_workdays :public Item_int_func +{ +public: + Item_func_workdays(Item *a, Item *b) :Item_int_func(a, b) {} + longlong val_int(); + const char *func_name() const { return "workdays"; } + void fix_length_and_dec() + { + decimals=0; + max_length=6*MY_CHARSET_BIN_MB_MAXLEN; + maybe_null=1; + } +}; + + class Item_func_dayofmonth :public Item_int_func { diff -Nur sql/lex.h ../mysql-5.0.21-patched/sql/lex.h --- sql/lex.h 2006-04-26 20:30:47.000000000 +0200 +++ ../mysql-5.0.21-patched/sql/lex.h 2007-05-19 00:24:46.000000000 +0200 @@ -588,6 +588,7 @@ { "CURTIME", SYM(CURTIME)}, { "DATE_ADD", SYM(DATE_ADD_INTERVAL)}, { "DATEDIFF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)}, + { "WORKDAYS", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_workdays)}, { "DATE_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)}, { "DATE_SUB", SYM(DATE_SUB_INTERVAL)}, { "DAYNAME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)},