Posted on

Natural-language date queries

I just wanted to be able to type in a date on the search and for the search to come up with all the blog posts for that date.

This is one of those tasks that sounds really simple, but isn’t as simple as could be. However, this question piqued my interest and turns out it isn’t that hard.

add_filter( 'relevanssi_modify_wp_query', 'rlv_date_query' );
function rlv_date_query( $query ) {
	$time     = strtotime( $query->query_vars['s'] );
	if ( $time ) {
		$year  = date( 'Y', $time );
		$use_year = strpos( $query->query_vars['s'], $year ) !== false ? true : false;
		$month = date( 'm', $time );
		$day   = date( 'd', $time );
		$date_query = array(
			'month' => $month,
			'day'   => $day,
		);
		if ( $use_year ) {
			$date_query['year'] = $year;
		}
		$query->set( 'date_query', $date_query );
		$query->query_vars['s'] = '';
	}
	return $query;
}

The solution is simple. The search query ($query->query_vars['s']) is fed to PHP’s strtotime() function, which converts an English-language string to a timestamp. If the search query converts to a timestamp, the timestamp is converted into a date and used for a date query.

The function also checks if the year appears in the query. If it doesn’t, the year isn’t used. Yearless dates are converted into current year timestamps (“16 August” matches August 16th, 2019), but if the year isn’t mentioned in the original query, it’s discarded, so the results include all years. The search query is then swiped clean.

This only works when there’s nothing else but the date in the query. This supports many different formats, all of these work at least:

– 16 August or 16 August 2019
– August 16th or August 16th 2019
– 16.8.2019
– 8/16/2019

(As it happens, this isn’t Relevanssi-specific. If you’re not using Relevanssi, you just need to use pre_get_posts instead of relevanssi_modify_wp_query.)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.