Schedule event every second thursday of the month

The question:

I’m working on an email system and they want it automated to send out emails every second thursday of the month. I’ve got the PHP sorted out and ready to fire a callback to send the emails, but I’m a complete newbie when it comes to cron and scheduling events.

Essentially, I have this:

echo date('M d Y', strtotime('first thursday this month'));
echo date('M d Y', strtotime('-5 hours'));
if(date('MdY',strtotime('first thursday this month')) == date('MdY',strtotime('-5 hours'))){
    send_emails();
}else{
    echo 'DO NOT SEND EMAILS';
}

So it checks if the current day (-5 hours for timezone) is the ‘second’ thursday of the month (PHP bugs out and adds a week to the date).

I’m not sure if that’s what I’m going to need to do to schedule an event or what. Currently it runs when the plugin page is visited, but I’d like it to be its own process that runs regardless or not whether a page is visited.

Any help is greatly appreciated!

Thanks!

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

WordPress lets you add custom cron schedules, which is normally what you’d want to do in this situation, in conjunction with wp_schedule_event(). But, they work based on intervals rather than specific dates/times. For instance,

add_filter( 'cron_schedules', 'addCustomCronIntervals' );
function addCustomCronIntervals( $schedules )
{
    $schedules[ self::PREFIX . 'debug' ] = array(
        'interval'  => 60 * 2,
        'display'   => 'Every 2 minutes'
    );

    return $schedules;
}

So, instead, you could do it with your current approach, but you’ll also need to setup a transient to make sure the e-mails aren’t sent every time the page loads.

$firstThursday = date_i18n( 'Ymd', strtotime( 'first thursday this month', current_time( 'timestamp' ) ) );
$today = date_i18n( 'Ymd', current_time( 'timestamp' ) );
if( strcmp( $firstThursday, $today ) === 0 && ! get_transient( 'alreadySentEmails' ) )
{
    send_emails();
    set_transient( 'alreadySentEmails', 60 * 60 * 24 );
}

Note that you should be using WordPress’ date_i18n() and current_time() functions instead of PHP’s date() and time() – which strtotime() implicitly calls -, so that time zones are handled correctly.

Also note that some relative formats are new to PHP 5.3, so make sure your server is current.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment