getNextFireTime of my existing job
Asked Answered
T

3

6

I tried Quartz.com documentation & googled for couple for hours...but could not find single good article on how to get Next Job (which is supposr to fire in future).

I am using CronTrigger Expression to Schedule jobs, using VB.net (winforms). jobs works fine...however I would like my users to see when will it FIRE next. I am storing CronExpression in my database, Can I use that Expression to show next Fire Date/Time to my end users? or if there is any other way possible please advise (with a simple samply).

Thanks

Edit

Following Code Returns next job will fire after 12 minutes instead of 20 minute

    Dim exp As CronExpression = New CronExpression("0 0/20 * * * ?")
    Dim nextFire As String = exp.GetNextValidTimeAfter(DateTime.Now)
    MsgBox(nextFire)
Tightwad answered 29/11, 2012 at 19:9 Comment(1)
Your cronExpression should fire at 00:00 then 00:20 , then 00:40 etc. So if you start it at 00:01 it will run 19 minutes later and if you start 00:19, it will run 1 minute later. (See also cronmaker.com)Smatter
R
7

You can create a new JobKey

JobKey jobKey = new JobKey(jobName, groupName);

and use the key to fetch the job detail:

var detail = scheduler.GetJobDetail(jobKey);

this is a simple function which does what you're looking for:

    private DateTime getNextFireTimeForJob(IScheduler scheduler, string jobName, string groupName = "")
    {
        JobKey jobKey = new JobKey(jobName, groupName);
        DateTime nextFireTime = DateTime.MinValue;

        bool isJobExisting = Scheduler.CheckExists(jobKey);
        if (isJobExisting)
        {
            var detail = scheduler.GetJobDetail(jobKey);
            var triggers = scheduler.GetTriggersOfJob(jobKey);

            if (triggers.Count > 0)
            {
                var nextFireTimeUtc = triggers[0].GetNextFireTimeUtc();
                nextFireTime = TimeZone.CurrentTimeZone.ToLocalTime(nextFireTimeUtc.Value.DateTime);
            }
        }

        return (nextFireTime);
    }

It works only if you have one trigger per job.
If there's more than one trigger in your job you can loop through them:

foreach (ITrigger trigger in triggers)
{
    Console.WriteLine(jobKey.Name);
    Console.WriteLine(detail.Description);
    Console.WriteLine(trigger.Key.Name);
    Console.WriteLine(trigger.Key.Group);
    Console.WriteLine(trigger.GetType().Name);
    Console.WriteLine(scheduler.GetTriggerState(trigger.Key));
    DateTimeOffset? nextFireTime = trigger.GetNextFireTimeUtc();
    if (nextFireTime.HasValue)
    {
        Console.WriteLine(TimeZone.CurrentTimeZone.ToLocalTime(nextFireTime.Value.DateTime).ToString());
    }
}

or using Linq (System.Linq) :

 var myTrigger = triggers.Where(f => f.Key.Name == "[trigger name]").SingleOrDefault();
Redundancy answered 30/11, 2012 at 10:46 Comment(2)
in my api i see "JobKey" as a Member of Class TriggerWrapper, Hence I cant make a new instance of JobKey. I am using quartz.net latest version.Tightwad
Is there a way to find all occurences within a datetime range?Hereditable
S
4

If you already know the cronExpression then you can call GetNextValidTimeAfter , eg

CronExpression exp = new CronExpression("0 0 0/1 1/1 * ? *");
var nextFire = exp.GetNextValidTimeAfter(DateTime.Now);
Console.WriteLine(nextFire);

and if you want more fire times, then

for(int i=0 ; i< 9; i++)
{
    if (nextFire.HasValue)
    {
        nextFire = exp.GetNextValidTimeAfter(nextFire.Value);        
        Console.WriteLine(nextFire);
     }
}

If you are looking for a more general way of showing next fire times for existing jobs, then check out the answer to this question which works even if you aren't using cron expressions. This is for Quartz Version 2

The Quartz Version 1 way of getting job and trigger information is something like the method below.

 public void GetListOfJobs(IScheduler scheduler)
 {
    var query =
        (from groupName in scheduler.JobGroupNames
         from jobName in scheduler.GetJobNames(groupName)
         let triggers = scheduler.GetTriggersOfJob(jobName, groupName)
         select new 
            { 
                groupName, 
                jobName, 
                triggerInfo = (from trigger in triggers select trigger) 
            }
        );

   foreach (var r in query)
   {
       if (r.triggerInfo.Count() == 0)
       {
           var details = String.Format("No triggers found for : Group {0}  Job {1}", r.groupName, r.jobName);
           Console.WriteLine(details);                   
       }

       foreach (var t in r.triggerInfo)
       {
           var details = String.Format("{0,-50} {9} Next Due {1,30:r} Last Run {2,30:r}  Group {3,-30}, Trigger {4,-50} {5,-50} Scheduled from {6:r} Until {7,30:r} {8,30:r} ",
               t.JobName,
               t.GetNextFireTimeUtc().ToLocalTime(), 
               t.GetPreviousFireTimeUtc().ToLocalTime(),
               t.JobGroup, 
               t.Name, 
               t.Description,
               t.StartTimeUtc.ToLocalTime(), 
               t.EndTimeUtc.ToLocalTime(), 
               t.FinalFireTimeUtc.ToLocalTime(),
               ((t.GetNextFireTimeUtc() > DateTime.UtcNow) ? "Active  " : "InActive")
               );

           Console.WriteLine(details);

       }
   }

}

Smatter answered 29/11, 2012 at 22:27 Comment(4)
i am not using Quartz.net 2.0, I tried to use 2.0 with my project and all of my code failed to compiled:(Tightwad
There was quite a few api changes going from V1 to V2, but they are tedious but fairly straightforward. I think the CronExpression.GetNextValidTimeAfter method is the same, but I have included a sample showing how to retrieve existing jobs and triggers under version 1.Smatter
Thanks, do you know where can i find examples for creating jobs with v2? Official website has no exsmples for new version.Tightwad
There is an Examples project in the source which you can download from github.com/quartznet or for a simple example see jvilalta.blogspot.co.uk/2011/03/… or just google for JobBuilder.Create Don't forget to check out the migration guide quartznet.sourceforge.net/migration_guide.htmlSmatter
B
0

I had problem where i am getting next execution time even for the date which are past the end time. Following is my implementation which eventually returning the correct result in Quartz 3.0.4

internal static DateTime? GetNextFireTimeForJob(IJobExecutionContext context)
        {
            JobKey jobKey = context.JobDetail.Key;
            DateTime? nextFireTime = null;

            var isJobExisting = MyQuartzScheduler.CheckExists(jobKey);
            if (isJobExisting.Result)
            {
                var triggers = MyQuartzScheduler.GetTriggersOfJob(jobKey);

                if (triggers.Result.Count > 0)
                {
                    var nextFireTimeUtc =  triggers.Result.First().GetNextFireTimeUtc();
                    if (nextFireTimeUtc.HasValue)
                    {
                        nextFireTime = TimeZone.CurrentTimeZone.ToLocalTime(nextFireTimeUtc.Value.DateTime);
                    }
                }
            }

            return nextFireTime;
        }
Beaubeauchamp answered 2/5, 2018 at 14:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.