diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
index 4b49ebfdcb..5bd3419fe8 100644
--- a/src/wp-includes/rest-api.php
+++ b/src/wp-includes/rest-api.php
@@ -1144,6 +1144,20 @@ function rest_get_avatar_sizes() {
  * @return true|WP_Error
  */
 function rest_validate_value_from_schema( $value, $args, $param = '' ) {
+	if ( is_array( $args['type'] ) ) {
+		foreach ( $args['type'] as $type ) {
+			$type_args         = $args;
+			$type_args['type'] = $type;
+
+			if ( true === rest_validate_value_from_schema( $value, $type_args, $param ) ) {
+				return true;
+			}
+		}
+
+		/* translators: 1: Parameter, 2: List of types. */
+		return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s' ), $param, implode( ',', $args['type'] ) ) );
+	}
+
 	if ( 'array' === $args['type'] ) {
 		if ( ! is_null( $value ) ) {
 			$value = wp_parse_list( $value );
@@ -1196,6 +1210,15 @@ function rest_validate_value_from_schema( $value, $args, $param = '' ) {
 		}
 	}
 
+	if ( 'null' === $args['type'] ) {
+		if ( null !== $value ) {
+			/* translators: 1: Parameter, 2: Type name. */
+			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'null' ) );
+		}
+
+		return true;
+	}
+
 	if ( ! empty( $args['enum'] ) ) {
 		if ( ! in_array( $value, $args['enum'], true ) ) {
 			/* translators: 1: Parameter, 2: List of valid values. */
@@ -1300,6 +1323,27 @@ function rest_validate_value_from_schema( $value, $args, $param = '' ) {
  * @return true|WP_Error
  */
 function rest_sanitize_value_from_schema( $value, $args ) {
+	if ( is_array( $args['type'] ) ) {
+		// Determine which type the value was validated against, and use that type when performing sanitization
+		$validated_type = '';
+
+		foreach ( $args['type'] as $type ) {
+			$type_args         = $args;
+			$type_args['type'] = $type;
+
+			if ( ! is_wp_error( rest_validate_value_from_schema( $value, $type_args ) ) ) {
+				$validated_type = $type;
+				break;
+			}
+		}
+
+		if ( ! $validated_type ) {
+			return null;
+		}
+
+		$args['type'] = $validated_type;
+	}
+
 	if ( 'array' === $args['type'] ) {
 		if ( empty( $args['items'] ) ) {
 			return (array) $value;
@@ -1342,6 +1386,10 @@ function rest_sanitize_value_from_schema( $value, $args ) {
 		return $value;
 	}
 
+	if ( 'null' === $args['type'] ) {
+		return null;
+	}
+
 	if ( 'integer' === $args['type'] ) {
 		return (int) $value;
 	}
diff --git a/src/wp-includes/rest-api/class-wp-rest-request.php b/src/wp-includes/rest-api/class-wp-rest-request.php
index 7b2a32e618..3c67b6ad2a 100644
--- a/src/wp-includes/rest-api/class-wp-rest-request.php
+++ b/src/wp-includes/rest-api/class-wp-rest-request.php
@@ -397,6 +397,30 @@ class WP_REST_Request implements ArrayAccess {
 		return null;
 	}
 
+	/**
+	 * Checks if a parameter exists in the request.
+	 *
+	 * This allows distinguishing between an omitted parameter,
+	 * and a parameter specifically set to null.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param string $key Parameter name.
+	 *
+	 * @return bool True if a param exists for the given key.
+	 */
+	public function has_param( $key ) {
+		$order = $this->get_parameter_order();
+
+		foreach ( $order as $type ) {
+			if ( array_key_exists( $key, $this->params[ $type ] ) ) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
 	/**
 	 * Sets a parameter on the request.
 	 *
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
index e53ff4b910..c0304de164 100644
--- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
@@ -1036,6 +1036,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 			}
 		}
 
+		// Sending a null date or date_gmt value resets date and date_gmt to their
+		// default values (`0000-00-00 00:00:00`).
+		if (
+			( ! empty( $schema['properties']['date_gmt'] ) && $request->has_param( 'date_gmt' ) && null === $request['date_gmt'] ) ||
+			( ! empty( $schema['properties']['date'] ) && $request->has_param( 'date' ) && null === $request['date'] )
+		) {
+			$prepared_post->post_date_gmt = null;
+			$prepared_post->post_date     = null;
+		}
+
 		// Post slug.
 		if ( ! empty( $schema['properties']['slug'] ) && isset( $request['slug'] ) ) {
 			$prepared_post->post_name = $request['slug'];
@@ -1881,13 +1891,13 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 			'properties' => array(
 				'date'         => array(
 					'description' => __( "The date the object was published, in the site's timezone." ),
-					'type'        => 'string',
+					'type'        => array( 'string', 'null' ),
 					'format'      => 'date-time',
 					'context'     => array( 'view', 'edit', 'embed' ),
 				),
 				'date_gmt'     => array(
 					'description' => __( 'The date the object was published, as GMT.' ),
-					'type'        => 'string',
+					'type'        => array( 'string', 'null' ),
 					'format'      => 'date-time',
 					'context'     => array( 'view', 'edit' ),
 				),
diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php
index ba174c448e..9d0a97f324 100644
--- a/tests/phpunit/tests/rest-api/rest-posts-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php
@@ -2555,6 +2555,66 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 		$this->assertEquals( $params['excerpt'], $post->post_excerpt );
 	}
 
+	/**
+	 * Verify that updating a post with a `null` date or date_gmt results in a reset post, where all
+	 * date values are equal (date, date_gmt, date_modified and date_modofied_gmt) in the API response.
+	 * In the database, the post_date_gmt field is reset to the default `0000-00-00 00:00:00`.
+	 *
+	 * @ticket 44975
+	 */
+	public function test_rest_update_post_with_empty_date() {
+		// Create a new test post.
+		$post_id = $this->factory->post->create();
+		wp_set_current_user( self::$editor_id );
+
+		// Set the post date to the future.
+		$future_date = '2919-07-29T18:00:00';
+		$request     = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) );
+		$request->add_header( 'content-type', 'application/json' );
+		$params = $this->set_post_data(
+			array(
+				'date_gmt' => $future_date,
+				'date'     => $future_date,
+				'title'    => 'update',
+				'status'   => 'draft',
+			)
+		);
+		$request->set_body( wp_json_encode( $params ) );
+		$response = rest_get_server()->dispatch( $request );
+		$this->check_update_post_response( $response );
+		$new_data = $response->get_data();
+
+		// Verify the post is set to the future date.
+		$this->assertEquals( $new_data['date_gmt'], $future_date );
+		$this->assertEquals( $new_data['date'], $future_date );
+		$this->assertNotEquals( $new_data['date_gmt'], $new_data['modified_gmt'] );
+		$this->assertNotEquals( $new_data['date'], $new_data['modified'] );
+
+		// Update post with a blank field (date or date_gmt).
+		$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) );
+		$request->add_header( 'content-type', 'application/json' );
+		$params = $this->set_post_data(
+			array(
+				'date_gmt' => null,
+				'title'    => 'test',
+				'status'   => 'draft',
+			)
+		);
+		$request->set_body( wp_json_encode( $params ) );
+		$response = rest_get_server()->dispatch( $request );
+
+		// Verify the date field values are reset in the API response.
+		$this->check_update_post_response( $response );
+		$new_data = $response->get_data();
+		$this->assertEquals( $new_data['date_gmt'], $new_data['date'] );
+		$this->assertNotEquals( $new_data['date_gmt'], $future_date );
+
+		$post = get_post( $post_id, 'ARRAY_A' );
+		$this->assertEquals( $post['post_date_gmt'], '0000-00-00 00:00:00' );
+		$this->assertNotEquals( $new_data['date_gmt'], $future_date );
+		$this->assertNotEquals( $new_data['date'], $future_date );
+	}
+
 	public function test_rest_update_post_raw() {
 		wp_set_current_user( self::$editor_id );
 
diff --git a/tests/phpunit/tests/rest-api/rest-schema-sanitization.php b/tests/phpunit/tests/rest-api/rest-schema-sanitization.php
index 4f9f2c9242..1b2fd1d90c 100644
--- a/tests/phpunit/tests/rest-api/rest-schema-sanitization.php
+++ b/tests/phpunit/tests/rest-api/rest-schema-sanitization.php
@@ -292,4 +292,59 @@ class WP_Test_REST_Schema_Sanitization extends WP_UnitTestCase {
 		$this->assertEquals( 1.10, rest_sanitize_value_from_schema( 1.10, $schema ) );
 		$this->assertEquals( 1, rest_sanitize_value_from_schema( 1, $schema ) );
 	}
+
+	public function test_nullable_date() {
+		$schema = array(
+			'type'   => array( 'string', 'null' ),
+			'format' => 'date-time',
+		);
+
+		$this->assertNull( rest_sanitize_value_from_schema( null, $schema ) );
+		$this->assertEquals( '2019-09-19T18:00:00', rest_sanitize_value_from_schema( '2019-09-19T18:00:00', $schema ) );
+		$this->assertNull( rest_sanitize_value_from_schema( 'lalala', $schema ) );
+	}
+
+	public function test_object_or_string() {
+		$schema = array(
+			'type'       => array( 'object', 'string' ),
+			'properties' => array(
+				'raw' => array(
+					'type' => 'string',
+				),
+			),
+		);
+
+		$this->assertEquals( 'My Value', rest_sanitize_value_from_schema( 'My Value', $schema ) );
+		$this->assertEquals( array( 'raw' => 'My Value' ), rest_sanitize_value_from_schema( array( 'raw' => 'My Value' ), $schema ) );
+		$this->assertNull( rest_sanitize_value_from_schema( array( 'raw' => 1 ), $schema ) );
+	}
+
+	public function test_object_or_bool() {
+		$schema = array(
+			'type'       => array( 'object', 'boolean' ),
+			'properties' => array(
+				'raw' => array(
+					'type' => 'boolean',
+				),
+			),
+		);
+
+		$this->assertTrue( rest_sanitize_value_from_schema( true, $schema ) );
+		$this->assertTrue( rest_sanitize_value_from_schema( '1', $schema ) );
+		$this->assertTrue( rest_sanitize_value_from_schema( 1, $schema ) );
+
+		$this->assertFalse( rest_sanitize_value_from_schema( false, $schema ) );
+		$this->assertFalse( rest_sanitize_value_from_schema( '0', $schema ) );
+		$this->assertFalse( rest_sanitize_value_from_schema( 0, $schema ) );
+
+		$this->assertEquals( array( 'raw' => true ), rest_sanitize_value_from_schema( array( 'raw' => true ), $schema ) );
+		$this->assertEquals( array( 'raw' => true ), rest_sanitize_value_from_schema( array( 'raw' => '1' ), $schema ) );
+		$this->assertEquals( array( 'raw' => true ), rest_sanitize_value_from_schema( array( 'raw' => 1 ), $schema ) );
+
+		$this->assertEquals( array( 'raw' => false ), rest_sanitize_value_from_schema( array( 'raw' => false ), $schema ) );
+		$this->assertEquals( array( 'raw' => false ), rest_sanitize_value_from_schema( array( 'raw' => '0' ), $schema ) );
+		$this->assertEquals( array( 'raw' => false ), rest_sanitize_value_from_schema( array( 'raw' => 0 ), $schema ) );
+
+		$this->assertNull( rest_sanitize_value_from_schema( array( 'raw' => 'something non boolean' ), $schema ) );
+	}
 }
diff --git a/tests/phpunit/tests/rest-api/rest-schema-validation.php b/tests/phpunit/tests/rest-api/rest-schema-validation.php
index df16a894ad..9c18a846dc 100644
--- a/tests/phpunit/tests/rest-api/rest-schema-validation.php
+++ b/tests/phpunit/tests/rest-api/rest-schema-validation.php
@@ -296,4 +296,36 @@ class WP_Test_REST_Schema_Validation extends WP_UnitTestCase {
 		$this->assertTrue( rest_validate_value_from_schema( 1, $schema ) );
 		$this->assertTrue( rest_validate_value_from_schema( array(), $schema ) );
 	}
+
+	public function test_type_null() {
+		$this->assertTrue( rest_validate_value_from_schema( null, array( 'type' => 'null' ) ) );
+		$this->assertWPError( rest_validate_value_from_schema( '', array( 'type' => 'null' ) ) );
+		$this->assertWPError( rest_validate_value_from_schema( 'null', array( 'type' => 'null' ) ) );
+	}
+
+	public function test_nullable_date() {
+		$schema = array(
+			'type'   => array( 'string', 'null' ),
+			'format' => 'date-time',
+		);
+
+		$this->assertTrue( rest_validate_value_from_schema( null, $schema ) );
+		$this->assertTrue( rest_validate_value_from_schema( '2019-09-19T18:00:00', $schema ) );
+		$this->assertWPError( rest_validate_value_from_schema( 'some random string', $schema ) );
+	}
+
+	public function test_object_or_string() {
+		$schema = array(
+			'type'       => array( 'object', 'string' ),
+			'properties' => array(
+				'raw' => array(
+					'type' => 'string',
+				),
+			),
+		);
+
+		$this->assertTrue( rest_validate_value_from_schema( 'My Value', $schema ) );
+		$this->assertTrue( rest_validate_value_from_schema( array( 'raw' => 'My Value' ), $schema ) );
+		$this->assertWPError( rest_validate_value_from_schema( array( 'raw' => array( 'a list' ) ), $schema ) );
+	}
 }
diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js
index 47f925fe44..fdbf056589 100644
--- a/tests/qunit/fixtures/wp-api-generated.js
+++ b/tests/qunit/fixtures/wp-api-generated.js
@@ -373,12 +373,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -553,12 +559,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -893,12 +905,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -1238,12 +1256,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -1390,12 +1414,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -1702,12 +1732,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -2015,12 +2051,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -2152,12 +2194,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -2399,12 +2447,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -2503,12 +2557,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
@@ -2612,12 +2672,18 @@ mockedApiResponse.Schema = {
                         "date": {
                             "required": false,
                             "description": "The date the object was published, in the site's timezone.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "date_gmt": {
                             "required": false,
                             "description": "The date the object was published, as GMT.",
-                            "type": "string"
+                            "type": [
+                                "string",
+                                "null"
+                            ]
                         },
                         "slug": {
                             "required": false,
