Date Queries In WordPress 3.7+

Earlier today, a patch for WordPress that I’ve been working on got committed to WordPress trunk. “Trunk” is the in-development version of WordPress and will eventually become the next version of WordPress, in this case 3.7.

My patch introduces the ability to do complex date-based queries for fetching both posts and comments from the WordPress database. In the past, you could select posts that had a specific value for year, month, etc. but there was no way to do things like selecting all posts before (or after) a certain date or selecting all posts between two different dates. With my patch, this and more is now easily possible.

Here’s some examples:

// Get the 10 most recent posts made
// between 9AM and 5PM on weekdays
$some_posts = new WP_Query( array(
	'date_query' => array(
		array(
			'hour' => 9,
			'compare' => '>=',
		),
		array(
			'hour' => 17,
			'compare' => '<=',
		),
		array(
			'dayofweek' => array( 2, 6 ),
			'compare' => 'BETWEEN',
		),
	),
	'posts_per_page' => 10,
) );

// Get all posts from this summer
// June 1st to August 31st, inclusive
// Note that strtotime()-compatible strings can be used
$some_posts = new WP_Query( array(
	'date_query' => array(
		array(
			// String via strtotime()
			'after'     => 'June 1st, 2013',
			// Or if you want, an array
			'before'    => array(
				'year'  => 2013,
				'month' => 8,
				'day'   => 31,
			),
			'inclusive' => true,
		),
	),
	'posts_per_page' => -1,
) );

// Any posts made over a year ago
// but modified in the past month
$some_posts = new WP_Query( array(
	'date_query' => array(
		array(
			'column' => 'post_date_gmt',
			'before' => '1 year ago',
		),
		array(
			'column' => 'post_modified_gmt',
			'after'  => '1 month ago',
		)
	),
	'posts_per_page' => -1,
) );

It works for comments too:

// All comments from post ID 123
// that are within the past week
$some_comments = get_comments( array(
	'post_ID' => 123,
	'date_query' => array(
		array(
			'after' => '1 week ago',
		),
	),
) );

As you can see, the possibilities and combinations of cool things you can do are endless.

Here’s all of the possible arguments:

'date_query' => array(
	'column' => 'optional, column to query against, default is post_date',
	'compare' => 'optional, see WP_Date_Query::get_compare()',
	'relation' => 'optional, OR or AND, how the sub-arrays should be compared, default is AND',
	array(
		'column' => 'see above',
		'compare' => 'see above',
		'after' => 'string or array, see WP_Date_Query::build_mysql_datetime()',
		'before' => 'string or array, see WP_Date_Query::build_mysql_datetime()',
		'inclusive' => 'boolean, for after/before, whether exact value should be matched or not',
		'year' => '4 digit int',
		'month' => 'int, 1-12',
		'week' => 'int, 0-53',
		'day' => 'int, 1-31',
		'hour' => 'int, 0-23',
		'minute' => 'int, 0-60',
		'second' => 'int, 0-60',
	),
	array(
		...
	),
	..
),

Additionally, all of the old-school date and time arguments for WP_Query are now handled by my code as well. They will continue to work as before and you only need to use the date_query parameter if you want more advanced control of your results.

Questions? Anything you want me to clarify? Leave a comment below. 🙂

98 thoughts on “Date Queries In WordPress 3.7+

  1. Pingback: How to list most commented posts with the new date queries in WordPress 3.7+ | Daniele Milana

  2. Hi. I’ve just started playing with WordPress development and I was looking for a way to get comments according to a specific week. Your code is very useful, thanks for that. But a question, how come this is nowhere in the WordPress documentation?

  3. I need a date query to return posts published between X days prior to post date of current post, and the post date of current post (excluding current post).

    Requires a static date range because this is for an email newsletter template. Newsletter will be sent weekly, as a digest of previous week’s posts, and will also be archived as a post, so it must retain correct posts for its’ week.

    • That’s pretty simple to do. Here’s some completely untested code that will likely work:

      // Plenty of other ways to get the "current post"
      // This is just an example
      $current_post = get_post( 123 );
      
      // How many days back?
      $days_back = 7;
      
      // date_query don't accept Unix timestamps currently
      // so we have to use date() to make it a string again
      $after_date = date( 'c', strtotime( "{$days_back} days ago", mysql2date( 'U', $current_post->post_date_gmt ) ) );
      
      $some_posts = new WP_Query( array(
      	'date_query' => array(
      		array(
      			'before' => $current_post->post_date_gmt,
      			'after' => $after_date,
      			'column' => 'post_date_gmt',
      		),
      	),
      	'post__not_in' => array( $current_post->ID ),
      	'posts_per_page' => -1,
      ) );
  4. Thank you for the rapid reply; code works well. I had trouble figuring out the $after_date variable… but your suggestion is spot-on, Mr. Mills.

  5. Hello Alex, I tried to get posts between 2009 and 2010 inclusive the years. So I would expect all posts from 1st January 2009 to 31st December 2010.

    So the ‘date_query’ parameter is:
    array(1) {
    [0]=>
    array(3) {
    [“after”]=>
    array(1) {
    [“year”]=>
    int(2009)
    }
    [“before”]=>
    array(1) {
    [“year”]=>
    int(2010)
    }
    [“inclusive”]=>
    bool(true)
    }
    }

    but the WP_Query Class renders a SQL string within the WHERE clause:

    … WHERE… post_date >= ‘2009-12-31 23:59:59’ AND post_date = ‘2009-01-01 00:00:00’ AND post_date <= '2010-12-31 23:59:59' )

    Did I misunderstood the after-before-inclusive parameters? Or is there another way?

  6. There is an error in my last post: The rendered SQL string is

    … WHERE … post_date >= ‘2009-12-31 23:59:59’ AND post_date = ‘2009-01-01 00:00:00’ AND post_date <= '2010-12-31 23:59:59' )

  7. Pingback: What's wrong with my date_query? « Bay Area Web Design Bay Area Web Design

  8. Pingback: Easy Wordpress date-queries | Code and the Gang

  9. Pingback: Part three

  10. Pingback: part 8

  11. Pingback: PHP Function to Find Last Monday | var_dumpster

  12. Pingback: ??WordPress????#5??????? | ??????

  13. Pingback: A Look Into: WordPress Date Query | vienergie

  14. Pingback: WordPress 3.7 Now Available | Articles From An Actual Living Web Professional

  15. Hi Alex. I need to show 2 posts (one previous posts from today and next post from today) but I can’t figure out how to do it. I figure out how to get current month posts. Can you help me? Thanks in advance.

  16. Pingback: WordPress Date Query

  17. Pingback: More than 1 Year Date Query | ‹src.works/›

Comments are closed.