Cronos icon indicating copy to clipboard operation
Cronos copied to clipboard

GetNext ? issue ?

Open TheCamel opened this issue 8 months ago • 4 comments

Hi, may be I am wrong somewhere but with the following cron, 0 18 16 ? * SUN,MON,TUE,WED,THU,FRI,SAT

// I call it at <00:16:16 22/04/2025>

while (!cancellationToken.IsCancellationRequested)
{
DateTime now = DateTime.UtcNow;
DateTime? nextExecTime;
CronExpression nextExecCron = CronExpression.Parse(treatment.Cron, CronFormat.IncludeSeconds);
nextExecTime = nextExecCron.GetNextOccurrence(now.**AddMinutes**(1));

// I got <00:18:16 22/04/2025>

int delay = (int)(nextExecTime.Value - DateTime.Now).TotalMilliseconds;
 
//wait for delay

} //while

I call it at <00:16:18 TUE> + ONE MINUTE

I got <00:18:16 22/04/2025> ==> SO BACK IN TIME ?? should have <00:18:16 23/04/2025>

if i debug and wait for several minutes, i got the same result...

thanks for your help

TheCamel avatar Apr 23 '25 08:04 TheCamel

It seams that with local time, it works...? but why ?

TheCamel avatar Apr 23 '25 11:04 TheCamel

The delay variable is calculated using the DateTime.Now property, which returns a date time in a local time zone, while next execution is using UTC. Try to modify the line to the following one:

int delay = (int)(nextExecTime.Value - DateTime.UtcNow).TotalMilliseconds;

odinserj avatar Apr 24 '25 08:04 odinserj

ok, may be I do a small mistake on this, but it is not the delay calculation the problem. It is the GETNEXT !

this code is not working : the second call to getnext return the same date even one minute after and delay becomes negative

do you see what is wrong ?

while (!cancellationToken.IsCancellationRequested)
{
	try
	{
		DateTime now = DateTime.UtcNow;
		DateTime? nextExecTime;

		CronExpression nextExecCron = CronExpression.Parse("45 14 ? * SUN,MON,TUE,WED,THU,FRI,SAT", CronFormat.Standard);
		nextExecTime = nextExecCron.GetNextOccurrence(now);

		if (nextExecTime > now.Date.AddDays(1))
		{ //si demain on arrete
			nextExecTime = null;
		}

		if (nextExecTime.HasValue)
		{
			int delay = (int)(nextExecTime.Value - now).TotalMilliseconds;
			if (delay > 0)
			{
				_tracer.Debug("schedule {Id} is awaited for {delay}", treatment.ScheduleId, delay);
				
				cancellationToken.WaitHandle.WaitOne(delay);

				if (!cancellationToken.IsCancellationRequested)
				{
					//execute
					
					//we wait the minute after...
					cancellationToken.WaitHandle.WaitOne(60000);
				}
			}
			else { return; }
		}
		else { return; }
	}
	catch (Exception ex)
	{
	}
}

TheCamel avatar Apr 24 '25 12:04 TheCamel

this code works

try
{
				DateTimeOffset DTnow = DateTimeOffset.Now;
				DateTime? nextExecTime;

				CronExpression nextExecCron = CronExpression.Parse(treatment.Cron, CronFormat.Standard);
				DateTimeOffset? next = nextExecCron.GetNextOccurrence(DTnow, TimeZoneInfo.Local);
				nextExecTime = next?.DateTime;

				if (nextExecTime > DTnow.Date.AddDays(1))
				{ //si demain on arrete
					nextExecTime = null;
				}

				if (nextExecTime.HasValue)
				{
					int delay = (int)(nextExecTime.Value - DateTime.Now).TotalMilliseconds;
					if (delay > 0)
					{
						_tracer.Debug("schedule {Id} is awaited for {delay}", treatment.ScheduleId, delay);
						
						cancellationToken.WaitHandle.WaitOne(delay);

						if (!cancellationToken.IsCancellationRequested)
						{
							_tracer.Debug("schedule {Id} is executed now", treatment.ScheduleId);
							new DdpScheduleCRUD(_connectionProvider).ApplySupSchedule(treatment.ScheduleId);
							
							//we wait the minute after...
							cancellationToken.WaitHandle.WaitOne(60000);
						}
					}
					else { return; }
				}
				else { return; }
}

TheCamel avatar Apr 24 '25 13:04 TheCamel