WPIntell

Source evidence

Timezone bug: coupons expire early on non-UTC sites

Auto Coupons for WooCommerce · support · 2026-06-09T08:01:00+00:00

mixedsentiment
mediumseverity
0.67relevance
1replies
Evidence linked to opportunitycommercial context

Proof Health

Open evidence

Commercial opportunities need traceable source links before they are treated as build-worthy.

4 / 26 rows with source links

15.4% of this page's analysis has direct source links.

0 build-decision rows missing links

0 rows here require auditable proof before promotion.

22 rows with no attached evidence

0 rows have source counts but still need direct links.

Conversation

support
bluantinoo resolved
Hi, I’ve found what looks like a timezone bug in the coupon-expiry check that makes auto-applied coupons stop applying before their actual expiry date on any site whose timezone is not UTC. Environment Plugin version: 3.0.42 (also confirmed the same code in the current 3.0.47) Site timezone: Asia/Tokyo (UTC+9) MySQL server timezone: UTC (@@session.time_zone = SYSTEM, server is UTC) WooCommerce default coupon expiry handling (expiry stored as a UTC epoch in date_expires postmeta) The problem In wac_functions.php the expiry comparison mixes two different timezones: $now = current_time('mysql'); // site/local timezone (JST here) // expiry flag: CASE WHEN FROM_UNIXTIME(x.meta_value) < '$now' THEN 1 ELSE 0 END exp // and in 3.0.47, also as a WHERE clause: AND IFNULL(FROM_UNIXTIME(x.meta_value),'9999-12-31') > '$now' current_time(‘mysql’) returns the site-local wall-clock time, while FROM_UNIXTIME() renders the stored timestamp in the MySQL session timezone (UTC on most servers). Comparing a UTC datetime string against a local datetime string makes the coupon appear expired by exactly the site’s UTC offset ahead of time. Concrete example A coupon set to expire on 2026-06-06 is stored by WooCommerce as date_expires = 1780671600 (= 2026-06-06 00:00 JST = 2026-06-05 15:00 UTC). FROM_UNIXTIME(1780671600) → 2026-06-05 15:00:00 (UTC string) current_time(‘mysql’) at, say, 18:44 JST on June 5 → 2026-06-05 18:44:00 The query evaluates ‘2026-06-05 15:00:00’ < ‘2026-06-05 18:44:00’ → TRUE → the coupon is treated as expired and is not auto-applied. In practice the coupon stopped auto-applying from 15:00 JST on June 5, i.e. 9 hours before the intended midnight expiry. WooCommerce core itself still considered the coupon valid at that time (it compares the raw UTC timestamp against time()), so the same coupon entered manually would still work — only the auto-apply was affected. The error is symmetric: positive UTC offsets expire early, negative offsets expire late. It only behaves correctly when the site is on UTC. Suggested fix Compare the raw integer timestamps instead of formatted datetime strings, since WooCommerce already stores date_expires as a UTC epoch — this is timezone-agnostic: -- instead of: FROM_UNIXTIME(x.meta_value) > '<current_time mysql>' -- use: x.meta_value > UNIX_TIMESTAMP() or, on the PHP side, pass time() (UTC epoch) as the comparator instead of current_time(‘mysql’) . Thanks for looking into it. Thanks for reporting this. I was able to reproduce and confirm the timezone issue. The fix has been implemented and will be included in today’s release. Thanks for bringing this to my attention.

Comments

1 shown
RLDD 2026-06-09T14:27:00+00:00

Thanks for reporting this. I was able to reproduce and confirm the timezone issue. The fix has been implemented and will be included in today’s release. Thanks for bringing this to my attention.