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 is actually complicated. 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
.)
Is there a way to do a OR Date ? Like I want to search the content for that date OR for the published date… Since I have field with date in the content, it block each others.
I think the easiest solution for that is to add the published date to the content in the indexing, so you can just search the content.
I figured another mechanism with instruction injected in the search query.
https://gist.github.com/jonathanlaf/5f57436ad1129dbbafac1484f981a111
Hello thsi is great and works well, is it possible to extend this so that I can simply add a the year in the search and only results from that year would show?
Gordon, sure. You need a function that scans the search query for digits that look like years and if it spots one, it removes it and converts it to a date query. I posted the answer here.
Wow – that was quick! It works like a charm, although I had to paste the code into my functions before the ‘Natural language date queries’ function, as I understand it – the year query has to look for the four digits first and then reset the query?
Is it possible to have the results run with the oldest date entires first?
Quick update – I’ve found another thread with the fix
https://www.relevanssi.com/user-manual/filter-hooks/relevanssi_orderby-relevanssi_order/
If you are running both of these functions together, you probably want the natural language date query to run first – if the whole search string is a date, process it that way instead of looking just for the year. The natural language date query will empty the search string afterwards, so the year query does nothing after that.
So, change
add_filter( 'relevanssi_modify_wp_query', 'rlv_date_query' );
toadd_filter( 'relevanssi_modify_wp_query', 'rlv_date_query', 9);
. This will make therlv_date_query()
function always run first and you’ll get more consistent behaviour that doesn’t depend of the order of the functions in the file – nothing should depend on a random factor like that, reorganising your functions.php should never change your site functionality!Thanks Mikko for your follow up – I understood some of that – are you saying that I just need this one modified function https://www.relevanssi.com/knowledge-base/year-filter-from-the-search-query/ to do both the ‘natural language date query’ and the ‘ year only’ search? Could you clarify please!
Gordon, keep both functions. Just change the one line as described – add that ”, 9” – that’s all.
I’m so sorry – am I missing something – this is what I have and it’s not working
/* Search / Relevanssi / Natural-language date queries
————————————————————————————— */
add_filter( ‘relevanssi_modify_wp_query’, ‘rlv_date_query’, 9 );
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;
}
/* Search / Relevanssi / Year only filter
————————————————————————————— */
add_filter( ‘relevanssi_modify_wp_query’, function( $query ) {
$m = preg_match( ‘/\b\d{4}\b/’, $query->query_vars[‘s’], $matches );
if ( 1 === $m ) {
$year = $matches[0];
if ( $year > 1900 && $year query_vars[‘s’];
$query->query_vars[‘year’] = $year;
$query->query_vars[‘s’] = str_replace( $year, ”, $query->query_vars[‘s’] );
}
}
return $query;
} );
add_filter( ‘posts_pre_query’, function( $a, $b ) {
global $wp_query, $relevanssi_original_query;
$wp_query->query_vars[‘s’] = $relevanssi_original_query;
return $a;
}, 100, 2 );
Gordon, you have some serious typos in the “year only” filter. It should look like this.
Oh – that’s bad! Apologies… I’ve corrected the code but it still doesn’t see to be working as expected. I could give you a login?
/* Search / Relevanssi / Natural-language date queries
————————————————————————————— */
add_filter( ‘relevanssi_modify_wp_query’, ‘rlv_date_query’, 9);
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;
}
/* Search / Relevanssi / Year only filter
————————————————————————————— */
add_filter( ‘relevanssi_modify_wp_query’, function( $query ) {
$m = preg_match( ‘/\b\d{4}\b/’, $query->query_vars[‘s’], $matches );
if ( 1 === $m ) {
$year = $matches[0];
if ( $year > 1900 && $year query_vars[‘s’];
$query->query_vars[‘year’] = $year;
$query->query_vars[‘s’] = str_replace( $year, ”, $query->query_vars[‘s’] );
}
}
return $query;
} );
Gordon, ah, I see the comments here break the code. If everything’s broken as in fatal error, make sure the code looks like what’s here.
If there’s no fatal error but things don’t work, please explain how it’s not working. I tested this on my test site and it’s working for me: a year search works, and if it’s a full date, that too works.
Ok so… here’s an image file of the two functions…
https://www.lonelyshoes.co.uk/screengrabs/functions-v001.png
please try the search on here https://www.lonelyshoes.co.uk
If I search ‘blue’ for example I get results
https://www.lonelyshoes.co.uk/?s=blue
(Normally at the top of the page I would see “Found:” – followed by the search term which is now blank)
If I search ‘2024’ – I get no results at all
If I search ‘January+2024’ – I get no results
https://www.lonelyshoes.co.uk/?s=January+2024
Gordon, ok, I see. First of all, the missing search term is a problem in my code. I updated the second function here so that it doesn’t remove the search terms accidentally.
“January 2024” finds no results, because you don’t have a post on January 1st. The natural language date query function doesn’t understand using only months, it’s either day, month, year or day, month (in the current year). So “november 17th 2019” works, because you have a post on that date. It’s possible to modify the function so that it ignores days.
The I built the year filter is built under the assumption there’s also a search term. If you search for “shoe 2024”, you get results. It should also work with just a year number; not sure why it’s not working on your site, and I can’t tell just from the front end.
Thanks again for helping with this and taking the time to explain. I understand better now what kind of search terms I can use with the natural ‘Natural-language date query’ . It’s not exactly what I was looking for, as I thought it might be interesting to see all the shoes that were found in April across all the years, or July the 4th across the years. Rather than to search a specific day, month and year. However by using your second function on it’s own I it appears I can now search for shoes via a single year search, which is quite good fun. So if I search for shoes using the term ‘2024’ I only get results for posts from ‘2024’. Thanks again and keep up the good work. It’s a great search system – I’m revisiting it after not using it for a few years. Best Gordon