Timezone Offsets in WordPress Themes

There is an odd implementation detail of many themes that has created a parsing problem with timestamps. It is actually a WordPress/PHP issue. The below is an excerpt from _s(Underscores) that appears in a large amount of themes.

$time_string = sprintf( $time_string,
   esc_attr( get_the_date( 'c' ) ),
   get_the_date(),
   esc_attr( get_the_modified_date( 'c' ) ),
   get_the_modified_date()
);

The string in question is used in a generated line of HTML, which usually looks like something below.

<time datetime="2016-06-21T22:48:40+00:00">June 21, 2016</time>

A parser reading the above will read it as 10:48PM UTC/GMT. Assuming it converted that into local time, it would actually be 6:48PM EDT. However, in reality, I posted at 10:48PM Eastern Time. It just omitted the timezone offset, putting in +00:00.

The timezone offset is properly shown if you replace ‘c’ with DATE_W3C or DATE_ATOM. The alternative is to add the date in as GMT.  Without proper timezone offsets, posts will be parsed as being at the wrong time.

Related:

https://core.trac.wordpress.org/ticket/25768

https://core.trac.wordpress.org/ticket/20973

 

 

Converting WordPress Themes for Microformats 2 – Part 1

I won’t claim to be a Microformats expert…but the below are some simple steps that can be taken to adjust a theme structurally for Microformat posts.

The below filters can be added to a theme’s functions.php, but you have to make sure that your theme uses the post, body, and comment class functions, and that it doesn’t style hfeed or hentry. Also, hfeed is often added to the theme, and should be removed to avoid duplication.

 

/**
 * Adds custom classes to the array of body classes.
 *
 * @param array $classes Classes for the body element.
 * @return array
 */
function body_classes( $classes ) {
	// Adds a class of hfeed to non-singular pages.
	if ( ! is_singular() ) {
		$classes[] = 'hfeed';
		$classes[] = 'h-feed';
	} else {
		if ( 'page' !== get_post_type() ) {
				$classes[] = 'hentry';
				$classes[] = 'h-entry';
		}
	}
	return $classes;
}
add_filter( 'body_class', 'body_classes' );
/**
 * Adds custom classes to the array of post classes.
 *
 * @param array $classes Classes for the body element.
 * @return array
 */
function post_classes( $classes ) {
	$classes = array_diff( $classes, array( 'hentry' ) );
	if ( ! is_singular() ) {
		if ( 'page' !== get_post_type() ) {
			// Adds a class for microformats v2
			$classes[] = 'h-entry';
			// add hentry to the same tag as h-entry
			$classes[] = 'hentry';
		}
	}
	return $classes;
}

add_filter( 'post_class', 'post_classes' );

 

Now the below adds microformats 2 classes to the avatar photo and to comments.

/**
 * Adds mf2 to avatar
 *
 * @param array             $args Arguments passed to get_avatar_data(), after processing.
 * @param int|string|object $id_or_email A user ID, email address, or comment object
 * @return array $args
 */
	function get_avatar_data($args, $id_or_email) {
	if ( ! isset( $args['class'] ) ) {
		$args['class'] = array( 'u-photo' );
	 } else {
		$args['class'][] = 'u-photo';
	 }
	return $args;
	}

add_filter( 'get_avatar_data', 'get_avatar_data', 11, 2 );

/**
 * Adds custom classes to the array of comment classes.
 */
function comment_classes( $classes ) {
	$classes[] = 'u-comment';
	$classes[] = 'h-cite';
	return array_unique( $classes );
}

add_filter( 'comment_class', 'comment_classes', 11 );

This allows for the simplest conversion of themes to the basic Microformats 2 structure. In the second part, we start moving into other more invasive modifications of the theme.