Schedule WooCommerce sale prices in bulk: dates, times and time zones
To schedule a WooCommerce sale price in bulk you do not need a scheduler: every product already has two sale date fields, and WooCommerce itself switches the price on and off on those days. The confusing part is how those dates work: they are whole days, they follow the WordPress time zone, and the switch depends on a background task. Below: a dated sale on hundreds of products in one BEAR run, why times cannot be set, why a sale starts a day off or seems never to end, and what to do when the change is not a sale.
Schedule a sale price for many products in one bulk run
A Black Friday sale of 25% from 27 to 30 November is one run of the Bulk Edit tab:
- Select the products in the Filters tab (a category, a tag, a brand) and check the line Bulk editing will be applied to at the top of the Bulk Edit tab.
- In the Basic section tick Sale price, enter
25and choose regular price minus %. - Open the Additional section, tick Sale time from and pick 27 November, tick Sale time to and pick 30 November.
- Press Do Bulk Edit.
Until the 27th the shop keeps showing the regular prices, from the start of the 27th the products are on sale, and after the end of the 30th the regular price is back. There is no end-of-sale run to remember.
Both parts are needed. The dates only limit a sale price in time: dates without a sale price do nothing, and a sale price without dates is active at once and until you remove it. Variable products keep prices and sale dates on their variations, so they need the variations switch and their own run; choosing products, the switch and the right price operation are covered in putting all products on sale.
When BEAR saves the dates it also sets the active price for the current moment, so a sale that starts today is live at once and a later one keeps the regular price until its day.
Sale dates are whole days: why you cannot set a time
WooCommerce stores the start and end of a sale as two moments, but its product screen only lets you choose dates, and BEAR follows the same rule. Sale time from is saved as 00:00:00 of the chosen day and Sale time to as 23:59:59 of its day, both in the time zone of the site. The end date is included: a sale to 30 November runs through the whole 30th. The calendar in BEAR therefore shows dates only; an hour typed anywhere would be thrown away on save.
Two filters decide which end of the day BEAR uses. woobe_on_sale_from_set_day (default false, the start of the day) and woobe_on_sale_to_set_day (default true, the end of the day). For example, to make a sale end at the beginning of the chosen end date, so that the day before is the last day of the sale:
/*
* BEAR: save "Sale time to" as 00:00:00 of the chosen day instead of 23:59:59.
* Child theme functions.php or a code snippets plugin.
*/
add_filter('woobe_on_sale_to_set_day', '__return_false');
These filters only choose between the two ends of a day; they cannot schedule a sale for 18:00. The WooCommerce product editor always saves the end of the day, so a product saved there later goes back to that rule. A sale that starts at a given hour is possible only through code or the WooCommerce REST API, which accept a full date and time.
Times also look shifted where they are shown raw: WooCommerce keeps the moments in UTC, so a sale ending at 23:59:59 in New York reads 03:59 or 04:59 the next day in the database. It is the same moment.
Scheduled sale one day off: the WordPress time zone
Every "start of the day" and "end of the day" above is calculated in the time zone set under Settings → General → Timezone. If the site still uses UTC+0 while the shop is in Hong Kong, a sale from 18 November starts at 08:00 local time; for a shop in Hawaii the same sale starts at 14:00 on the 17th, which looks like a day early. The sale itself works; it follows the wrong clock.
- Choose a city in the Timezone list rather than a fixed UTC+X offset. A city follows daylight saving time; a fixed offset is an hour off for half of the year. See the General Settings screen in the WordPress documentation.
- After changing the time zone, set the dates again on the products of the next sale: dates already saved keep the moments calculated with the old setting.
- Check one product of the run in the WooCommerce product editor. Its Sale price dates should show the days you chose.
Sales that cross a daylight saving change
BEAR converts the chosen day with the offset WordPress reports when you save. If the clocks change between that day and the sale, as with a Black Friday sale prepared in October, the sale starts and ends one hour off: from 23:00 the evening before to 22:59 on the last day, or from 01:00 on the first day to 00:59 after the last one when the clocks go the other way. The WooCommerce product editor converts with the offset of the sale day, so it shows one of the two dates a day off, and pressing Update there saves the date it shows. When the exact hour matters, set the dates after the clock change, and do not re-save those products in the WooCommerce editor before the sale.
How WooCommerce starts and ends a scheduled sale
BEAR only writes the sale price and the two dates; switching the price at the right moment is WooCommerce's job, and it works the same for products edited in BEAR, in the product editor or by an import. Since WooCommerce 10.5, saving sale dates creates two background actions per product, wc_product_start_scheduled_sale and wc_product_end_scheduled_sale, set to the exact start and end. A daily woocommerce_scheduled_sales task catches anything they missed. Older versions relied on that daily task alone, which is why sales there could switch hours or even a day late.
When a sale ends, current WooCommerce only switches the active price back to the regular price. The sale price and both dates stay on the product: the shop shows the regular price and no sale badge, while the product editor and the BEAR table still show the old sale price and dates. That is the normal state of an ended sale, not a sale that did not end. Older versions cleared the sale price and dates at the end.
When a sale really did not start or end on the shop:
- Check the actions. Open WooCommerce → Status → Scheduled Actions and search for the product ID or for
wc_product_end_scheduled_sale. A Pending action whose time has passed means background tasks are not running. Failed shows an error in its log. - Check WP-Cron. These actions are processed by WP-Cron, which runs only when the site gets visits. If
DISABLE_WP_CRONis set inwp-config.php, a real cron job on the server must callwp-cron.php, every few minutes; the WordPress guide on hooking WP-Cron into the system task scheduler shows how. On a site with little traffic, an action can wait for the first visit after its time. - Clear the page cache. A cached product or category page keeps showing the old price until the cache is purged or expires.
- Test without discount plugins. Pricing and discount plugins such as Woo Discount Rules calculate the displayed price themselves, so a scheduled WooCommerce sale can be hidden or doubled by their rules. Deactivate them on a staging copy, or check their rules for the same products.
- Compare with WooCommerce itself. Give one test product the same dates in the WooCommerce product editor. If it does not switch either, the cause is the server or another plugin, not the way the dates were written.
A new sale on a product that had one
Because an ended sale keeps its dates, a new sale price written alone inherits them. With an end date in the past it never shows; with an old end date still in the future it ends on that day. When you start a new sale, write the sale price and both dates in the same run, or clear the old dates first.
A future price change that is not a sale
BEAR applies a bulk operation when you press the button; it cannot hold one and run it on a date. If the change is temporary, write it as a sale with dates, as above. If it is not:
- A new regular price from a date. Prepare the filter and the operation in advance and run it at the moment of the change. A run over thousands of products takes minutes; see bulk editing thousands of products for large catalogues. Pricing plugins that support scheduled rules are the other route.
- Two sales back to back, for example 15% until 31 August and 20% from 1 September. A product holds one sale price, so the second sale cannot be stored while the first is running: overwriting the sale price changes the current sale at once. Run the second sale, with its dates, when the first one ends.
- Not the publication date. A future Date Published does not schedule a price. WordPress turns such products into scheduled posts, and they disappear from the shop until that date.
Remove sale dates in bulk or undo the run
To clear old dates from many products, select them with checkboxes, switch on binded editing and clear the date cell of one of them; the FAQ on removing sale dates shows the steps. To find products whose sale has ended, show the Sale time to column and sort by it. The sale price itself is removed with -1 and set new, as described in the FAQ on removing sale prices.
A wrong date in a large run needs no manual fixing: every bulk run is one entry in the History tab, and rolling it back restores the previous dates and prices of all products it changed.
Checklist before the sale starts
- Settings → General → Timezone is your city.
- Sale price and both dates were written in the same run; variable products had their own run with the variations switch on.
- One product opened in the WooCommerce editor shows the expected Sale price dates.
- On WooCommerce 10.5 or later, Scheduled Actions lists pending actions for the start and end of that product, and no pending action is overdue.
- Page cache rules and discount plugins will not hide the new prices.
If the dates are right, the actions run and the price still does not switch, describe the product, the dates and the state of its scheduled actions on the BEAR support forum.