diff --git a/include/my_time.h b/include/my_time.h
index d4dbe459c3bb336bd1c55cee9c8220d763fd6b3e..dab17904b2df9f0ba303472b26bc6464ca5b76b7 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -60,6 +60,20 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
 
 void set_zero_time(MYSQL_TIME *tm);
 
+/*
+  Required buffer length for my_time_to_str, my_date_to_str,
+  my_datetime_to_str and TIME_to_string functions. Note, that the
+  caller is still responsible to check that given TIME structure
+  has values in valid ranges, otherwise size of the buffer could
+  be not enough.
+*/
+#define MAX_DATE_STRING_REP_LENGTH 30
+
+int my_time_to_str(const MYSQL_TIME *l_time, char *to);
+int my_date_to_str(const MYSQL_TIME *l_time, char *to);
+int my_datetime_to_str(const MYSQL_TIME *l_time, char *to);
+int my_TIME_to_str(const MYSQL_TIME *l_time, char *to);
+
 C_MODE_END
 
 #endif /* _my_time_h_ */
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index deb09c856eceaaf5ef8de8efc99267a9f00c3c17..5dc5379e180513f211f7a2149996d09c3b5b4b55 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -3231,12 +3231,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
     tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
 
     tm->year= tm->month= 0;
-    tm->time_type= MYSQL_TIMESTAMP_TIME;
 
     *pos+= length;
   }
   else
     set_zero_time(tm);
+  tm->time_type= MYSQL_TIMESTAMP_TIME;
 }
 
 static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
@@ -3261,12 +3261,12 @@ static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
     else
       tm->hour= tm->minute= tm->second= 0;
     tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
-    tm->time_type= MYSQL_TIMESTAMP_DATETIME;
 
     *pos+= length;
   }
   else
     set_zero_time(tm);
+  tm->time_type= MYSQL_TIMESTAMP_DATETIME;
 }
 
 static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
@@ -3283,12 +3283,12 @@ static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
     tm->hour= tm->minute= tm->second= 0;
     tm->second_part= 0;
     tm->neg= 0;
-    tm->time_type= MYSQL_TIMESTAMP_DATE;
 
     *pos+= length;
   }
   else
     set_zero_time(tm);
+  tm->time_type= MYSQL_TIMESTAMP_DATE;
 }
 
 
@@ -3566,28 +3566,8 @@ static void fetch_datetime_with_conversion(MYSQL_BIND *param,
       Convert time value  to string and delegate the rest to
       fetch_string_with_conversion:
     */
-    char buff[25];
-    uint length;
-
-    switch (time->time_type) {
-    case MYSQL_TIMESTAMP_DATE:
-      length= my_sprintf(buff,(buff, "%04d-%02d-%02d",
-                               time->year, time->month, time->day));
-      break;
-    case MYSQL_TIMESTAMP_DATETIME:
-      length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
-                               time->year, time->month, time->day,
-                               time->hour, time->minute, time->second));
-      break;
-    case MYSQL_TIMESTAMP_TIME:
-      length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
-                                time->hour, time->minute, time->second));
-      break;
-    default:
-      length= 0;
-      buff[0]='\0';
-      break;
-    }
+    char buff[MAX_DATE_STRING_REP_LENGTH];
+    uint length= my_TIME_to_str(time, buff);
     /* Resort to string conversion */
     fetch_string_with_conversion(param, (char *)buff, length);
     break;
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 4b5daf53bea5aeee24c2c4391b33c9fc609dc851..93549f7340c05f10c7e23c6a597e3378a3f34ef2 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -726,3 +726,75 @@ void set_zero_time(MYSQL_TIME *tm)
   tm->time_type= MYSQL_TIMESTAMP_NONE;
 }
 
