0

I was searching for the easiest/fastest way to get the accurate date range for copyright notices in the footer. The copyright notice shouldn't only contain the year, but as well take month and day into account and consider the post type. So a custom post type of "Event" could have a different copyright date range than a blog "post" post type.

2

There was an issue with the code originally posted by kaiser in that it queried for year, month and day distinctly resulting in values representing "the largest month for any date" or the "smallest day for any date" rather than values representing the MAX and MIN dates globally.

I altered that original code to query for globally MAX and MIN dates and with kaiser's blessing am posting it here. The following returns the correct dates when tested on my server but testing has not been by any means exhaustive.

function get_copyright_daterange_v2()
{
    global $wpdb;
    static $range = array();

    if ( ! empty( $range ) )
        return $range;

    return $range = array_shift( $wpdb->get_results( $wpdb->prepare( "
        SELECT
            MIN( post_date ) AS first,
            MAX( post_date ) AS last
        FROM
            {$wpdb->posts}
        WHERE
            post_type = %s
            AND NOT post_status = 'auto-draft'
            AND NOT post_status = 'inherit'
            AND NOT post_status = 'trash'
        ",
        is_admin() ? get_current_screen()->post_type : get_queried_object()->post_type
    ) ) );
}

$date_range = get_copyright_daterange_v2();
printf(
    '© %s — %s',
    date_i18n( 
        get_option( 'date_format' ),
        strtotime( $date_range->first ),
        true // GMT
    ),
    date_i18n( 
        get_option( 'date_format' ),
        strtotime( $date_range->last ),
        true // GMT
    )
);
2

The following function queries for the maximum and minimum dates for the currently displayed post type (single or archive). It works in the admin UI as well as in the front end/Theme. It only takes a limited set of post status into account and needs to be altered/extended if you want to exclude status like pending, future, etc. as well.

function get_copyright_daterange()
{
    global $wpdb;
    static $range = array();

    if ( ! empty( $range ) )
        return $range;

    return $range = array_shift( $wpdb->get_results( $wpdb->prepare( "
        SELECT
            MIN( YEAR( post_date ) )  AS first_year,
            MIN( MONTH( post_date ) ) AS first_month,
            MIN( DAY( post_date ) )   AS first_day,
            MAX( DAY( post_date ) )   AS last_day,
            MAX( MONTH( post_date ) ) AS last_month,
            MAX( YEAR( post_date ) )  AS last_year
        FROM
            {$wpdb->posts}
        WHERE
            post_type = %s
            AND NOT post_status = 'auto-draft'
            AND NOT post_status = 'inherit'
            AND NOT post_status = 'trash'
        ",
        is_admin() ? get_current_screen()->post_type : get_queried_object()->post_type
    ) ) );
}

You can then simply call it like this:

$date_range = get_copyright_daterange();
printf(
    '© %s — %s',
    date_i18n( 
        get_option( 'date_format' ),
        strtotime( "{$date_range->first_year}-01-01" ),
        true // GMT
    ),
    date_i18n( 
        get_option( 'date_format' ),
        strtotime( "{$date_range->last_year}-01-01" ),
        true // GMT
    )
);

The function that does the query saves it into a static variable, so you can call it multiple times on a single page without doing multiple DB queries.

As you can see, I set the third argument for date_i18n(), which is the GMT offset, to true. If you don't want that, but still have the GMT offset, you could as well just use post_date_gmt inside the query.

EDIT

As @s_ha_dum pointed out, the above query will result in a "weird" behavior: It queries the year, month and day distinctly. So the query won't work when you try to build the actually first/last date from it. But it will work, if you are just searching for either one of them. Originally I did use that for a date based navigation/pagination.

  • The earliest "post" post type on my dev server is 1923-09-06 and the latest is 2013-06-29 but your code returns "January 1, 1923" and "September 29, 2013". Since you are searching for MAX and MIN year, month, and day distinctly you are disconnecting them from each other and getting "the largest month for any date" or the "smallest day for any date", for example. I don't think that is expected behavior but maybe that is what you want. I have modified your code to give what to my mind would be the correct dates but I'd have to post it as an answer. I thought I'd mention the issue first. – s_ha_dum Jul 7 '13 at 15:46
  • @s_ha_dum Yes, you're completely right. I was using this originally for date based navigation and post type limits, but had to think of a broader scenario to post a Q/A here to share some knowledge. And yes, please post your answer. I'll reduce mine to only the years so it stays valid. Thanks! – kaiser Jul 7 '13 at 16:00
  • Bascically exactly what I did. :) No need for both answers. I'm deleting mine. – s_ha_dum Jul 7 '13 at 16:34
  • @s_ha_dum Don't delete it. I'll roll mine back and add an extra edit to note about what happens in there. – kaiser Jul 7 '13 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.