DateTime crash course for WordPress developers

Check out my WpDateTime library, which solves many of the issues described in the post.

WordPress implementation of date and time handling is from PHP 4 times. It is good at localization and nothing else.

As result Date/Time PHP extension is bit of a mystery for many WordPress developers. Let’s see how to start with it in WordPress context.

Disclaimers

Most of the DateTime code is good for PHP 5.2, but some of it requires less obsolete versions. I only write PHP 5.2 for money, so you are on your own to backport anything from this post that doesn’t quite work in it.

Related code in WordPress is abundant with insane edge cases, assumptions, and outright bugs. I love digging through such stuff, but that is beyond even me. This post focuses on how, without going into details of why it goes wrong, done other ways.

Why DateTime

WordPress represents date/time as combination of string and state of timezone offset settings. It also resets current time zone to UTC and prevents native PHP code from working properly.

This makes it hard to check dates for sanity and perform calculations with them.

DateTime is object based (with much of API available as procedural function counterparts). It provides:

  • native sanity checks (can’t make invalid date);
  • smarter time zone handling (not just numeric offset);
  • objects (enables proper type hinting);
  • comparisons (you can compare objects).

Basic DateTime classes

DateTime is a basic object. It represents a date with time. You manipulate an object to retrieve, format, change, and compare dates to other instances.

DateTimeImmutable has one difference that any modification produces a new object instance. This is useful when original instance should stay the same.

DateTimeInterface is an interface for type hinting, which accepts both kinds. This is what you should use for type hints.

WordPress to DateTime

WordPress code has opinions. Wrestling its dates into DateTime object can be confusing.

Let’s start with the post date. WordPress way is:

var_dump( get_the_date( DATE_RSS ) );
// string(32) "Пт, 07 Nov 2014 13:36:31 +0200"

Note the localized presentation. It wouldn’t do to feed it into DateTime. Converting to timestamp doesn’t work well either.

Oh, and it is also wrong because the post was created at 13:36 GMT and blog settings changed since, so 13:36 GMT+2 is not the actual valid time. Since WP doesn’t store timezone with the time whenever settings change all existing data effectively becomes wrong.

To retrieve the correct time we would need to use post field which holds value in GMT time zone:

$mysql_datetime = get_post_field( 'post_date_gmt', get_post() );
$utc_timezone   = new DateTimeZone( 'UTC' );
$date           = DateTime::createFromFormat( 'Y-m-d H:i:s', $mysql_datetime, $utc_timezone );

var_dump( $date->format( DATE_RSS ) );
// string(31) "Fri, 07 Nov 2014 13:36:31 +0000"

Now we have correct time in GMT we can enhance it with current time zone information:

$timezone_string = get_option( 'timezone_string' );

if ( $timezone_string ) {
	$date->setTimezone( new DateTimeZone( $timezone_string ) );
}

var_dump( $date->format( DATE_RSS ) );
// string(31) "Fri, 07 Nov 2014 15:36:31 +0200"

In some cases timezone_string option might not be available and then code has to deal with older and less convenient gmt_offset one.

DateTime to WordPress

We still need to use WordPress for pretty localized output. date_i18n() function performs that, but also not without issue. While it documents accepting Unix timestamp, what it actually expects is combination of Unix timestamp and desired timezone.

Luckily easy enough to produce once from our objects:

var_dump( date_i18n( DATE_RSS, $date->getTimestamp() + $date->getOffset() ) );
// string(32) "Пт, 07 Nov 2014 15:36:31 +0200"

Overall

Use WordPress functions to:

  • retrieve stored dates data;
  • output localized dates.

Use DateTime to:

  • modify dates;
  • perform calculations with dates.

Related Posts