Commit 26155aa9745 for woocommerce

commit 26155aa974543821c930e16aafd658d74db1ee0d
Author: Peter Petrov <peter.petrov89@gmail.com>
Date:   Wed Aug 12 16:58:32 2026 +0300

    Respect the WordPress "Week Starts On" setting in Analytics week ranges (#67629)

    * Respect the WordPress "Week Starts On" setting in Analytics week ranges

    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

    * Spread the actual @wordpress/date module in the import status bar test mock

    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

    ---------

    Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

diff --git a/packages/js/date/changelog/fix-week-start-setting b/packages/js/date/changelog/fix-week-start-setting
new file mode 100644
index 00000000000..f2869a18d52
--- /dev/null
+++ b/packages/js/date/changelog/fix-week-start-setting
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Respect the WordPress "Week Starts On" setting in Analytics week date ranges and calendars.
diff --git a/packages/js/date/src/index.ts b/packages/js/date/src/index.ts
index cd116113e7d..74620e3fdb0 100644
--- a/packages/js/date/src/index.ts
+++ b/packages/js/date/src/index.ts
@@ -3,6 +3,7 @@
  */
 import moment from 'moment';
 import { getTimezoneOffset } from 'date-fns-tz';
+import { getSettings as getDateSettings } from '@wordpress/date';
 import { find, memoize } from 'lodash';
 import { __ } from '@wordpress/i18n';
 import { parse } from 'qs';
@@ -258,6 +259,34 @@ function anchorRangeToStoreTimeZone( range: DateValue ): DateValue {
 	};
 }

+/**
+ * Aligns the moment locale's start of the week with the WordPress
+ * "Week Starts On" setting. WordPress core applies the setting to the moment
+ * locale, but `wp.date.setSettings` then redefines the locale without a `week`
+ * key, resetting the start of the week to Sunday; without this correction,
+ * week ranges and calendar layouts ignore the setting.
+ */
+function ensureMomentStartOfWeek() {
+	const startOfWeek = getDateSettings().l10n?.startOfWeek;
+
+	if (
+		typeof startOfWeek !== 'number' ||
+		! Number.isInteger( startOfWeek ) ||
+		startOfWeek < 0 ||
+		startOfWeek > 6
+	) {
+		return;
+	}
+
+	if ( moment.localeData().firstDayOfWeek() !== startOfWeek ) {
+		moment.updateLocale( moment.locale(), {
+			week: { dow: startOfWeek },
+		} );
+	}
+}
+
+ensureMomentStartOfWeek();
+
 /**
  * Get a DateValue object for a period prior to the current period.
  *
@@ -269,6 +298,8 @@ export function getLastPeriod(
 	period: moment.DurationInputArg2,
 	compare: string
 ) {
+	ensureMomentStartOfWeek();
+
 	const primaryStart = getStoreTimeZoneMoment()
 		.startOf( period )
 		.subtract( 1, period );
@@ -321,6 +352,8 @@ export function getCurrentPeriod(
 	period: moment.DurationInputArg2,
 	compare: string
 ) {
+	ensureMomentStartOfWeek();
+
 	const primaryStart = getStoreTimeZoneMoment().startOf( period );
 	const primaryEnd = getStoreTimeZoneMoment();

diff --git a/packages/js/date/src/test/index.ts b/packages/js/date/src/test/index.ts
index 980055f47dd..52088bc4ff7 100644
--- a/packages/js/date/src/test/index.ts
+++ b/packages/js/date/src/test/index.ts
@@ -2,7 +2,11 @@
  * External dependencies
  */
 import moment from 'moment';
-import { format as formatDate } from '@wordpress/date';
+import {
+	format as formatDate,
+	getSettings as getDateSettings,
+	setSettings as setDateSettings,
+} from '@wordpress/date';
 import { timeFormat as d3TimeFormat } from 'd3-time-format';
 /**
  * Internal dependencies
@@ -732,6 +736,58 @@ describe( 'getLastPeriod', () => {
 	} );
 } );

+describe( 'start of week setting', () => {
+	const originalSettings = getDateSettings();
+	const originalDow = moment.localeData().firstDayOfWeek();
+
+	afterEach( () => {
+		setDateSettings( originalSettings );
+		moment.updateLocale( moment.locale(), {
+			week: { dow: originalDow },
+		} );
+	} );
+
+	it( 'getCurrentPeriod should start the week on the day from the WordPress setting', () => {
+		setDateSettings( {
+			...originalSettings,
+			l10n: { ...originalSettings.l10n, startOfWeek: 1 },
+		} );
+
+		const dateValue = getCurrentPeriod( 'week', 'previous_period' );
+
+		expect( dateValue.primaryStart.day() ).toBe( 1 );
+		expect( dateValue.primaryStart.isSameOrBefore( moment(), 'day' ) ).toBe(
+			true
+		);
+	} );
+
+	it( 'getLastPeriod should start and end the week on days from the WordPress setting', () => {
+		setDateSettings( {
+			...originalSettings,
+			l10n: { ...originalSettings.l10n, startOfWeek: 3 },
+		} );
+
+		const dateValue = getLastPeriod( 'week', 'previous_period' );
+
+		expect( dateValue.primaryStart.day() ).toBe( 3 );
+		expect( dateValue.primaryEnd.day() ).toBe( 2 );
+	} );
+
+	it( 'should leave the moment default when the setting is invalid', () => {
+		setDateSettings( {
+			...originalSettings,
+			l10n: {
+				...originalSettings.l10n,
+				startOfWeek: 7 as unknown as 0,
+			},
+		} );
+
+		const dateValue = getCurrentPeriod( 'week', 'previous_period' );
+
+		expect( dateValue.primaryStart.day() ).toBe( originalDow );
+	} );
+} );
+
 describe( 'getRangeLabel', () => {
 	it( 'should return correct string for dates on the same day', () => {
 		const label = getRangeLabel(
diff --git a/plugins/woocommerce/changelog/fix-week-start-setting b/plugins/woocommerce/changelog/fix-week-start-setting
new file mode 100644
index 00000000000..5c853df534a
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-week-start-setting
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Spread the actual @wordpress/date module in the import status bar test mock.
diff --git a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx
index 3a3ff7f9d04..ad005f4fd2e 100644
--- a/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx
+++ b/plugins/woocommerce/client/admin/client/analytics/components/import-status-bar/test/import-status-bar.test.tsx
@@ -21,6 +21,7 @@ jest.mock( '@wordpress/data', () => ( {
 	} ) ),
 } ) );
 jest.mock( '@wordpress/date', () => ( {
+	...jest.requireActual( '@wordpress/date' ),
 	dateI18n: jest.fn( ( format, date ) => {
 		// Simple mock that returns a date-like string
 		if ( ! date ) return 'Never';