[13.x] Fix schedule:list timezone conversion for range, step, and wildcard cron expressions#60877
[13.x] Fix schedule:list timezone conversion for range, step, and wildcard cron expressions#60877xiCO2k wants to merge 3 commits into
Conversation
|
Some stuff found by my agent review
|
|
Tested On the current 13.x base, stepped four-hour expressions remain unchanged during BST and are therefore incorrectly labelled UTC. With this PR: I also tested immediately after both 2026 Europe/London DST transitions and compared the next 12 actual run timestamps across six scenarios. Every converted UTC timestamp matched the original expression evaluated in Europe/London. Focused result on PHP 8.5.7: 87 tests, 344 assertions passed. Thanks a lot |
|
@taylorotwell implemented those suggestions. |
f90bc92 to
5b3081b
Compare
This PR is a follow-up to #59286. The converter only shifts plain numeric fields, so ranges (
8-23), steps (*/2), and wildcards pass through unchanged while the output still labels them with the display timezone. Anything consumingschedule:list --jsonwill compute the wrong run times for those.Example
Before
[ { "expression": "*/10 8-23 * * *", "timezone": "UTC" } ]The expression claims the task runs 08:00-23:59 UTC. It actually runs 08:00-23:59 Amsterdam time (06:00-21:59 UTC).
After
[ { "expression": "*/10 6-21 * * *", "timezone": "UTC" } ]The converter now expands any field into its values, shifts them, and collapses the result back into compact syntax (
*,a-b,*/s,a-b/s, or a comma list). More examples:0 0-4 * * *0 0-4 * * *0 5-9 * * *0 */2 * * *0 */2 * * *0 1-23/2 * * *0 8 * * 1-50 23 * * 1-50 23 * * 0-40 0 1 1-12/3 *0 15 31 1-12/3 *0 15 31 3-12/3 *The last two were converted before, but wrongly. The hour was shifted across midnight while the day-of-week/month ranges stayed behind. They now shift together with the carry.
Some nastier ones, with fractional offsets and boundary crossings:
0 8-17 * * 1-515 8-17 * * 1-515 19-23 * * 0-415 0-4 * * 1-5* * 1 1 ** * 1 1 *15-59 18-23 31 12 *15-59 0-17 1 1 *0-14 19-23 31 12 *0-14 0-18 1 1 **/15 9-17 * * **/15 9-17 * * *15-45/15 3-11 * * *0 4-12 * * *0 22-23 * * 50 22-23 * * 50 5,6 * * 6Note the Chatham case: the old code shifted the minute by the fractional offset but left the hours and weekdays alone, producing an expression that is correct in no timezone.
Some edge-cases
Splitting still works as in #59286. When a shifted range crosses midnight and a day field is fixed, the event is split:
When the day fields are all wildcards, a day carry is irrelevant (every day matches), so mixed carries now merge into a single entry instead.
twiceDaily(13, 17)inAmerica/Los_Angelesnow produces one line,0 1,21 * * *, where #59286 produced two.Expressions using syntax that cannot be safely shifted (
L,W,#,?, or named values likeMON) in a field that needs shifting are returned unchanged, as before. The converter never emits a half-converted expression.Tests
Updated the cases that pinned the old pass-through behavior and added coverage for ranges, steps, wildcards, half-hour offsets, day carries, merging, and the fallbacks. Also verified the converted expressions produce the exact same run instants as the originals evaluated in their own timezone.