Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Aug 17, 2025

This PR fixes a critical issue where responses that should not be cached were being cached for approximately one hour during DST (Daylight Saving Time) transitions when PHP is configured with a non-UTC timezone.

Problem

The library uses new \DateTime('-1 seconds') to create expiry timestamps for cache entries that should not be cached (e.g., responses with Cache-Control: no-cache). During DST transitions, specifically when going from summer time to winter time, there's an hour that repeats. PHP's DateTime class with relative time strings can create ambiguous timestamps that resolve to future times instead of past times.

For example, during the Europe/Berlin DST transition on 2024-10-27:

  • Both UTC times "2024-10-27 00:00:56" and "2024-10-27 01:00:56" correspond to "2024-10-27 02:00:56" in local time
  • new \DateTime('-1 seconds') could resolve to the later occurrence, creating a future timestamp
  • This results in a TTL of ~3599 seconds instead of -1, causing unwanted caching

Solution

Replace new \DateTime('-1 seconds') with new \DateTime('@' . (time() - 1)) in two locations within PrivateCacheStrategy.php. The '@' prefix creates a DateTime object from a Unix timestamp, which is always UTC-based and unambiguous.

Changes

  • src/Strategy/PrivateCacheStrategy.php: Fixed two instances where relative DateTime creation was replaced with explicit UTC timestamps
  • tests/DstTransitionTest.php: Added comprehensive tests to verify the fix works across different timezones and prevents the DST issue

Impact

  • ✅ Cache entries marked for immediate expiry now consistently expire immediately
  • ✅ No unexpected caching during DST transitions
  • ✅ Consistent behavior across all timezones
  • ✅ Maintains all existing functionality - this is a surgical fix

The fix ensures RFC 7234 compliance is maintained while preventing the timezone-related edge case that could cause security or correctness issues.

Fixes #194.

Warning

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/iamHi8 /usr/bin/composer install --no-dev (http block)
  • https://api.github.com/repos/php-cache/hierarchical-cache/zipball/dedffd0a74f72c1db76e57ce29885836944e27f3
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/qSfBGF /usr/bin/composer install (http block)
  • https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/iamHi8 /usr/bin/composer install --no-dev (http block)
  • https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/qSfBGF /usr/bin/composer install (http block)
  • https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/iamHi8 /usr/bin/composer install --no-dev (http block)

If you need me to access, download, or install something from one of these locations, you can either:


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Replace DateTime('-1 seconds') with UTC timestamp approach to avoid timezone ambiguity during DST transitions. This prevents cache entries that should expire immediately from being cached for extended periods during DST transitions.

Co-authored-by: Kevinrob <[email protected]>
@Copilot Copilot AI changed the title [WIP] Forced caching during DST transition Fix DST transition issue causing forced caching of non-cacheable responses Aug 17, 2025
@Copilot Copilot AI requested a review from Kevinrob August 17, 2025 14:56
Copilot finished work on behalf of Kevinrob August 17, 2025 14:56
Remove testUtcTimestampApproachIsConsistentAcrossTimezones method as it tests PHP's DateTime behavior rather than our cache middleware logic. Keep the tests that actually verify our CacheEntry implementation.

Co-authored-by: Kevinrob <[email protected]>
@Kevinrob Kevinrob requested a review from Copilot August 21, 2025 11:45
Copy link
Contributor Author

Copilot AI commented Aug 21, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/JHEoOR /usr/bin/composer install --no-dev (http block)
  • https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/JHEoOR /usr/bin/composer install --no-dev (http block)
  • https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/JHEoOR /usr/bin/composer install --no-dev (http block)
  • https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/JHEoOR /usr/bin/composer install --no-dev (http block)
  • https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/JHEoOR /usr/bin/composer install --no-dev (http block)
  • https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822
    • Triggering command: /usr/bin/php8.3 -n -c /tmp/JHEoOR /usr/bin/composer install --no-dev (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@Copilot Copilot AI requested a review from Kevinrob August 21, 2025 11:46
Copilot finished work on behalf of Kevinrob August 21, 2025 11:46
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a critical DST (Daylight Saving Time) bug where responses marked as non-cacheable were incorrectly cached for approximately one hour during timezone transitions. The issue occurred because new \DateTime('-1 seconds') could resolve to future timestamps during DST transitions when PHP uses non-UTC timezones.

  • Replaced relative DateTime creation with UTC timestamp-based approach in PrivateCacheStrategy
  • Added comprehensive test coverage to verify the fix across different timezones
  • Ensures RFC 7234 compliance is maintained while preventing timezone-related edge cases

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Strategy/PrivateCacheStrategy.php Fixed two instances of relative DateTime creation that could cause DST issues by using UTC timestamps
tests/DstTransitionTest.php Added new test class to verify the fix works across timezones and prevents DST-related caching issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Forced caching during DST transition
2 participants