WP Cron – Run Cron after evey 15 minutes at a specific time for the next three hours

Setup WordPress Cron Events

Let’s say you want to start the cron at 6PM and keep running the cron after every 15 minutes till 9PM (for 3 hours). Then all cron stops.

Note: for the simplicity of implementation, all time entry in the CODE is considered to be GMT/UTC.

For this, you need to schedule two cron events, one will start at 6PM and keep running at every 15 minutes from 6PM. The other one will be one time cron event that’ll run at 9PM. This one will stop the other cron.

The plugin CODE will be something like the following:

<?php
/*
Plugin Name:  WPSE Custom Cron
Plugin URI:   https://wordpress.stackexchange.com/a/309973/110572
Description:  Custom Cron Plugin
Version:      1.0.0
Author:       Fayaz Ahmed
Author URI:   https://www.fayazmiraz.com/
*/

add_action( 'wpse_custom_cron_event',        'wpse_custom_cron' );
add_action( 'wpse_custom_cron_event_stop',   'wpse_custom_cron_stop' );

function wpse_custom_cron() {
    // Your Custom Cron CODE HERE
}

function wpse_custom_cron_start() {
    // Calculate the start time: e.g. whenever the next 6:00PM (UTC) is.
    $cron_start_time = strtotime( "today 6:00pm" );
    // If 6PM has already passed today, set it to 6PM next day
    if( $cron_start_time < time() ) {
        $cron_start_time = $cron_start_time + 24 * HOUR_IN_SECONDS;
    }

    if ( ! wp_next_scheduled( 'wpse_custom_cron_event' ) ) {
        wp_schedule_event( $cron_start_time, 'fifteen_minutes', 'wpse_custom_cron_event' );
    }

    if ( ! wp_next_scheduled( 'wpse_custom_cron_event_stop' ) ) {
        // this 1 time cron will stop the original cron 'wpse_custom_cron_event' after 3 hours of starting 
        $cron_stop_time = $cron_start_time + 3 * HOUR_IN_SECONDS;
        wp_schedule_single_event( $cron_stop_time, 'wpse_custom_cron_event_stop' );
    }
}

function wpse_custom_cron_stop() {
    // removing all possible custom cron events named 'wpse_custom_cron_event'
    while( false !== wp_unschedule_event( wp_next_scheduled( 'wpse_custom_cron_event' ), 'wpse_custom_cron_event' ) ) {}
}

// Add a 15 minutes custom cron schedule
add_filter( 'cron_schedules', 'wpse_custom_cron_schedule' );
function wpse_custom_cron_schedule( $schedules ) {
    $schedules['fifteen_minutes'] = array(
        'interval' => 15 * 60,
        'display'  => esc_html__( 'Every Fifteen Minutes' ),
    );
    return $schedules;
}

// schedule the cron event on plugin activation
register_activation_hook( __FILE__, 'wpse_custom_cron_plugin_activation' );
function wpse_custom_cron_plugin_activation() {
    wpse_custom_cron_start();
}
// remove the cron event on plugin deactivation
register_deactivation_hook( __FILE__, 'wpse_custom_cron_plugin_deactivation' );
function wpse_custom_cron_plugin_deactivation() {
    wpse_custom_cron_stop();

    // in case the stop event didn't run yet
    while( false !== wp_unschedule_event( wp_next_scheduled( 'wpse_custom_cron_event_stop' ), 'wpse_custom_cron_event_stop' ) ) {}
}

This sample plugin will start the cron on plugin activation, but if needed, you can edit the CODE to start the cron by other means as well (say using a button click in admin panel) using the wpse_custom_cron_start() function.

Also, if you want to run the same cron everyday 6PM (not just one time after activation), then simply change the wp_schedule_single_event call in wpse_custom_cron_start() function to:

wp_schedule_event( $cron_stop_time, 'daily', 'wpse_custom_cron_event_stop' );

Note: Event/Cron created with arguments

If you create the event/cron with an argument, you must also stop the event with the exact same argument.

For example, if you created the event like this (in wpse_custom_cron_start() function of the above CODE):

....
wp_schedule_event( $cron_start_time, 'fifteen_minutes', 'wpse_custom_cron_event', $args1 );
....
wp_schedule_single_event( $cron_stop_time, 'wpse_custom_cron_event_stop', $args2 );

then when stopping the events, you must also use the exact same argument in wp_next_scheduled() function call. So the stop CODE will become like:

....
while( false !== wp_unschedule_event( wp_next_scheduled( 'wpse_custom_cron_event', $args1 ), 'wpse_custom_cron_event' ) ) {}
....
while( false !== wp_unschedule_event( wp_next_scheduled( 'wpse_custom_cron_event_stop', $args2 ), 'wpse_custom_cron_event_stop' ) ) {} 

Again, remember, it has to be the exact same argument, even different data type will not work. For example, in the following CODE, $args1 and $args2 are NOT the same, but $args1 and $args3 are same:

$args1 = array( 'key' => 1 );
$args2 = array( 'key' => '1' );
$args3 = array( 'key' => 1 );

because '1' is string and 1 is a number.

This is important because, sometimes people save the arguments in database as key value pairs, & when they use it again later, the value from database doesn’t work for arguments that were numbers, as the numbers are converted to strings when retrieved from database. So you must convert them back to numbers when passing the argument to the wp_next_scheduled() function.

for more information, check the documentation:

Running the Cron:

The best way to run WordPress cron is to set define('DISABLE_WP_CRON', true); in wp-config.php file and then run the cron from system crontab as described in this post.

Use external cron service:

In case you cannot set crontab, you may use an external cron service like cron-job.org and set the cron accordingly.

For example, for the above cron events, you may set a single cron job there with a setting like:

cron-job.org settings

Here, all the values of Days of Month, Days of Week & Months are selected; and Hours selected to 18, 19, 20 and Minutes selected to 0, 15, 30, 45. Which means: run cron Everyday from 6PM to 9PM (GTM is set as time zone from account setting) on 0th, 15th, 30th and 45th minute (i.e. at 15 minutes interval).

Cron Check + Manual Cron:

You may check if your cron schedules properly using WP Control plugin. This plugin can also be used to set up custom cron events and intervals.

Leave a Comment