Commit 1d9de854795 for woocommerce

commit 1d9de8547954e03fda251e7015f5c6ab56b1c063
Author: Jorge A. Torres <jorge.torres@automattic.com>
Date:   Wed Sep 23 23:18:28 2026 +0100

    Revert "Fix HPOS migration leaving orders without a created date when post_date_gmt is zero" (#68772) (#69025)

diff --git a/plugins/woocommerce/changelog/fix-hpos-migration-zero-gmt-dates b/plugins/woocommerce/changelog/fix-hpos-migration-zero-gmt-dates
deleted file mode 100644
index 0163552b161..00000000000
--- a/plugins/woocommerce/changelog/fix-hpos-migration-zero-gmt-dates
+++ /dev/null
@@ -1,4 +0,0 @@
-Significance: patch
-Type: fix
-
-Fix orders losing their created date when migrating to HPOS from posts with an empty GMT date.
diff --git a/plugins/woocommerce/changelog/revert-fix-hpos-migration-zero-gmt-dates b/plugins/woocommerce/changelog/revert-fix-hpos-migration-zero-gmt-dates
new file mode 100644
index 00000000000..f1e01c323d0
--- /dev/null
+++ b/plugins/woocommerce/changelog/revert-fix-hpos-migration-zero-gmt-dates
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Revert PR #68772 (HPOS migration zero GMT date fix); unreleased, so no production change.
diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php
index d4b6233ce15..24ee797294b 100644
--- a/plugins/woocommerce/includes/class-wc-install.php
+++ b/plugins/woocommerce/includes/class-wc-install.php
@@ -361,7 +361,6 @@ class WC_Install {
 			'wc_update_11203_normalize_stock_notification_emails',
 		),
 		'11.3.0'   => array(
-			'wc_update_1130_repair_hpos_order_dates_from_posts',
 			'wc_update_1130_set_legacy_variation_price_hash_option',
 		),
 	);
diff --git a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
index 9b602afb4e2..03593403e73 100644
--- a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
+++ b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
@@ -153,8 +153,8 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
 			$order,
 			array(
 				'parent_id'     => $post_object->post_parent,
-				'date_created'  => $this->post_date_to_timestamp( $post_object->post_date_gmt, $post_object->post_date ),
-				'date_modified' => $this->post_date_to_timestamp( $post_object->post_modified_gmt, $post_object->post_modified ),
+				'date_created'  => $this->string_to_timestamp( $post_object->post_date_gmt ),
+				'date_modified' => $this->string_to_timestamp( $post_object->post_modified_gmt ),
 				'status'        => $post_object->post_status,
 			)
 		);
@@ -426,26 +426,6 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
 		return wc_generate_order_key();
 	}