+
+/*
+  Functions to convert time/date/datetime value to a string,
+  using default format.
+  This functions don't check that given TIME structure members are
+  in valid range. If they are not, return value won't reflect any
+  valid date either. Additionally, make_time doesn't take into
+  account time->day member: it's assumed that days have been converted
+  to hours already.
+
+  RETURN
+    number of characters written to 'to'
+*/
+
+int my_time_to_str(const MYSQL_TIME *l_time, char *to)
+{
+  return my_sprintf(to, (to, "%s%02d:%02d:%02d",
+                         (l_time->neg ? "-" : ""),
+                         l_time->hour,
+                         l_time->minute,
+                         l_time->second));
+}
+
+int my_date_to_str(const MYSQL_TIME *l_time, char *to)
+{
+  return my_sprintf(to, (to, "%04d-%02d-%02d",
+                         l_time->year,
+                         l_time->month,
+                         l_time->day));
+}
+
+int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
+{
+  return my_sprintf(to, (to, "%04d-%02d-%02d %02d:%02d:%02d",
+                         l_time->year,
+                         l_time->month,
+                         l_time->day,
+                         l_time->hour,
+                         l_time->minute,
+                         l_time->second));
+}
+
+
+/*
+  Convert struct DATE/TIME/DATETIME value to string using built-in
+  MySQL time conversion formats.
+
+  SYNOPSIS
+    my_TIME_to_string()
+
+  NOTE
+    The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
+*/
+
+int my_TIME_to_str(const MYSQL_TIME *l_time, char *to)
+{
+  switch (l_time->time_type) {
+  case MYSQL_TIMESTAMP_DATETIME:
+    return my_datetime_to_str(l_time, to);
+  case MYSQL_TIMESTAMP_DATE:
+    return my_date_to_str(l_time, to);
+  case MYSQL_TIMESTAMP_TIME:
+    return my_time_to_str(l_time, to);
+  case MYSQL_TIMESTAMP_NONE:
+  case MYSQL_TIMESTAMP_ERROR:
+    to[0]='\0';
+    return 0;
+  default:
+    DBUG_ASSERT(0);
+    return 0;
+  }
+}
diff --git a/sql/field.cc b/sql/field.cc
index e7e8ec736effd11242b1985ca20f8fc7e88e8b05..aae507cd0ecd481187519e40005169b0a2e89be8 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -452,11 +452,9 @@ bool Field::get_time(TIME *ltime)
 
 void Field::store_time(TIME *ltime,timestamp_type type)
 {
-  char buff[MAX_DATE_REP_LENGTH];
-  String tmp;
-  tmp.set(buff, sizeof(buff), &my_charset_bin);
-  TIME_to_string(ltime, &tmp);
-  store(buff, tmp.length(), &my_charset_bin);
+  char buff[MAX_DATE_STRING_REP_LENGTH];
+  uint length= (uint) my_TIME_to_str(ltime, buff);
+  store(buff, length, &my_charset_bin);
 }
 
 
diff --git a/sql/item.cc b/sql/item.cc
index b37d0aed1aeee141ff7ef4a3576661a710935844..58143f52aff28d2192b572b457e174427b39519d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -988,9 +988,10 @@ String *Item_param::val_str(String* str)
     return str;
   case TIME_VALUE:
   {
-    if (str->reserve(MAX_DATE_REP_LENGTH))
+    if (str->reserve(MAX_DATE_STRING_REP_LENGTH))
       break;
-    TIME_to_string(&value.time, str);
+    str->length((uint) my_TIME_to_str(&value.time, (char*) str->ptr()));
+    str->set_charset(&my_charset_bin);
     return str;
   }
   case NULL_VALUE:
