Scheduling a Batch job at a particular time

You need to transform your datetime to the schedule format. More info here

Example

String day = string.valueOf(system.now().day());
String month = string.valueOf(system.now().month());
String hour = string.valueOf(system.now().hour());
String minute = string.valueOf(system.now().minute() + 1);
String second = string.valueOf(system.now().second());
String year = string.valueOf(system.now().year());
String strSchedule = '0 ' + minute + ' ' + hour + ' ' + day + ' ' + month + ' ?' + ' ' + year;
System.schedule('Sample Job', strSchedule, new sampleapexbatch());

I usually include a few helper methods in any Schedulable class that needs to run at a given time as determined by Apex logic that's more complex than a simple cron expression. You can then call Database.executeBatch() from your Schedulable class's execute method:

public class Schedule_SomethingAwesome implements Schedulable {

    public static final String JOBNAME = 'Schedule_SomethingAwesome';

    public void execute(SchedulableContext sc) {
        Database.executeBatch(new AwesomeBatchJob(), 200);
    }

    public static void scheduleMe(DateTime runtime) {
        unscheduleMe();
        runtime = (runtime!=null) ? runtime : System.now().addMinutes(15);
        if ( runtime >= System.now() ) {
            DateTime next = runtime;
            String cron = next.second() + ' ' + next.minute() + ' ' + next.hour() + ' ' +
                            next.day() + ' ' + next.month() + ' ? ' + next.year();

            Id jobId = System.schedule(JOBNAME, cron, new Schedule_SomethingAwesome());
            // do something with the jobId, like keep track of the job in a custom setting, perhaps?
        }
    }

    public static void unscheduleMe() {
        for ( CronTrigger ct : [select Id from CronTrigger where CronJobDetail.Name like :(JOBNAME+'%')] ) {
            System.abortJob(ct.Id);
        }
    }
}

I find this useful because then I can kill kill the job before it runs if I need to. Alternatively, you can use System.scheduleBatch() as you suggested, by specifying the length of time in minutes until the job should fire:

public static void scheduleBatch(DateTime runtime) {
    DateTime now = System.now();
    Integer delay = Integer.valueOf((runtime.getTime()-now.getTime())/1000/60);
    System.scheduleBatch(new AwesomeBatchJob(), 'AwesomeBatchJob'+System.now().getTime(), delay);
}

If you refer to Using the System.scheduleBatch Method

You can use the System.scheduleBatch method to schedule a batch job to run once at a future time. The System.scheduleBatch method takes the following parameters.

  • An instance of a class that implements the Database.Batchable interface.
  • The job name.
  • The time interval, in minutes, after which the job starts executing.

This example schedules a batch job to run one minute from now by calling System.scheduleBatch.

System.scheduleBatch(sampleapexbatch, 'job example', 1);