-	/**
-	 * Convert a post's GMT datetime to a timestamp, using the local one when the GMT column holds the zero date.
-	 *
-	 * WordPress leaves the GMT columns at the zero date for some posts (drafts, imports) and treats the local
-	 * column as the truth. The HPOS migrator applies the same rule, so both stores read the same date.
-	 *
-	 * @since 11.3.0
-	 *
-	 * @param string $gmt_date   Datetime in GMT, possibly the zero date.
-	 * @param string $local_date The same datetime in the site timezone.
-	 * @return int|null
-	 */
-	protected function post_date_to_timestamp( $gmt_date, $local_date ) {
-		$timestamp = $this->string_to_timestamp( $gmt_date );
-		if ( null === $timestamp && '' !== $local_date && '0000-00-00 00:00:00' !== $local_date ) {
-			$timestamp = $this->string_to_timestamp( get_gmt_from_date( $local_date ) );
-		}
-		return $timestamp;
-	}
-
 	/**
 	 * Read order data. Can be overridden by child classes to load other props.
 	 *
@@ -1001,6 +981,8 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
 		add_filter( 'wp_insert_post_data', array( $this, 'update_post_modified_data' ), 10, 2 );
 		$post_data = array(
 			'ID'                 => $order->get_id(),
+			'post_date'          => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
+			'post_date_gmt'      => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
 			'post_status'        => $this->get_post_status( $order ),
 			'post_parent'        => $order->get_parent_id(),
 			'edit_date'          => true,
@@ -1009,13 +991,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
 			'order_modified'     => ! is_null( $order->get_date_modified() ) ? gmdate( 'Y-m-d H:i:s', $order->get_date_modified( 'edit' )->getOffsetTimestamp() ) : '',
 			'order_modified_gmt' => ! is_null( $order->get_date_modified() ) ? gmdate( 'Y-m-d H:i:s', $order->get_date_modified( 'edit' )->getTimestamp() ) : '',
 		);
-		// An order with no created date leaves the post's date columns to WordPress, which keeps them unless they are zero too.
-		$date_created = $order->get_date_created( 'edit' );
-		if ( ! is_null( $date_created ) ) {
-			$post_data['post_date']     = gmdate( 'Y-m-d H:i:s', $date_created->getOffsetTimestamp() );
-			$post_data['post_date_gmt'] = gmdate( 'Y-m-d H:i:s', $date_created->getTimestamp() );
-		}
-		$updated = wp_update_post( $post_data );
+		$updated   = wp_update_post( $post_data );
 		remove_filter( 'wp_insert_post_data', array( $this, 'update_post_modified_data' ) );
 		return $updated;
 	}
diff --git a/plugins/woocommerce/includes/wc-update-functions.php b/plugins/woocommerce/includes/wc-update-functions.php
index b7d19919e03..26c280f504a 100644
--- a/plugins/woocommerce/includes/wc-update-functions.php
+++ b/plugins/woocommerce/includes/wc-update-functions.php
@@ -4011,167 +4011,6 @@ function wc_update_11203_normalize_stock_notification_emails() {
 	return false;
 }

-/**
- * Give HPOS orders migrated without a created or updated date the dates their posts still hold.
- *
- * Earlier migrations copied a zero post_date_gmt verbatim, so the HPOS row ended up with no created date and the next
- * save stamped it with the current time. Only rows whose date is NULL or the zero date are touched, and only when the
- * order's post has a usable date. Placeholder posts count too: legacy cleanup keeps the date columns when it converts a
- * post, and placeholders created for new HPOS orders carry the order's own date. Repaired orders are dropped from the
- * order caches and queued for the Analytics import, which skipped them while they had no date. Batched, returns true
- * while rows remain.
- *
- * @return bool True to run again.
- */
-function wc_update_1130_repair_hpos_order_dates_from_posts() {
-	global $wpdb;
-
-	$orders_table = \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore::get_orders_table_name();
-	if ( $orders_table !== $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $orders_table ) ) ) {
-		return false;
-	}
-
-	$last_id_option = 'woocommerce_update_1130_last_repaired_order_id';
-	$batch_size     = 500;
-	$zero           = '0000-00-00 00:00:00';
-	$type_list      = array();
-	$post_types     = array_merge( wc_get_order_types( 'cot-migration' ), array( \Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::PLACEHOLDER_ORDER_POST_TYPE ) );
-	foreach ( $post_types as $post_type ) {
-		$escaped = esc_sql( $post_type );
-		if ( is_string( $escaped ) ) {
-			$type_list[] = "'" . $escaped . "'";
-		}
-	}
-	$type_list = implode( ',', $type_list );
-
-	// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table names and the escaped type list cannot be prepared.
-	$rows = $wpdb->get_results(
-		$wpdb->prepare(
-			"SELECT o.id, o.date_created_gmt, o.date_updated_gmt, p.post_date, p.post_date_gmt, p.post_modified, p.post_modified_gmt
-			FROM {$orders_table} o
-			INNER JOIN {$wpdb->posts} p ON p.ID = o.id AND p.post_type IN ({$type_list})
-			WHERE o.id > %d
-			AND ( o.date_created_gmt IS NULL OR o.date_created_gmt = %s OR o.date_updated_gmt IS NULL OR o.date_updated_gmt = %s )
-			ORDER BY o.id ASC
-			LIMIT %d",
-			(int) get_option( $last_id_option, 0 ),
-			$zero,
-			$zero,
-			$batch_size
-		)
-	);
-	// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-
-	if ( '' !== $wpdb->last_error ) {
-		wc_get_logger()->error( sprintf( 'Stopped repairing HPOS order dates: %s', $wpdb->last_error ), array( 'source' => 'wc-updater' ) );
-		delete_option( $last_id_option );
-		return false;
-	}
-
-	// The rule WordPress applies to its own posts: the GMT column, or the local one when the GMT one is the zero date.
-	$gmt_from_post = function ( $gmt_date, $local_date ) use ( $zero ) {
-		if ( $gmt_date && $zero !== $gmt_date ) {
-			return $gmt_date;
-		}
-		if ( ! $local_date || $zero === $local_date ) {
-			return null;
-		}
-		$datetime = date_create( $local_date, wp_timezone() );
-		return $datetime ? $datetime->setTimezone( new DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' ) : null;
-	};
-
-	// Repaired orders leave the caches (a cached object still has no date and would stamp the current time on its next save)
-	// and get queued for the Analytics import, which skipped them while they had no date.
-	$forget_and_import = function ( array $order_ids ) {
-		if ( ! $order_ids ) {
-			return;
-		}
-		wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore::class )->clear_cached_data( $order_ids );
-		$order_cache = wc_get_container()->get( \Automattic\WooCommerce\Caches\OrderCache::class );
-		// With Analytics disabled nothing handles the import action, and queueing it would only leave failed actions behind.
-		$import_hook    = \Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler::get_action( 'import' );
-		$import_handled = is_string( $import_hook ) && has_action( $import_hook );
-		/**
-		 * Filters whether Analytics runs its imports inline instead of queueing them.
-		 *
-		 * @since 4.0.0
-		 * @param bool $disable Whether Action Scheduler is bypassed.
-		 */
-		$import_inline = ! get_option( 'schema-ActionScheduler_StoreSchema' ) || apply_filters( 'woocommerce_analytics_disable_action_scheduling', false );
-		foreach ( $order_ids as $order_id ) {
-			$order_cache->remove( $order_id );
-			if ( ! $import_handled ) {
-				continue;
-			}
-			if ( $import_inline ) {
-				\Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler::import( $order_id );
-				continue;
-			}
-			// Queued directly: OrdersScheduler::schedule_action() first searches every pending action for a duplicate, which gets
-			// slower with each order queued here. A duplicate import only rewrites the same stats row.
-			WC()->queue()->schedule_single( time() + 5, $import_hook, array( $order_id ), (string) \Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler::$group );
-		}
-	};
-
-	$repaired_ids = array();
-	foreach ( $rows as $row ) {
-		$columns = array();
-		if ( ! $row->date_created_gmt || $zero === $row->date_created_gmt ) {
-			$columns['date_created_gmt'] = $gmt_from_post( $row->post_date_gmt, $row->post_date );
-		}
-		if ( ! $row->date_updated_gmt || $zero === $row->date_updated_gmt ) {
-			$columns['date_updated_gmt'] = $gmt_from_post( $row->post_modified_gmt, $row->post_modified );
-		}
-		$columns = array_filter( $columns );
-		if ( empty( $columns ) ) {
-			continue;
-		}
-		// Each column is written only while it is still empty, so a save that lands between the read and the write wins.
-		$assignments = array();
-		$values      = array();
-		foreach ( $columns as $column => $value ) {
-			$assignments[] = "{$column} = IF( {$column} IS NULL OR {$column} = %s, %s, {$column} )";
-			$values[]      = $zero;
-			$values[]      = $value;
-		}
-		$values[] = (int) $row->id;
-		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared -- Table and column names are code-defined, values go through prepare().
-		$updated = $wpdb->query( $wpdb->prepare( "UPDATE {$orders_table} SET " . implode( ', ', $assignments ) . ' WHERE id = %d', $values ) );
-		if ( false === $updated ) {
-			wc_get_logger()->error( sprintf( 'Stopped repairing HPOS order dates at order #%d: %s', (int) $row->id, $wpdb->last_error ), array( 'source' => 'wc-updater' ) );
-			$forget_and_import( $repaired_ids );
-			delete_option( $last_id_option );
-			return false;
-		}
-		// Zero rows means a save or another run filled the dates first, and that writer already took care of the rest.
-		if ( $updated > 0 ) {
-			$repaired_ids[] = (int) $row->id;
-		}
-	}
-
-	$forget_and_import( $repaired_ids );
-
-	if ( count( $rows ) === $batch_size ) {
-		// The cursor only ever moves forward: a concurrent run (the queue plus `wp wc update`) may already have saved this id or a
-		// later one, and update_option() reports that as false just like a failed write. Without a saved cursor the next run would
-		// pick the same rows again, and rows whose post has no date never leave the selection.
-		$cursor = (int) end( $rows )->id;
-		if ( (int) get_option( $last_id_option, 0 ) < $cursor && ! update_option( $last_id_option, $cursor, false ) ) {
-			wp_cache_delete( $last_id_option, 'options' );
-			if ( (int) get_option( $last_id_option, 0 ) < $cursor ) {
-				wc_get_logger()->error( 'Stopped repairing HPOS order dates: the progress cursor could not be saved.', array( 'source' => 'wc-updater' ) );
-				delete_option( $last_id_option );
-				return false;
-			}
-		}
-		return true;
-	}
-
-	delete_option( $last_id_option );
-
-	return false;
-}
-
 /**
  * Persist the legacy variation price hash option for existing stores so get_option returns an explicit value.
  *
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 8d4f5a6ce09..bb71ed432d4 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -16546,13 +16546,13 @@ parameters:
 		-
 			message: '#^Cannot call method getOffsetTimestamp\(\) on WC_DateTime\|null\.$#'
 			identifier: method.nonObject
-			count: 4
+			count: 5
 			path: includes/data-stores/abstract-wc-order-data-store-cpt.php

 		-
 			message: '#^Cannot call method getTimestamp\(\) on WC_DateTime\|null\.$#'
 			identifier: method.nonObject
-			count: 4
+			count: 5
 			path: includes/data-stores/abstract-wc-order-data-store-cpt.php

 		-
@@ -60058,6 +60058,18 @@ parameters:
 			count: 1
 			path: src/Internal/DataStores/Orders/OrdersTableDataStore.php

+		-
+			message: '#^Cannot call method getOffsetTimestamp\(\) on WC_DateTime\|null\.$#'
+			identifier: method.nonObject
+			count: 1
+			path: src/Internal/DataStores/Orders/OrdersTableDataStore.php
+
+		-
+			message: '#^Cannot call method getTimestamp\(\) on WC_DateTime\|null\.$#'
+			identifier: method.nonObject
+			count: 1
+			path: src/Internal/DataStores/Orders/OrdersTableDataStore.php
+
 		-
 			message: '#^Cannot call method get_download_permissions_granted\(\) on WC_Order\|WC_Order_Refund\|false\.$#'
 			identifier: method.nonObject
diff --git a/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/PostToOrderTableMigrator.php b/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/PostToOrderTableMigrator.php
index 8af67d980f2..f524ce438f5 100644
--- a/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/PostToOrderTableMigrator.php
+++ b/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/PostToOrderTableMigrator.php
@@ -69,18 +69,13 @@ class PostToOrderTableMigrator extends MetaToCustomTableMigrator {
 				'type'        => 'string',
 				'destination' => 'status',
 			),
-			// WordPress leaves the GMT columns at the zero date for some posts (drafts, imports) and treats the local
-			// columns as the truth in that case. Without the fallback such orders arrive here with no date at all, and the
-			// next save stamps them with the current time.
 			'post_date_gmt'     => array(
-				'type'            => 'date',
-				'destination'     => 'date_created_gmt',
-				'fallback_column' => 'post_date',
+				'type'        => 'date',
+				'destination' => 'date_created_gmt',
 			),
 			'post_modified_gmt' => array(
-				'type'            => 'date',
-				'destination'     => 'date_updated_gmt',
-				'fallback_column' => 'post_modified',
+				'type'        => 'date',
+				'destination' => 'date_updated_gmt',
 			),
 			'post_parent'       => array(
 				'type'        => 'int',
diff --git a/plugins/woocommerce/src/Database/Migrations/MetaToCustomTableMigrator.php b/plugins/woocommerce/src/Database/Migrations/MetaToCustomTableMigrator.php
index 2f0f82678f0..597703121cc 100644
--- a/plugins/woocommerce/src/Database/Migrations/MetaToCustomTableMigrator.php
+++ b/plugins/woocommerce/src/Database/Migrations/MetaToCustomTableMigrator.php
@@ -13,11 +13,6 @@ namespace Automattic\WooCommerce\Database\Migrations;
  */
 abstract class MetaToCustomTableMigrator extends TableMigrator {

-	/**
-	 * The value MySQL stores for a DATETIME that was never set.
-	 */
-	private const ZERO_DATE = '0000-00-00 00:00:00';
-
 	/**
 	 * Config for tables being migrated and migrated from. See __construct() for detailed config.
 	 *
@@ -84,7 +79,6 @@ abstract class MetaToCustomTableMigrator extends TableMigrator {
 	 *  '$source_column_name_1' => array( // $source_column_name_1 is column name in source table, or a select statement.
 	 *      'type' => 'type of value, could be string/int/date/float.',
 	 *      'destination' => 'name of the column in column name where this data should be inserted in.',
-	 *      'fallback_column' => 'optional, for the date type only: source column holding the same datetime in the site timezone, used when the source column is empty or the zero date.',
 	 *  ),
 	 *  '$source_column_name_2' => array(
 	 *          ......
@@ -450,11 +444,8 @@ WHERE source.`$source_primary_key_column` IN ( $entity_id_placeholder ) $additio
 			} else {
 				$entity_keys[] = "$source_entity_table.$column_name";
 			}
-			if ( isset( $column_schema['fallback_column'] ) ) {
-				$entity_keys[] = "$source_entity_table.{$column_schema['fallback_column']}";
-			}
 		}
-		$entity_column_string = implode( ', ', array_unique( $entity_keys ) );
+		$entity_column_string = implode( ', ', $entity_keys );
 		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- $source_meta_rel_id_column, $source_destination_rel_id_column etc is escaped for backticks. $where clause and $order_by should already be escaped.
 		$query = $wpdb->prepare(
 			"
@@ -545,11 +536,7 @@ WHERE
 			foreach ( $this->core_column_mapping as $column_name => $schema ) {
 				$custom_table_column_name = $schema['destination'] ?? $column_name;
 				$value                    = $entity->$column_name;
-				if ( isset( $schema['fallback_column'] ) && ( null === $value || '' === $value || self::ZERO_DATE === $value ) ) {
-					// With nothing to fall back to, the original value is stored as it always was.
-					$value = $this->local_date_to_gmt( $entity->{$schema['fallback_column']} ?? null ) ?? $value;
-				}
-				$value = $this->validate_data( $value, $schema['type'] );
+				$value                    = $this->validate_data( $value, $schema['type'] );
 				if ( is_wp_error( $value ) ) {
 					$error_records[ $entity->primary_key_id ][ $custom_table_column_name ] = $value->get_error_code();
 				} else {
@@ -668,9 +655,6 @@ WHERE
 			$source_select_column         = isset( $schema['select_clause'] ) ? $schema['select_clause'] : "$source_table.$column_name";
 			$source_select_clauses[]      = "$source_select_column as {$source_table}_{$column_name}";
 			$destination_select_clauses[] = "$destination_table.{$schema['destination']} as {$destination_table}_{$schema['destination']}";
-			if ( isset( $schema['fallback_column'] ) ) {
-				$source_select_clauses[] = "$source_table.{$schema['fallback_column']} as {$source_table}_{$schema['fallback_column']}";
-			}
 		}

 		foreach ( $this->meta_column_mapping as $meta_key => $schema ) {
@@ -882,44 +866,13 @@ WHERE $where_clause
 			} else {
 				$row[ $alias ] = ( new \DateTime( "@{$row[ $alias ]}" ) )->format( 'Y-m-d H:i:s' );
 			}
-			if ( self::ZERO_DATE === $row[ $destination_alias ] ) {
-				$row[ $destination_alias ] = null;
-			}
-		}
-		if ( 'date' === $schema['type'] ) {
-			if ( '' === $row[ $alias ] || self::ZERO_DATE === $row[ $alias ] ) {
-				$row[ $alias ] = null;
-			}
-			if ( null === $row[ $alias ] && isset( $schema['fallback_column'] ) ) {
-				$fallback_alias = "{$this->schema_config['source']['entity']['table_name']}_{$schema['fallback_column']}";
-				$row[ $alias ]  = $this->local_date_to_gmt( $row[ $fallback_alias ] ?? null );
-			}
-			if ( self::ZERO_DATE === $row[ $destination_alias ] ) {
+			if ( '0000-00-00 00:00:00' === $row[ $destination_alias ] ) {
 				$row[ $destination_alias ] = null;
 			}
 		}
 		return $row;
 	}

-	/**
-	 * Convert a datetime string expressed in the site's timezone to its GMT equivalent.
-	 *
-	 * Unlike get_gmt_from_date(), an empty, zero or unparsable value yields null rather than the Unix epoch.
-	 *
-	 * @param string|null $value Datetime string in the site's timezone.
-	 * @return string|null GMT datetime string, or null when there is no usable value.
-	 */
-	private function local_date_to_gmt( ?string $value ): ?string {
-		if ( null === $value || '' === $value || self::ZERO_DATE === $value ) {
-			return null;
-		}
-		$datetime = date_create( $value, wp_timezone() );
-		if ( false === $datetime ) {
-			return null;
-		}
-		return $datetime->setTimezone( new \DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' );
-	}
-
 	/**
 	 * Helper method to get default value of a type.
 	 *
diff --git a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
index 5d481d63b96..ace31dd00ef 100644
--- a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
+++ b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
@@ -2347,18 +2347,13 @@ FROM $order_meta_table
 		$data_sync = wc_get_container()->get( DataSynchronizer::class );

 		$data = array(
-			'post_type'   => $data_sync->data_sync_is_enabled() ? $order->get_type() : $data_sync::PLACEHOLDER_ORDER_POST_TYPE,
-			'post_status' => 'draft',
-			'post_parent' => $order->get_changes()['parent_id'] ?? $order->get_data()['parent_id'] ?? 0,
+			'post_type'     => $data_sync->data_sync_is_enabled() ? $order->get_type() : $data_sync::PLACEHOLDER_ORDER_POST_TYPE,
+			'post_status'   => 'draft',
+			'post_parent'   => $order->get_changes()['parent_id'] ?? $order->get_data()['parent_id'] ?? 0,
+			'post_date'     => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
+			'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
 		);

-		// An order with no created date leaves the post dates to WordPress rather than failing the whole sync batch.
-		$date_created = $order->get_date_created( 'edit' );
-		if ( ! is_null( $date_created ) ) {
-			$data['post_date']     = gmdate( 'Y-m-d H:i:s', $date_created->getOffsetTimestamp() );
-			$data['post_date_gmt'] = gmdate( 'Y-m-d H:i:s', $date_created->getTimestamp() );
-		}
-
 		if ( 'backfill' === $context ) {
 			if ( ! $order->get_id() ) {
 				return 0;
diff --git a/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php b/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php
index f4fbe8c3b5e..3ac20437fea 100644
--- a/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php
+++ b/plugins/woocommerce/tests/php/includes/data-stores/class-wc-order-data-store-cpt-test.php
@@ -57,52 +57,6 @@ class WC_Order_Data_Store_CPT_Test extends WC_Unit_Test_Case {
 		parent::tearDown();
 	}

-	/**
-	 * @testdox Should read the created and modified dates from the local post columns when the GMT ones hold the zero date.
-	 */
-	public function test_read_falls_back_to_local_dates_when_gmt_dates_are_zero(): void {
-		global $wpdb;
-
-		update_option( 'timezone_string', 'Europe/Amsterdam' );
-		$order = OrderHelper::create_order();
-		$wpdb->update(
-			$wpdb->posts,
-			array(
-				'post_date_gmt'     => '0000-00-00 00:00:00',
-				'post_modified_gmt' => '0000-00-00 00:00:00',
-			),
-			array( 'ID' => $order->get_id() )
-		);
-		clean_post_cache( $order->get_id() );
-		$post = get_post( $order->get_id() );
-
-		$read = new WC_Order();
-		$read->set_id( $order->get_id() );
-		( new WC_Order_Data_Store_CPT() )->read( $read );
-
-		$this->assertSame( get_gmt_from_date( $post->post_date ), $read->get_date_created()->setTimezone( new DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' ), 'The created date should come from post_date.' );
-		$this->assertSame( get_gmt_from_date( $post->post_modified ), $read->get_date_modified()->setTimezone( new DateTimeZone( 'UTC' ) )->format( 'Y-m-d H:i:s' ), 'The modified date should come from post_modified.' );
-	}
-
-	/**
-	 * @testdox Should leave the post dates untouched when backfilling an order that has no created date.
-	 */
-	public function test_update_order_from_object_keeps_post_dates_for_order_without_created_date(): void {
-		$order    = OrderHelper::create_order();
-		$before   = get_post( $order->get_id() );
-		$dateless = new WC_Order();
-		$dateless->set_id( $order->get_id() );
-		$dateless->set_status( OrderStatus::COMPLETED );
-		$dateless->set_date_created( null );
-
-		$this->assertNotFalse( ( new WC_Order_Data_Store_CPT() )->update_order_from_object( $dateless ) );
-
-		$after = get_post( $order->get_id() );
-		$this->assertSame( $before->post_date, $after->post_date, 'post_date should be kept.' );
-		$this->assertSame( $before->post_date_gmt, $after->post_date_gmt, 'post_date_gmt should be kept.' );
-		$this->assertSame( 'wc-completed', $after->post_status, 'Other fields should still be written.' );
-	}
-
 	/**
 	 * Test that refund cache are invalidated correctly when refund is deleted.
 	 */
diff --git a/plugins/woocommerce/tests/php/includes/wc-update-functions-test.php b/plugins/woocommerce/tests/php/includes/wc-update-functions-test.php
index 3a7c144b8f0..3512d225c7a 100644
--- a/plugins/woocommerce/tests/php/includes/wc-update-functions-test.php
+++ b/plugins/woocommerce/tests/php/includes/wc-update-functions-test.php
@@ -5,12 +5,6 @@
  * @package WooCommerce\Tests\Functions.
  */

-use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
-use Automattic\WooCommerce\Caches\OrderCache;
-use Automattic\WooCommerce\Utilities\OrderUtil;
-use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
-use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
-use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
 use Automattic\Jetpack\Constants;
 use Automattic\WooCommerce\Admin\API\Reports\Cache as ReportsCache;
 use Automattic\WooCommerce\Admin\Notes\Note;
@@ -27,30 +21,10 @@ use Automattic\WooCommerce\Internal\VariationGallery\Package as VariationGallery
  */
 class WC_Update_Functions_Test extends \WC_Unit_Test_Case {

-	/**
-	 * Whether HPOS was authoritative before the test.
-	 *
-	 * @var bool
-	 */
-	private $previous_hpos_state;
-
-	/**
-	 * Set up test fixtures.
-	 */
-	public function setUp(): void {
-		parent::setUp();
-		// Tests that migrate orders leave the two storages out of sync, which would otherwise block restoring the storage setting.
-		add_filter( 'wc_allow_changing_orders_storage_while_sync_is_pending', '__return_true' );
-		$this->previous_hpos_state = OrderUtil::custom_orders_table_usage_is_enabled();
-		OrderHelper::create_order_custom_table_if_not_exist();
-	}
-
 	/**
 	 * Tear down test fixtures.
 	 */
 	public function tearDown(): void {
-		OrderHelper::toggle_cot_feature_and_usage( $this->previous_hpos_state );
-		remove_filter( 'wc_allow_changing_orders_storage_while_sync_is_pending', '__return_true' );
 		Constants::clear_single_constant( 'WOOCOMMERCE_BIS_ALPHA_ENABLED' );
 		delete_option( 'woocommerce_feature_customer_stock_notifications_enabled' );
 		parent::tearDown();
@@ -752,169 +726,6 @@ class WC_Update_Functions_Test extends \WC_Unit_Test_Case {
 		return $variation_id;
 	}

-	/**
-	 * @testdox wc_update_1130_repair_hpos_order_dates_from_posts should fill HPOS dates that an earlier migration left empty from the order's post.
-	 */
-	public function test_wc_update_1130_repairs_hpos_dates_from_posts(): void {
-		global $wpdb;
-
-		include_once WC_ABSPATH . 'includes/wc-update-functions.php';
-
-		update_option( 'timezone_string', 'Europe/Amsterdam' );
-		$order_id = OrderHelper::create_complex_wp_post_order();
-		$wpdb->update(
-			$wpdb->posts,
-			array(
-				'post_date_gmt'     => '0000-00-00 00:00:00',
-				'post_modified_gmt' => '0000-00-00 00:00:00',
-			),
-			array( 'ID' => $order_id )
-		);
-		clean_post_cache( $order_id );
-		wc_get_container()->get( PostsToOrdersMigrationController::class )->migrate_orders( array( $order_id ) );
-		$orders_table = OrdersTableDataStore::get_orders_table_name();
-		// The shape earlier migrations left behind.
-		$wpdb->update(
-			$orders_table,
-			array(
-				'date_created_gmt' => '0000-00-00 00:00:00',
-				'date_updated_gmt' => null,
-			),
-			array( 'id' => $order_id )
-		);
-		$post = get_post( $order_id );
-
-		// A second order whose legacy data was cleaned up: the post is a placeholder but keeps its date columns.
-		$cleaned_id = OrderHelper::create_complex_wp_post_order();
-		$wpdb->update( $wpdb->posts, array( 'post_date_gmt' => '0000-00-00 00:00:00' ), array( 'ID' => $cleaned_id ) );
-		clean_post_cache( $cleaned_id );
-		wc_get_container()->get( PostsToOrdersMigrationController::class )->migrate_orders( array( $cleaned_id ) );
-		$wpdb->update( $orders_table, array( 'date_created_gmt' => '0000-00-00 00:00:00' ), array( 'id' => $cleaned_id ) );
-		$wpdb->update( $wpdb->posts, array( 'post_type' => DataSynchronizer::PLACEHOLDER_ORDER_POST_TYPE ), array( 'ID' => $cleaned_id ) );
-		clean_post_cache( $cleaned_id );
-		$cleaned_post = get_post( $cleaned_id );
-
-		// A cached order object without a date must not survive the repair.
-		$order_cache = wc_get_container()->get( OrderCache::class );
-		$order_cache->set( wc_get_order( $order_id ), $order_id );
-		// Creating the orders queued their own imports: clear them so the assertion below is about the routine.
-		as_unschedule_all_actions( 'wc-admin_import_orders' );
-
-		$this->assertFalse( wc_update_1130_repair_hpos_order_dates_from_posts(), 'A single small batch should not request another run' );
-
-		$row = $wpdb->get_row( $wpdb->prepare( "SELECT date_created_gmt, date_updated_gmt FROM {$orders_table} WHERE id = %d", $order_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-		$this->assertSame( get_gmt_from_date( $post->post_date ), $row->date_created_gmt, 'Created date should come from post_date converted with the site timezone' );
-		$this->assertSame( get_gmt_from_date( $post->post_modified ), $row->date_updated_gmt, 'Updated date should come from post_modified' );
-		$this->assertNotSame( $post->post_date, $row->date_created_gmt, 'The local date must have been converted' );
-		$this->assertSame( get_gmt_from_date( $cleaned_post->post_date ), $wpdb->get_var( $wpdb->prepare( "SELECT date_created_gmt FROM {$orders_table} WHERE id = %d", $cleaned_id ) ), 'A cleaned-up order is repaired from its placeholder post' ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-		$this->assertFalse( $order_cache->is_cached( $order_id ), 'The cached order object must be dropped' );
-		$this->assertNotFalse( as_next_scheduled_action( 'wc-admin_import_orders', array( $order_id ) ), 'The Analytics import must be queued for the repaired order' );
-	}
-
-	/**
-	 * @testdox wc_update_1130_repair_hpos_order_dates_from_posts should import repaired orders inline when Analytics scheduling is disabled.
-	 */
-	public function test_wc_update_1130_imports_inline_when_analytics_scheduling_is_disabled(): void {
-		global $wpdb;
-
-		include_once WC_ABSPATH . 'includes/wc-update-functions.php';
-
-		$order_id = OrderHelper::create_complex_wp_post_order();
-		wc_get_container()->get( PostsToOrdersMigrationController::class )->migrate_orders( array( $order_id ) );
-		$orders_table = OrdersTableDataStore::get_orders_table_name();
-		$wpdb->update( $orders_table, array( 'date_created_gmt' => '0000-00-00 00:00:00' ), array( 'id' => $order_id ) );
-		OrderHelper::toggle_cot_feature_and_usage( true );
-		// Creating the order queued its own import. Start from a clean slate so only the routine's behaviour is measured.
-		as_unschedule_all_actions( 'wc-admin_import_orders' );
-		$wpdb->delete( $wpdb->prefix . 'wc_order_stats', array( 'order_id' => $order_id ) );
-		add_filter( 'woocommerce_analytics_disable_action_scheduling', '__return_true' );
-
-		wc_update_1130_repair_hpos_order_dates_from_posts();
-
-		$this->assertFalse( as_next_scheduled_action( 'wc-admin_import_orders', array( $order_id ) ), 'Nothing should be queued when scheduling is disabled' );
-		$this->assertNotNull( $wpdb->get_var( $wpdb->prepare( "SELECT order_id FROM {$wpdb->prefix}wc_order_stats WHERE order_id = %d", $order_id ) ), 'The order should have been imported inline' );
-	}
-
-	/**
-	 * Insert a full batch of HPOS rows with no created date whose posts have no date either, so the repair has to advance its cursor.
-	 *
-	 * @return int The id of the last row in the batch.
-	 */
-	private function insert_full_batch_of_unrepairable_orders(): int {
-		global $wpdb;
-
-		$orders_table = OrdersTableDataStore::get_orders_table_name();
-		$first_id     = (int) $wpdb->get_var( "SELECT GREATEST( COALESCE( ( SELECT MAX( ID ) FROM {$wpdb->posts} ), 0 ), COALESCE( ( SELECT MAX( id ) FROM {$orders_table} ), 0 ) )" ) + 1; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-		$posts        = array();
-		$orders       = array();
-		for ( $id = $first_id; $id < $first_id + 500; $id++ ) {
-			$posts[]  = "( {$id}, 'shop_order', 'wc-completed', '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', '', '', '', '', '', '' )";
-			$orders[] = "( {$id}, 'shop_order', 'wc-completed', NULL, '2026-01-01 00:00:00' )";
-		}
-		// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Generated integers and literals only.
-		$wpdb->query( "INSERT INTO {$wpdb->posts} ( ID, post_type, post_status, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, post_title, post_excerpt, to_ping, pinged, post_content_filtered ) VALUES " . implode( ',', $posts ) );
-		$wpdb->query( "INSERT INTO {$orders_table} ( id, type, status, date_created_gmt, date_updated_gmt ) VALUES " . implode( ',', $orders ) );
-		// phpcs:enable
-
-		return $first_id + 499;
-	}
-
-	/**
-	 * @testdox wc_update_1130_repair_hpos_order_dates_from_posts should keep going when another run has already saved the same or a later cursor.
-	 *
-	 * @testWith [0]
-	 *           [1000]
-	 *
-	 * @param int $ahead How far past this batch the other run has already moved the cursor.
-	 */
-	public function test_wc_update_1130_accepts_a_cursor_saved_by_a_concurrent_run( int $ahead ): void {
-		include_once WC_ABSPATH . 'includes/wc-update-functions.php';
-
-		$last_id      = $this->insert_full_batch_of_unrepairable_orders();
-		$option       = 'woocommerce_update_1130_last_repaired_order_id';
-		$orders_table = OrdersTableDataStore::get_orders_table_name();
-		// The other run saves its cursor right after this one has read its batch.
-		$concurrent_save = function ( $query ) use ( $option, $last_id, $ahead, $orders_table ) {
-			if ( false !== strpos( $query, "FROM {$orders_table} o" ) ) {
-				update_option( $option, $last_id + $ahead, false );
-			}
-			return $query;
-		};
-		add_filter( 'query', $concurrent_save );
-
-		$this->assertTrue( wc_update_1130_repair_hpos_order_dates_from_posts(), 'A cursor saved by another run is progress, not a failure' );
-		$this->assertSame( $last_id + $ahead, (int) get_option( $option ), 'The cursor must never move backwards' );
-	}
-
-	/**
-	 * @testdox wc_update_1130_repair_hpos_order_dates_from_posts should leave rows alone when they have dates or their post has none.
-	 */
-	public function test_wc_update_1130_leaves_dated_rows_and_dateless_posts_alone(): void {
-		global $wpdb;
-
-		include_once WC_ABSPATH . 'includes/wc-update-functions.php';
-
-		$dated_id    = OrderHelper::create_complex_wp_post_order();
-		$dateless_id = OrderHelper::create_complex_wp_post_order();
-		$wpdb->update(
-			$wpdb->posts,
-			array(
-				'post_date'     => '0000-00-00 00:00:00',
-				'post_date_gmt' => '0000-00-00 00:00:00',
-			),
-			array( 'ID' => $dateless_id )
-		);
-		clean_post_cache( $dateless_id );
-		wc_get_container()->get( PostsToOrdersMigrationController::class )->migrate_orders( array( $dated_id, $dateless_id ) );
-		$orders_table = OrdersTableDataStore::get_orders_table_name();
-		$dated_before = $wpdb->get_var( $wpdb->prepare( "SELECT date_created_gmt FROM {$orders_table} WHERE id = %d", $dated_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-
-		$this->assertFalse( wc_update_1130_repair_hpos_order_dates_from_posts() );
-
-		$this->assertSame( $dated_before, $wpdb->get_var( $wpdb->prepare( "SELECT date_created_gmt FROM {$orders_table} WHERE id = %d", $dated_id ) ), 'A dated row must not change' ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-		$this->assertSame( '0000-00-00 00:00:00', $wpdb->get_var( $wpdb->prepare( "SELECT date_created_gmt FROM {$orders_table} WHERE id = %d", $dateless_id ) ), 'A post with no date gives nothing to repair from' ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-	}
-
 	/**
 	 * @testdox Migration rewrites stored stock notification emails in canonical form and leaves canonical rows alone.
 	 */
diff --git a/plugins/woocommerce/tests/php/src/Database/Migrations/CustomOrderTable/PostsToOrdersMigrationControllerTest.php b/plugins/woocommerce/tests/php/src/Database/Migrations/CustomOrderTable/PostsToOrdersMigrationControllerTest.php
index 35c54b87dcf..bbfc038375d 100644
--- a/plugins/woocommerce/tests/php/src/Database/Migrations/CustomOrderTable/PostsToOrdersMigrationControllerTest.php
+++ b/plugins/woocommerce/tests/php/src/Database/Migrations/CustomOrderTable/PostsToOrdersMigrationControllerTest.php
@@ -4,7 +4,6 @@ declare( strict_types = 1 );
 namespace Automattic\WooCommerce\Tests\Database\Migrations\CustomOrderTable;

 use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
-use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostToOrderTableMigrator;
 use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
 use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
 use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
@@ -125,72 +124,6 @@ class PostsToOrdersMigrationControllerTest extends \WC_Unit_Test_Case {
 		$this->assert_metadata_is_migrated( $order );
 	}

-	/**
-	 * @testdox Should derive the GMT created and modified dates from the local ones when the post holds the zero date in the GMT columns.
-	 */
-	public function test_migration_for_order_with_zero_gmt_dates(): void {
-		global $wpdb;
-
-		update_option( 'timezone_string', 'Europe/Amsterdam' );
-		$order = wc_get_order( OrderHelper::create_complex_wp_post_order() );
-		$this->clear_all_orders();
-		$wpdb->update(
-			$wpdb->posts,
-			array(
-				'post_date_gmt'     => '0000-00-00 00:00:00',
-				'post_modified_gmt' => '0000-00-00 00:00:00',
-			),
-			array( 'ID' => $order->get_id() )
-		);
-		clean_post_cache( $order->get_id() );
-		$post = get_post( $order->get_id() );
-
-		$this->sut->migrate_order( $order->get_id() );
-
-		$db_order = $this->get_order_from_cot( $order );
-		$this->assertEquals( get_gmt_from_date( $post->post_date ), $db_order->date_created_gmt, 'The created date should be derived from post_date.' );
-		$this->assertEquals( get_gmt_from_date( $post->post_modified ), $db_order->date_updated_gmt, 'The modified date should be derived from post_modified.' );
-		$this->assertNotEquals( $post->post_date, $db_order->date_created_gmt, 'The local date should have been converted to GMT.' );
-
-		$migrator = new PostToOrderTableMigrator();
-		$this->assertEmpty( $migrator->verify_migrated_data( array( $order->get_id() ) ), 'Verification should accept the derived dates.' );
-
-		// A row migrated before the fallback existed still holds the zero date: verification must report it.
-		$wpdb->update( $this->data_store::get_orders_table_name(), array( 'date_created_gmt' => '0000-00-00 00:00:00' ), array( 'id' => $order->get_id() ) );
-		$failures = $migrator->verify_migrated_data( array( $order->get_id() ) );
-		$this->assertSame( 'post_date_gmt', $failures[ $order->get_id() ][0]['column'] ?? null, 'Verification should flag a created date that was not derived.' );
-	}
-
-	/**
-	 * @testdox Should keep the zero date when both the GMT and the local columns hold the zero date.
-	 */
-	public function test_migration_for_order_with_zero_gmt_and_local_dates(): void {
-		global $wpdb;
-
-		$order = wc_get_order( OrderHelper::create_complex_wp_post_order() );
-		$this->clear_all_orders();
-		$wpdb->update(
-			$wpdb->posts,
-			array(
-				'post_date'         => '0000-00-00 00:00:00',
-				'post_date_gmt'     => '0000-00-00 00:00:00',
-				'post_modified'     => '0000-00-00 00:00:00',
-				'post_modified_gmt' => '0000-00-00 00:00:00',
-			),
-			array( 'ID' => $order->get_id() )
-		);
-		clean_post_cache( $order->get_id() );
-
-		$this->sut->migrate_order( $order->get_id() );
-
-		$db_order = $this->get_order_from_cot( $order );
-		$this->assertSame( '0000-00-00 00:00:00', $db_order->date_created_gmt, 'With no date to derive the created date from, the zero date is stored as before.' );
-		$this->assertSame( '0000-00-00 00:00:00', $db_order->date_updated_gmt, 'With no date to derive the modified date from, the zero date is stored as before.' );
-
-		$migrator = new PostToOrderTableMigrator();
-		$this->assertEmpty( $migrator->verify_migrated_data( array( $order->get_id() ) ), 'Verification should accept the empty dates.' );
-	}
-
 	/**
 	 * Test that already migrated order isn't migrated twice.
 	 */
diff --git a/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php b/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
index 877c187b13f..ad4decc7ad4 100644
--- a/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
+++ b/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
@@ -1478,30 +1478,6 @@ class OrdersTableDataStoreTests extends \HposTestCase {
 		}
 	}

-	/**
-	 * @testDox Backfilling an order that has no created date and no post row should create the post instead of failing.
-	 */
-	public function test_backfill_post_record_for_order_without_created_date_or_post() {
-		global $wpdb;
-		$this->toggle_cot_feature_and_usage( true );
-		$this->disable_cot_sync();
-		$order = $this->create_complex_cot_order();
-		$wpdb->delete( $wpdb->posts, array( 'ID' => $order->get_id() ) );
-		$wpdb->update( $this->sut::get_orders_table_name(), array( 'date_created_gmt' => null ), array( 'id' => $order->get_id() ) );
-		clean_post_cache( $order->get_id() );
-		$this->sut->clear_cached_data( array( $order->get_id() ) );
-
-		$dateless = new WC_Order();
-		$dateless->set_id( $order->get_id() );
-		$this->switch_data_store( $dateless, $this->sut );
-		$this->sut->read( $dateless );
-		$this->assertNull( $dateless->get_date_created(), 'Precondition: the order has no created date.' );
-
-		$this->sut->backfill_post_record( $dateless );
-
-		$this->assertInstanceOf( \WP_Post::class, get_post( $order->get_id() ), 'The backup post should exist after the backfill.' );
-	}
-
 	/**
 	 * @testDox Test `get_unpaid_orders()`.
 	 */
@@ -1582,29 +1558,6 @@ class OrdersTableDataStoreTests extends \HposTestCase {
 		remove_all_filters( 'woocommerce_hpos_enable_sync_on_read' );
 	}

-	/**
-	 * @testDox Sync on read should keep the created date when the post's GMT date column holds the zero date.
-	 */
-	public function test_sync_on_read_keeps_created_date_when_post_gmt_date_is_zero() {
-		global $wpdb;
-		$this->toggle_cot_feature_and_usage( true );
-		$this->enable_cot_sync();
-		add_filter( 'woocommerce_hpos_enable_sync_on_read', '__return_true' );
-		$order   = $this->create_complex_cot_order();
-		$created = $order->get_date_created()->getTimestamp();
-		$wpdb->update( $wpdb->posts, array( 'post_date_gmt' => '0000-00-00 00:00:00' ), array( 'ID' => $order->get_id() ) );
-		clean_post_cache( $order->get_id() );
-
-		$refreshed_order = new WC_Order();
-		$refreshed_order->set_id( $order->get_id() );
-		$this->switch_data_store( $refreshed_order, $this->sut );
-		$this->sut->read( $refreshed_order );
-
-		$this->assertSame( $created, $refreshed_order->get_date_created()->getTimestamp(), 'The posts reader must agree with HPOS, so nothing is copied back.' );
-		$this->assertSame( gmdate( 'Y-m-d H:i:s', $created ), $wpdb->get_var( $wpdb->prepare( "SELECT date_created_gmt FROM {$this->sut::get_orders_table_name()} WHERE id = %d", $order->get_id() ) ), 'The HPOS row must keep its date.' ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-		remove_all_filters( 'woocommerce_hpos_enable_sync_on_read' );
-	}
-
 	/**
 	 * @testDox When there are direct writes to posts data, order should synced upon reading.
 	 */