@@ -1020,24 +1021,19 @@ const String *Item_param::query_val_str(String* str) const
   case TIME_VALUE:
     {
       char *buf, *ptr;
-      String tmp;
       str->length(0);
       /*
         TODO: in case of error we need to notify replication
         that binary log contains wrong statement 
       */
-      if (str->reserve(MAX_DATE_REP_LENGTH+3))
+      if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
         break; 
 
       /* Create date string inplace */
       buf= str->c_ptr_quick();
       ptr= buf;
       *ptr++= '\'';
-      tmp.set(ptr, MAX_DATE_REP_LENGTH, &my_charset_bin);
-      tmp.length(0);
-      TIME_to_string(&value.time, &tmp);
-
-      ptr+= tmp.length();
+      ptr+= (uint) my_TIME_to_str(&value.time, ptr);
       *ptr++= '\'';
       str->length((uint32) (ptr - buf));
       break;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 863b041044e917e4df41728f535a4a8ceae0d605..48c1f2c54437770c599212c139f32a467b23074e 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1292,14 +1292,13 @@ String *Item_func_curtime::val_str(String *str)
 void Item_func_curtime::fix_length_and_dec()
 {
   TIME ltime;
-  String tmp((char*) buff,sizeof(buff), &my_charset_bin);
 
   decimals=0;
   collation.set(&my_charset_bin);
   store_now_in_TIME(&ltime);
   value= TIME_to_ulonglong_time(&ltime);
-  make_time((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
-  max_length= buff_length= tmp.length();
+  buff_length= (uint) my_time_to_str(&ltime, buff);
+  max_length= buff_length;
 }
 
 
@@ -1341,16 +1340,14 @@ String *Item_func_now::val_str(String *str)
 
 void Item_func_now::fix_length_and_dec()
 {
-  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
-
   decimals=0;
   collation.set(&my_charset_bin);
 
   store_now_in_TIME(&ltime);
   value= (longlong) TIME_to_ulonglong_datetime(&ltime);
 
-  make_datetime((DATE_TIME_FORMAT *) 0, &ltime, &tmp);
-  max_length= buff_length= tmp.length();
+  buff_length= (uint) my_datetime_to_str(&ltime, buff);
+  max_length= buff_length;
 }
 
 
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e94d436b1355658e36ca4bd1b656abf8ee797554..e0db5e88c952fb5dea753bf1a5b7cb657d51b40c 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -284,14 +284,6 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
 #define WEEK_MONDAY_FIRST    1
 #define WEEK_YEAR            2
 #define WEEK_FIRST_WEEKDAY   4
-/*
-  Required buffer length for make_date, make_time, make_datetime
-  and TIME_to_string functions. Note, that the caller is still
-  responsible to check that given TIME structure has values
-  in valid ranges, otherwise size of the buffer could be not 
-  enough.
-*/
-#define MAX_DATE_REP_LENGTH 30
 
 enum enum_parsing_place
 {
@@ -1046,7 +1038,6 @@ void make_date(const DATE_TIME_FORMAT *format, const TIME *l_time,
                String *str);
 void make_time(const DATE_TIME_FORMAT *format, const TIME *l_time,
                String *str);
-void TIME_to_string(const TIME *time, String *str);
 ulonglong TIME_to_ulonglong_datetime(const TIME *time);
 ulonglong TIME_to_ulonglong_date(const TIME *time);
 ulonglong TIME_to_ulonglong_time(const TIME *time);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index c2d9117b062a73a909be2c3a927caedab96a9824..060dc14be10de4b88836229e3d00b1efad00e4ec 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -880,10 +880,9 @@ bool Protocol_simple::store_date(TIME *tm)
 	      field_types[field_pos] == MYSQL_TYPE_DATE);
   field_pos++;
 #endif
-  char buff[40];
-  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
-  make_date((DATE_TIME_FORMAT *) 0, tm, &tmp);
-  return net_store_data((char*) tmp.ptr(), tmp.length());
+  char buff[MAX_DATE_STRING_REP_LENGTH];
+  int length= my_date_to_str(tm, buff);
+  return net_store_data(buff, (uint) length);
 }
 
 
diff --git a/sql/time.cc b/sql/time.cc
index 4421b6aa00ffda67a2ebd3d94125b8405686370b..e76b169b3360bdba2da41b5c861f75883ebcb824 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -747,13 +747,7 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
 void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
                const TIME *l_time, String *str)
 {
-  long length= my_sprintf((char*) str->ptr(),
-			  ((char*) str->ptr(),
-			   "%s%02d:%02d:%02d",
-			   (l_time->neg ? "-" : ""),
-			   l_time->hour,
-			   l_time->minute,
-			   l_time->second));
+  uint length= (uint) my_time_to_str(l_time, (char*) str->ptr());
   str->length(length);
   str->set_charset(&my_charset_bin);
 }
@@ -762,12 +756,7 @@ void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
 void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
                const TIME *l_time, String *str)
 {
-  long length= my_sprintf((char*) str->ptr(),
-			  ((char*) str->ptr(),
-			   "%04d-%02d-%02d",
-			   l_time->year,
-			   l_time->month,
-			   l_time->day));
+  uint length= (uint) my_date_to_str(l_time, (char*) str->ptr());
   str->length(length);
   str->set_charset(&my_charset_bin);
 }
