WP breaks time & how to fix it
Had you ever...
changed WP time zone?
Settings → General → Timezone
Had you ever...
output localized time?
date_i18n()
, the_date()
, etc.
A very brief history of time
- solar time
- city time
- rail time
- time zones
- Universal Coordinated Time
Unix time
1 525 435 200
seconds since 1970–01–01 00:00:00 UTC
Unix time
- consistent
- storage–friendly
- comparison–friendly
- not human readable
PHP DateTime
$dt = new DateTime();
echo $dt->getTimestamp();
echo $dt->format( DATE_RFC3339 );
echo $dt->getTimezone()->getName();
php.net/datetime
WP time
- PHP 4 code
- partial PHP 5 retrofit
- custom time zone logic
- custom internationalization
WP time zone options
setting | gmt_offset | timezone_string |
Berlin | 2 | 'Europe/Berlin' |
UTC+2 | '2' | '' |
WP time zone in all cases
- get
timezone_string
- if empty — get
gmt_offset
- convert the offset number to
±00:00
(PHP 5.5+)
WpDateTimeZone to parse time zone
$timezone = WpDateTimeZone::getWpTimezone();
setting | $timezone->getName() |
Berlin | 'Europe/Berlin' |
UTC+2 | '+02:00' |
date_i18n() logic
echo date_i18n( 'j. F Y, G.i \U\h\r T' );
j. F Y, G.i \U\h\r T
j. \M\a\i Y, G.i \U\h\r T
— locale
j. \M\a\i Y, G.i \U\h\r \C\E\S\T
— zone
4. Mai 2018, 14.00 Uhr CEST
— date()
date_i18n() fails w/ gmt_offset
WP set to Berlin time zone:
echo date_i18n( DATE_RFC3339 );
WP set to UTC+2 time zone:
echo date_i18n( DATE_RFC3339 );
#34835
date_i18n() fails w/ Unix timestamp
echo date( DATE_RFC3339, time() );
echo date_i18n( DATE_RFC3339, time() );
#38771
date_i18n() fails w/ some formats
echo date_i18n( DATE_RFC3339 ); // === 'Y-m-d\TH:i:sP'
echo date_i18n( 'c' ); // === 'c'
echo date_i18n( DATE_RFC2822 ); // === 'D, d M Y H:i:s O'
echo date_i18n( 'r' ); // === 'r'
#20973
WpDateTime to wrap date_i18n()
WP set to UTC+2 time zone:
$time = new WpDateTime( '@' . time() );
$timezone = WpDateTimeZone::getWpTimezone();
$time = $time->setTimezone( $timezone );
echo $time->formatI18n( 'c' );
echo $time->formatI18n( 'r' );
post_date
post_date | post_date_gmt | post_title |
2018-05-04 13:00:00 |
2018-05-04 12:00:00 |
A post made in London |
WP set to London time zone:
the_date( DATE_RFC3339 );
post_date fails w/ changed time zone
post_date | post_date_gmt | post_title |
2018-05-04 13:00:00 |
2018-05-04 12:00:00 |
A post made in London |
WP set to Berlin time zone:
the_date( DATE_RFC3339 );
#38774
post_date in all cases
- get
post_date_gmt
- if empty — get
post_date
- get WP time zone
- adjust
post_date[_gmt]
with the time zone
- convert to desired format
WpDateTime to parse post date
post_date | post_date_gmt | post_title |
2018-05-04 13:00:00 |
2018-05-04 12:00:00 |
A post made in London |
WP set to Berlin time zone:
$time = WpDateTime::createFromPost( get_post() );
echo $time->formatI18n( DATE_RFC3339 );
Takeaways
- WP gets time storage and output wrong
- read and use UTC time
- write timestamp, UTC, or RFC 3339
- use
DateTime
to operate time
- use
WpDateTime
to bridge WP and PHP