In my settings, I have New York defined as the time zone. But when I run plugins using PHP date() functions, I am getting a time zone of UTC as it shows in WP Admin > Settings > General.

enter image description here

enter image description here

Edit: Here's the mu-plugin I use to add the meta tag:

 * Plugin Name: Web Services Global Meta Tag(s)
 * Plugin URI: http://example.com/wp-content/mu-plugins/global-metatag-insertion.php
 * Description: This plugin fires on every page and post in the WordPress Multisite Network. It adds custom meta tags to meets our needs. One meta tag that is added is for `last-modified` date.
 * Version: 1.0
 * Author: me
 * Author URI: http://me.example.com/
defined( 'ABSPATH' ) or die( 'Direct access not allowed' );

 * Insert `last-modified` date meta within `<head></head>` container
function last_modified_date() {
    echo '<meta http-equiv="last-modified" content="' . date( 'D, d M Y H:i:s T', strtotime( get_the_date() .' ' . get_the_time() ) ) . '" />' . "\n";
add_action( 'wp_head', 'last_modified_date' );
  • 1
    Could you please post that part that adds the meta tag? You probably just use the wrong function and make no use of the actual option set in the admin UI.
    – kaiser
    May 24, 2016 at 20:33
  • Yes, you are probably echoing the server time. Try with current_time.
    – Luis Sanz
    May 24, 2016 at 21:59
  • I added your plugin as edit to your answer. Please keep in mind that things that belong to a question should be put into the question – not in an answer.
    – kaiser
    May 25, 2016 at 12:34

2 Answers 2


date() is unreliable in WP since it always resets time zone to UTC and uses its own processing for time zones.

date_i18n() is usually preferable WP replacement, but it will also localize output, which might be unwanted.

What you want for correct unlocalized output is to:

  1. Get data out of WP API without its offset silliness.
  2. Get timezone setting out of WP.
  3. Feed those into DateTime object.

Here is brief (read it basics, not covering all possibilities) introduction to code:

d( date( 'D, d M Y H:i:s T', strtotime( get_the_date() .' ' . get_the_time() ) ) );
// Sat, 07 Jan 2012 07:07:00 UTC < wrong, date() is always wrong in WP

d( date( 'D, d M Y H:i:s T', get_the_time('U') ) );
// Sat, 07 Jan 2012 07:07:21 UTC < more short, still wrong

d( date_i18n( 'D, d M Y H:i:s T', get_the_time('U') ) );
// or simply
d( get_the_time( 'D, d M Y H:i:s T' ) );
// Сб, 07 Jan 2012 07:07:21 EEST < correct! but localized

$date = DateTime::createFromFormat( DATE_W3C, get_the_date( DATE_W3C ) );
d( $date->format( 'D, d M Y H:i:s T' ) );
// Sat, 07 Jan 2012 07:07:21 GMT+0300 < correct, but meh numeric time zone

$timezone = new DateTimeZone( get_option( 'timezone_string' ) );
$date->setTimezone( $timezone );

d( $date->format( 'D, d M Y H:i:s T' ) );
// Sat, 07 Jan 2012 06:07:21 EET < correct and not localized

I wrote more on topic in my DateTime crash course for WordPress developers post.

PS EEST / EET out of sync... I don't even know what's up with that difference. :)

  • 1
    ps: d() is a custom wrapper for var_dump() ?
    – birgire
    May 26, 2016 at 0:16
  • 1
    Yeah, it's Kint dumper.
    – Rarst
    May 26, 2016 at 7:58


First off: The http-equiv meta tags are the HTML equivalent of an HTTP response header. They can not override a header already sent by your web server. So their only use is as a fallback and they rarely provide any real help. In reality, you want to go in and fix the headers your server(s) is/are sending instead – or ask your host to do so if you are in a shared environment and are not allowed to do so.

Date and Time options

All those can be retrieved via: get_option( 'name' );. The possible values are:

  • Time format: time_format – default: __('g:i a') (string)
  • Time zone: timezone_string – default: null (string)
  • Date format: date_format – default: __('F j, Y') (string)
  • GMT Offset: gmt_offset – default: date('Z') / 3600 (integer)

Then there are several other possible functions that you can use, depending on what you are actually displaying (use "Conditional Tags" to switch):

  • Single post or page (or custom post): the_date()
  • Archives: Use the most current post date for this archive…

Here's your plugin, slightly reformatted to retrieve the timezone name from the GMT offset, account for PHP Bug #44780 (props uınbɐɥs) and also custom settings from your admin UI. If that is not what you want, you will have to play a bit with the options. What is missing is the conditional switches

/* Plugin Name: "Last Modified" meta tag */
add_action( 'wp_head', function() 
    // Abort if not on at home/ on the front page as this is just an example
    if ( ! ( is_home() or is_front_page() )

    $offset = get_option( 'gmt_offset' ) * 3600;
    $zone = timezone_name_from_abbr( '', $offset, 1 );
    ! $zone and $zone = timezone_name_from_abbr( '', $offset, 0 );
    $format = get_option( 'date_format' ).' '.get_option( 'time_format' ) );
    // @TODO adjust to take post date or similar into account
    $date = 'now';

    printf( '<meta http-equiv="last-modified" content="%s" />',
        ( new DateTime( $date, $zone ) )
            ->format( $format )
} );
  • Code is tad off, DateTime doesn't take zone as first argument.
    – Rarst
    May 25, 2016 at 17:23
  • @Rarst Written out of the back of my head + SO answer. Thanks for the pointer – fixed.
    – kaiser
    May 25, 2016 at 19:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.