@@ -776,15 +765,7 @@ void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
 void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
                    const TIME *l_time, String *str)
 {
-  long length= my_sprintf((char*) str->ptr(),
-			  ((char*) str->ptr(),
-			   "%04d-%02d-%02d %02d:%02d:%02d",
-			   l_time->year,
-			   l_time->month,
-			   l_time->day,
-			   l_time->hour,
-			   l_time->minute,
-			   l_time->second));
+  uint length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
   str->length(length);
   str->set_charset(&my_charset_bin);
 }
@@ -894,38 +875,4 @@ ulonglong TIME_to_ulonglong(const TIME *time)
   return 0;
 }
 
-
-/*
-  Convert struct DATE/TIME/DATETIME value to string using built-in
-  MySQL time conversion formats.
-
-  SYNOPSIS
-    TIME_to_string()
-
-  NOTE 
-    The string must have at least MAX_DATE_REP_LENGTH bytes reserved.
-*/
-
-void TIME_to_string(const TIME *time, String *str)
-{
-  switch (time->time_type) {
-  case MYSQL_TIMESTAMP_DATETIME:
-    make_datetime((DATE_TIME_FORMAT*) 0, time, str);
-    break;
-  case MYSQL_TIMESTAMP_DATE:
-    make_date((DATE_TIME_FORMAT*) 0, time, str);
-    break;
-  case MYSQL_TIMESTAMP_TIME:
-    make_time((DATE_TIME_FORMAT*) 0, time, str);
-    break;
-  case MYSQL_TIMESTAMP_NONE:
-  case MYSQL_TIMESTAMP_ERROR:
-    str->length(0);
-    str->set_charset(&my_charset_bin);
-    break;
-  default:
-    DBUG_ASSERT(0);
-  }
-}
-
 #endif
diff --git a/tests/client_test.c b/tests/client_test.c
index eb97c0ce949b263862a9e0bac13509e0cbf6a9c1..8721285ec3f5dba79aacc97056a14e9d5625c769 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -3431,7 +3431,7 @@ static void test_fetch_date()
   MYSQL_STMT *stmt;
   uint       i;
   int        rc, year;
-  char       date[25], time[25], ts[25], ts_4[15], ts_6[20], dt[20];
+  char       date[25], time[25], ts[25], ts_4[25], ts_6[20], dt[20];
   ulong      d_length, t_length, ts_length, ts4_length, ts6_length,
              dt_length, y_length;
   MYSQL_BIND bind[8];
@@ -3541,8 +3541,8 @@ static void test_fetch_date()
   DIE_UNLESS(strcmp(dt, "2010-07-10 00:00:00") == 0);
   DIE_UNLESS(dt_length == 19);
 
