wordpress/date: Recover WP timezone after third-party reload#75831
wordpress/date: Recover WP timezone after third-party reload#75831jsnajdr merged 1 commit intoWordPress:trunkfrom
Conversation
Fixes issue where plugins (e.g. WooCommerce) that load their own copy of moment-timezone destroy the custom 'WP' zone and cause post times to be offset by 2x the UTC difference. The fix adds ensureWPTimezone() guards to isInTheFuture(), getDate(), and humanTimeDiff(). The custom WP timezone zone is now cached in packed form on first creation, so it can be re-added without requiring moment-timezone-utils after a third-party reload. Includes tests that verify recovery after the zone is destroyed.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Hey @jsnajdr @aduth, would love your eyes on this one when you get a chance! You've both worked on TL;DR: Adds resilience against third-party plugins that reload moment-timezone and destroy the custom 'WP' timezone zone. Thanks! 🙏 |
|
I'd like to better understand the mechanism how WooCommerce overwrites the How does WooCommerce load the second copy of If WooCommerce merely bundled |
|
Thanks @jsnajdr for your reply! Please let me provide some more context, I was not able to reproduce the issue using function telex_timezone_converter_simulate_moment_overwrite() {
// Log state BEFORE the CDN script loads
wp_add_inline_script(
'wp-date',
'console.log("[TZ Debug] BEFORE CDN - WP zone:", window.moment.tz.zone("WP"));
console.log("[TZ Debug] BEFORE CDN - tz.names count:", window.moment.tz.names().length);',
'after'
);
wp_enqueue_script(
'moment-timezone-override',
'https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.46/moment-timezone-with-data-10-year-range.min.js',
array( 'wp-date' ),
null,
false
);
// Log state AFTER the CDN script loads
wp_add_inline_script(
'moment-timezone-override',
'console.log("[TZ Debug] AFTER CDN - WP zone:", window.moment.tz.zone("WP"));
console.log("[TZ Debug] AFTER CDN - tz.names count:", window.moment.tz.names().length);',
'after'
);
}
add_action( 'admin_enqueue_scripts', 'telex_timezone_converter_simulate_moment_overwrite' );When I load the block, the timezone is not correctly applied. But after giving this some more thought, if the issue isn't reproducible with popular plugins or doesn't represent a standard use case, it might make sense to close this PR. What do you think? |
The telex reproduction case makes sense: if any plugin registers its own copy of It would be nice to know where did the issue come from. What motivated you to fix it, did it happen to you personally on some site. If someone overwrites I quite like the PR, but would like to see a stronger case why it needs to be done. Such a change will last for many years, and folks in the future will be asking what is this special code doing and whether it's still needed. |
This originates from a Calypso issue: Automattic/wp-calypso#71529. The latest occurrences are from more than a year ago, so they may already have been resolved.
That’s very reasonable, and it makes total sense. I think the change is self-explanatory, but it may also be considered unnecessary, so I understand that if we don’t have a strong case, this can be closed. I will update the issue with these comments, and it can be reopened if further occurrences appear and can be reproduced without a plugin created just for that purpose |
There are indeed many reports there, but most seem to have been resolved after a Still, this PR is pretty good, let's merge it 🙂 |
…ad (#75831) Fixes issue where plugins (e.g. WooCommerce) that load their own copy of moment-timezone destroy the custom 'WP' zone and cause post times to be offset by 2x the UTC difference. The fix adds ensureWPTimezone() guards to isInTheFuture(), getDate(), and humanTimeDiff(). The custom WP timezone zone is now cached in packed form on first creation, so it can be re-added without requiring moment-timezone-utils after a third-party reload. Includes tests that verify recovery after the zone is destroyed. Co-authored-by: epeicher <epeicher@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>
…ad (#75831) Fixes issue where plugins (e.g. WooCommerce) that load their own copy of moment-timezone destroy the custom 'WP' zone and cause post times to be offset by 2x the UTC difference. The fix adds ensureWPTimezone() guards to isInTheFuture(), getDate(), and humanTimeDiff(). The custom WP timezone zone is now cached in packed form on first creation, so it can be re-added without requiring moment-timezone-utils after a third-party reload. Includes tests that verify recovery after the zone is destroyed. Co-authored-by: epeicher <epeicher@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>
…ad (#75831) Fixes issue where plugins (e.g. WooCommerce) that load their own copy of moment-timezone destroy the custom 'WP' zone and cause post times to be offset by 2x the UTC difference. The fix adds ensureWPTimezone() guards to isInTheFuture(), getDate(), and humanTimeDiff(). The custom WP timezone zone is now cached in packed form on first creation, so it can be re-added without requiring moment-timezone-utils after a third-party reload. Includes tests that verify recovery after the zone is destroyed. Co-authored-by: epeicher <epeicher@git.wordpress.org> Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>
What?
Makes the
@wordpress/datepackage resilient to third-party plugins that reload moment-timezone and destroy the custom 'WP' timezone zone.Why?
On sites with non-UTC timezones, post times in the block editor can be offset by 2x the site's UTC difference (e.g., a post published at 10 AM on a UTC+4 site shows as 2 AM). This occurs because plugins like WooCommerce load their own copy of moment-timezone, which reinitializes the internal zone storage and destroys Gutenberg's custom 'WP' timezone zone. When the zone is lost,
moment.tz(date, 'WP')falls back incorrectly, causing the UTC offset to be applied twice.How?
The fix adds resilience to moment-timezone reloads by:
ensureWPTimezone()guard that checks if the 'WP' zone still exists before using itmomentLib.tz.add(), not the utils that get destroyed)isInTheFuture(),getDate(), andhumanTimeDiff()before accessingWP_ZONEThe cached approach avoids calling
pack()on recovery since the utils are also destroyed by third-party reloads.Testing Instructions
wp-date(e.g., enqueuemoment-timezone-with-data-10-year-range.min.jsfrom cdnjs withwp-dateas a dependency), for example, the following testing plugintelex-timezone-converter.zip
timezone-converterplugin, add theTimezone Date Converterblock to the potTesting Instructions for Keyboard
N/A — no UI changes.