Skip to content

Forced caching during DST transition #194

@olavmo-sikt

Description

@olavmo-sikt

Summary

If PHP is configured with a non-UTC timezone, this library ends up caching objects that should not be cached when going from summer time to winter time.

Details

This library uses new \DateTime('-1 seconds') as an expiry timestamp for objects that should not be cached.
E.g. in src/Strategy/PrivateCacheStrategy.php#L112:

return new CacheEntry($request, $response, new \DateTime('-1 seconds'));

If PHP is configured with a non-UTC time zone, this breaks when going from summer time to winter time.

For example, both UTC time "2024-10-27 00:00:56" and "2024-10-27 01:00:56" was "2024-10-27 02:00:56" in timezone Europe/Berlin:

$ TZ=Europe/Berlin date -d '2024-10-27T00:00:56 +00:00'
Sun 27 Oct 02:00:56 CEST 2024
$ TZ=Europe/Berlin date -d '2024-10-27T01:00:56 +00:00'
Sun 27 Oct 02:00:56 CET 2024

The PHP DateTime class does not differentiate between these timestamps. However, when calling $ts->getTimestamp() it will always return the last value, even if it is in the future.

This library uses the $ts->getTimestamp() method to calculate a TTL for the object, which will then indicate that an object with an expiry of -1 seconds will be valid for nearly one hour.

Here is an example script that shows the problem:

<?php
$ts = new \DateTime("-1 seconds");
echo '$ts = ' . var_export($ts, true) . "\n";
echo '$ts->getTimestamp() = ' . $ts->getTimestamp() . "\n";
$ttl = $ts->getTimestamp() - time();
echo '$ttl = ' . $ttl . "\n";

Run this script during the transition from summer time to winter time using a non-UTC timezone to see the problem.
For example, using the faketime command and the Europe/Berlin time zone:

$ faketime '2024-10-27 00:00:56 +00:00' php -d date.timezone=Europe/Berlin datetime-timestamp.php
$ts = \DateTime::__set_state(array(
   'date' => '2024-10-27 02:00:55.936087',
   'timezone_type' => 3,
   'timezone' => 'Europe/Berlin',
))
$ts->getTimestamp() = 1729990855
$ttl = 3599

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions