Posted on

Searching between dates

If you want to have a search with a date range, that’s possible with Relevanssi. It takes a bit of handling, though, as Relevanssi expects date ranges in the date query format, and getting to that from search form can be tricky.

Here’s the code you need for date range searches:

add_filter( 'relevanssi_modify_wp_query', 'rlv_date_between' );
function rlv_date_between( $query ) {
	$from_date = null;
	$to_date   = null;
 
	// Get the dates from parameters "from" and "to", and parse to make sure they are dates.
	if ( isset( $_GET['from'] ) ) {
		$from_date = date_parse( $_GET['from'] );
	}
	if ( isset( $_GET['to'] ) ) {
		$to_date   = date_parse( $_GET['to'] );
	}
 
	$after  = null;
	$before = null;
 
	// If the "from" date checks as a valid date, create a parameter set for it.
	if ( $from_date && checkdate( $from_date['month'], $from_date['day'], $from_date['year'] ) ) {
		$after = array(
			'year'  => $from_date['year'],
		 	'month' => $from_date['month'],
		 	'day'   => $from_date['day'],
		);
	}
	// Same for the "to" date.
	if ( $to_date && checkdate( $to_date['month'], $to_date['day'], $to_date['year'] ) ) {
		$before = array(
			'year'  => $to_date['year'],
		 	'month' => $to_date['month'],
		 	'day'   => $to_date['day'],
		);
	}
 
	// Create the date query array and add the parameter sets to it if they were created.
	$date_query = array();
	if ( $after ) {
		$date_query['after'] = $after;
	}
	if ( $before ) {
		$date_query['before'] = $before;
	}
	if ( $after || $before ) {
		$date_query['inclusive'] = true;
	}
	// If there's something in the date query array, add it to the query.
	if ( ! empty( $date_query ) ) {
		$query->date_query = $date_query;
	}
 
	return $query;
}

Add this code to your theme (preferably child theme) functions.php file. This is a bit wordy, but also fairly safe: it checks that the parameters are actually dates before they are passed to anywhere. I’m not sure how necessary that is, but it’s best to be safe.

Using this would look like this: https://www.example.com/?s=search&from=2018-01-01 would show posts starting from January 1st. https://www.example.com/?s=search&from=2018-01-01&to=2018-01-31 would show posts in January 2018.

To get this on the search form, just add two input fields:

From: [input type="text" name="from" /] to [input type="text" name="to" /]

(Replace the square brackets with angled brackets.)

2 comments Searching between dates

  1. Hi!

    IIs this possible, without too heavy workarounds, to tweak this so that the date range would instead just be dropdowns searching “from Month / year to month/year” ? So it would look in the relevant monthly/yearly wp archives for example? Would be better ux than having user type in dates in a specific format in my case.

    1. Yes, you can use dropdowns. Instead of using one from field and one to field, you can have four fields: from_month and from_year for the from date and to_month and to_year for the to date. Those fields can be dropdowns, no problems with that. Then just parse those to form a date.

      Something like this:

      // Get the dates from parameters "from" and "to", and parse to make sure they are dates.
      if ( isset( $_GET['from_month'] ) && isset( $_GET['from_year'] ) ) {
      	$from_date = date_parse( $_GET['from_year'] . '-' . $_GET['from_month'] . '-01' );
      }
      if ( isset( $_GET['to'] ) ) {
      	$to_date = date_parse( $_GET['to_year'] . '-' . $_GET['to_month'] . '-31' );
      }

      Something like that, with perhaps a bit more checking that the month option makes sense and so on.

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.