diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 524ff48d69edc507c365171ec8665b641ad62aae..88601eceb0a74c049cd948dfdf9559c653ddcd3e 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -414,4 +414,28 @@ NULL
 NULL
 20070719
 drop table t1;
+CREATE TABLE t1 (f1 DATE);
+INSERT INTO t1 VALUES ('2007-07-19'), (NULL);
+SELECT HOUR(f1),
+MINUTE(f1),
+SECOND(f1) FROM t1;
+HOUR(f1)	MINUTE(f1)	SECOND(f1)
+0	0	0
+NULL	NULL	NULL
+SELECT HOUR(CAST('2007-07-19' AS DATE)),
+MINUTE(CAST('2007-07-19' AS DATE)),
+SECOND(CAST('2007-07-19' AS DATE));
+HOUR(CAST('2007-07-19' AS DATE))	MINUTE(CAST('2007-07-19' AS DATE))	SECOND(CAST('2007-07-19' AS DATE))
+0	0	0
+SELECT HOUR(CAST(NULL AS DATE)),
+MINUTE(CAST(NULL AS DATE)),
+SECOND(CAST(NULL AS DATE));
+HOUR(CAST(NULL AS DATE))	MINUTE(CAST(NULL AS DATE))	SECOND(CAST(NULL AS DATE))
+NULL	NULL	NULL
+SELECT HOUR(NULL),
+MINUTE(NULL),
+SECOND(NULL);
+HOUR(NULL)	MINUTE(NULL)	SECOND(NULL)
+NULL	NULL	NULL
+DROP TABLE t1;
 End of 5.0 tests
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index bd2a43569ddd5b842ca9dd010de7bd944583e3b2..f16b873f37b4bc6044ba07896e99b26db01b5475 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -214,4 +214,9 @@ INSERT INTO t1 VALUES ('0000-00-00');
 ERROR 22007: Incorrect date value: '0000-00-00' for column 'a' at row 1
 SET SQL_MODE=DEFAULT;
 DROP TABLE t1,t2;
+CREATE TABLE t1 SELECT curdate() AS f1;
+SELECT hour(f1), minute(f1), second(f1) FROM t1;
+hour(f1)	minute(f1)	second(f1)
+0	0	0
+DROP TABLE t1;
 End of 5.0 tests
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index 316b79efe4d975820699d1b966f21ddc62d08ca1..df475b49746837c73b813cdb25da81314c648116 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -246,4 +246,26 @@ INSERT INTO t1(d1) VALUES ('2007-07-19 08:30:00'), (NULL),
 SELECT cast(date(d1) as signed) FROM t1;
 drop table t1;
 
+#
+# Bug #31990: MINUTE() and SECOND() return bogus results when used on a DATE
+#
+
+# Show that HH:MM:SS of a DATE are 0, and that it's the same for columns
+# and typecasts (NULL in, NULL out).
+CREATE TABLE t1 (f1 DATE);
+INSERT INTO t1 VALUES ('2007-07-19'), (NULL);
+SELECT HOUR(f1),
+       MINUTE(f1),
+       SECOND(f1) FROM t1;
+SELECT HOUR(CAST('2007-07-19' AS DATE)),
+       MINUTE(CAST('2007-07-19' AS DATE)),
+       SECOND(CAST('2007-07-19' AS DATE));
+SELECT HOUR(CAST(NULL AS DATE)),
+       MINUTE(CAST(NULL AS DATE)),
+       SECOND(CAST(NULL AS DATE));
+SELECT HOUR(NULL),
+       MINUTE(NULL),
+       SECOND(NULL);
+DROP TABLE t1;
+
 --echo End of 5.0 tests
diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test
index 507537457d3a84dfdb759fa05167eb9ac219c3e0..3f2ee4234bd2bb529fe3e0367a14dd56b9253bb1 100644
--- a/mysql-test/t/type_date.test
+++ b/mysql-test/t/type_date.test
@@ -190,4 +190,12 @@ INSERT INTO t1 VALUES ('0000-00-00');
 SET SQL_MODE=DEFAULT;
 DROP TABLE t1,t2;
 
+#
+# Bug #31990: MINUTE() and SECOND() return bogus results when used on a DATE
+#
+
+CREATE TABLE t1 SELECT curdate() AS f1;
+SELECT hour(f1), minute(f1), second(f1) FROM t1;
+DROP TABLE t1;
+
 --echo End of 5.0 tests
diff --git a/sql/field.cc b/sql/field.cc
index 86853389c6496b161cc6b6fb76c7826fdc820757..db438c7c4d0f1ea6852f2ba67da12922b4a12548 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5194,6 +5194,13 @@ String *Field_date::val_str(String *val_buffer,
 }
 
 
+bool Field_date::get_time(MYSQL_TIME *ltime)
+{
+  bzero((char *)ltime, sizeof(MYSQL_TIME));
+  return 0;
+}
+
+
 int Field_date::cmp(const char *a_ptr, const char *b_ptr)
 {
   int32 a,b;
diff --git a/sql/field.h b/sql/field.h
index 8c01931fa21d6686ce0ac7e134e37c0e548812fb..8ae39f78558ee3b5333e28a7d4e319035ef47ac5 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -933,6 +933,7 @@ public:
   double val_real(void);
   longlong val_int(void);
   String *val_str(String*,String *);
+  bool get_time(MYSQL_TIME *ltime);
   bool send_binary(Protocol *protocol);
   int cmp(const char *,const char*);
   void sort_string(char *buff,uint length);
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index c1fa9dce0385a08bb92eaad92bd134ed0ba9d1e5..7ed5e375f5b065cb29f508b91baeb2b0f2d104b6 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2645,6 +2645,13 @@ bool Item_date_typecast::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
 }
 
 
+bool Item_date_typecast::get_time(MYSQL_TIME *ltime)
+{
+  bzero((char *)ltime, sizeof(MYSQL_TIME));
+  return args[0]->null_value;
+}
+
+
 String *Item_date_typecast::val_str(String *str)
 {
   DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index a5ecbc57e8da4a03b3ecd3c705244d3717fafb5e..b647e93b7003f0eec901c38672ab9d739ec17bd1 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -779,6 +779,7 @@ public:
   const char *func_name() const { return "cast_as_date"; }
   String *val_str(String *str);
   bool get_date(MYSQL_TIME *ltime, uint fuzzy_date);
+  bool get_time(MYSQL_TIME *ltime);
   const char *cast_type() const { return "date"; }
   enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
   Field *tmp_table_field(TABLE *t_arg)