I’ve recently had to think about calculating time intervals in a little WordPress plugin of mine, and I thought I would share my findings. Maybe some of you will have some ideas on how to improve things even further :)
Problem: I want to store the results of an expensive query in a transient for the day.
My first implementation was to set the transient for 24 hours:
set_transient( $transient_key, $query, DAY_IN_SECONDS );
DAY_IN_SECONDS is a default constant provided by WordPress to make those things easier.
That’s not exactly what I want, though. I don’t want data to be cached for 24 hours; I want it to be cached for the rest of the day, i.e. for the amount of time (seconds) left in the day until midnight.
If the query is first run on the site a minute before midnight, I don’t want to cache it for 24 hours; I want that data to be refreshed after midnight, since it’s already going to be the next day.
In my second implementation, I used WordPress’
current_time (reference) and
strtotime like so:
$time_now = (int) current_time( 'timestamp' ); $time_tonight = (int) strtotime( 'today 24:00' ); $seconds_remaining = $time_tonight - $time_now;
Comparing 2 Unix timestamps seemed simple enough. It works.
However, WPCS wasn’t happy. The use of
timestamp is discouraged in core, as explained in this GitHub issue.
That led me to a third solution, using the improvements to the Date/Time components that were brought to Core a couple of years ago.
$time_now = current_datetime(); $time_tonight = new DateTimeImmutable( 'today 24:00', wp_timezone() ); $seconds_remaining = $time_tonight->getTimestamp() - $time_now->getTimestamp();
Excellent! No more phpcs warnings, and it works well. Bonus, it’s a tiny bit faster :)
current_datetime() is also creating a
DateTimeImmutable object, I figured it may be easier to read if I were to replace that wrapper:
$time_now = new DateTimeImmutable( 'now', wp_timezone() ); $time_tonight = new DateTimeImmutable( 'today 24:00', wp_timezone() ); $seconds_remaining = $time_tonight->getTimestamp() - $time_now->getTimestamp();
That seems a bit easier to understand at first glance. It’s also faster.
For fun, here is a last alternative, that’s again a bit faster:
$timezone = new DateTimeZone( wp_timezone_string() ); $time_now = new DateTimeImmutable( 'now', $timezone ); $time_tonight = new DateTimeImmutable( 'today 24:00', $timezone ); $seconds_remaining = $time_tonight->getTimestamp() - $time_now->getTimestamp();
I think I’ll keep using
wp_timezone(); it’s readable and quick enough. And in the future, I’ll definitely try to use WordPress’ date and time components a bit more!
Would you have done it differently? I’d be curious to have your take on this!