-  DIE_UNLESS(ts_4[0] == '\0');
-  DIE_UNLESS(ts4_length == 0);
+  DIE_UNLESS(strcmp(ts_4, "0000-00-00 00:00:00") == 0);
+  DIE_UNLESS(ts4_length == strlen("0000-00-00 00:00:00"));
 
   DIE_UNLESS(strcmp(ts_6, "1999-12-29 00:00:00") == 0);
   DIE_UNLESS(ts6_length == 19);
@@ -10533,6 +10533,99 @@ static void test_bug5315()
 }
 
 
+static void test_bug6049()
+{
+  MYSQL_STMT *stmt;
+  MYSQL_BIND bind[1];
+  MYSQL_RES *res;
+  MYSQL_ROW row;
+  const char *stmt_text;
+  char buffer[30];
+  ulong length;
+  int rc;
+
+  myheader("test_bug6049");
+
+  stmt_text= "SELECT MAKETIME(-25, 12, 12)";
+
+  rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+  myquery(rc);
+  res= mysql_store_result(mysql);
+  row= mysql_fetch_row(res);
+
+  stmt= mysql_stmt_init(mysql);
+  rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+  check_execute(stmt, rc);
+  rc= mysql_stmt_execute(stmt);
+  check_execute(stmt, rc);
+
+  bzero(bind, sizeof(bind));
+  bind[0].buffer_type    = MYSQL_TYPE_STRING;
+  bind[0].buffer         = &buffer;
+  bind[0].buffer_length  = sizeof(buffer);
+  bind[0].length         = &length;
+
+  mysql_stmt_bind_result(stmt, bind);
+  rc= mysql_stmt_fetch(stmt);
+  DIE_UNLESS(rc == 0);
+
+  printf("Result from query: %s\n", row[0]);
+  printf("Result from prepared statement: %s\n", (char*) buffer);
+
+  DIE_UNLESS(strcmp(row[0], (char*) buffer) == 0);
+
+  mysql_free_result(res);
+  mysql_stmt_close(stmt);
+}
+
+
+static void test_bug6058()
+{
+  MYSQL_STMT *stmt;
+  MYSQL_BIND bind[1];
+  MYSQL_RES *res;
+  MYSQL_ROW row;
+  const char *stmt_text;
+  char buffer[30];
+  ulong length;
+  int rc;
+
+  myheader("test_bug6058");
+
+  stmt_text= "SELECT CAST('0000-00-00' AS DATE)";
+
+  rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+  myquery(rc);
+  res= mysql_store_result(mysql);
+  row= mysql_fetch_row(res);
+
+  stmt= mysql_stmt_init(mysql);
+  rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+  check_execute(stmt, rc);
+  rc= mysql_stmt_execute(stmt);
+  check_execute(stmt, rc);
+
+  bzero(bind, sizeof(bind));
+  bind[0].buffer_type    = MYSQL_TYPE_STRING;
+  bind[0].buffer         = &buffer;
+  bind[0].buffer_length  = sizeof(buffer);
+  bind[0].length         = &length;
+
+  mysql_stmt_bind_result(stmt, bind);
+  rc= mysql_stmt_fetch(stmt);
+  DIE_UNLESS(rc == 0);
+
+  printf("Result from query: %s\n", row[0]);
+  printf("Result from prepared statement: %s\n", buffer);
+
+  DIE_UNLESS(strcmp(row[0], buffer) == 0);
+
+  mysql_free_result(res);
+  mysql_stmt_close(stmt);
+}
+
+
+
 /*
   Read and parse arguments and MySQL options from my.cnf
 */
@@ -10843,6 +10936,8 @@ int main(int argc, char **argv)
     test_bug5194();         /* bulk inserts in prepared mode */
     test_bug5315();         /* check that mysql_change_user closes all
                                prepared statements */
+    test_bug6049();         /* check support for negative TIME values */
+    test_bug6058();         /* check support for 0000-00-00 dates */
     /*
       XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
       DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.