Anonymous View

3v4l.org

run code in 500+ PHP versions simultaneously
<?php function add_calendar_months($date_str, $months){ $dt = new DateTime($date_str, new DateTimeZone('UTC')); $day = (int) $dt->format('j'); $dt->modify('first day of this month'); $dt->modify("+{$months} months"); $max_day = (int) $dt->format('t'); $dt->setDate((int) $dt->format('Y'), (int) $dt->format('n'), min($day, $max_day)); return $dt; } // EXACT force_renew.php logic. Pin "now" deterministically via a fixed timestamp. date_default_timezone_set('UTC'); $current_next = '2026-02-28 23:59:59'; $billing_months = 1; // Simulate renewal landing on the anniversary day-of-month==28 at noon: $now_ts = strtotime('2026-03-28 12:00:00 UTC'); $next_dt = add_calendar_months($current_next, $billing_months); echo "first_add=" . $next_dt->format('Y-m-d H:i:s') . " ts=" . $next_dt->getTimestamp() . "\n"; echo "now_ts=" . $now_ts . " (" . gmdate('Y-m-d H:i:s', $now_ts) . ")\n"; $iter = 0; while ($next_dt->getTimestamp() <= $now_ts) { $iter++; $next_dt = add_calendar_months($next_dt->format('Y-m-d H:i:s'), $billing_months); if ($iter > 6){ echo "RUNAWAY\n"; break; } } $new_next_billing_date = $next_dt->format('Y-m-d') . ' 23:59:59'; echo "LOOP_ITERS=$iter\n"; echo "STORED_next_billing_date=$new_next_billing_date\n"; echo "EXPECTED_for_1mo=2026-03-28 23:59:59\n"; echo (($new_next_billing_date === '2026-03-28 23:59:59') ? "VERDICT=CORRECT_no_overadvance\n" : "VERDICT=OVERADVANCED_BUG\n");
Output for 8.2.31, 8.3.0 - 8.3.31, 8.4.1 - 8.4.22, 8.5.0 - 8.5.7
first_add=2026-03-28 23:59:59 ts=1774742399 now_ts=1774699200 (2026-03-28 12:00:00) LOOP_ITERS=0 STORED_next_billing_date=2026-03-28 23:59:59 EXPECTED_for_1mo=2026-03-28 23:59:59 VERDICT=CORRECT_no_overadvance

preferences:
43.09 ms | 761 KiB | 4 Q