Replace "lablel" and "goto" in CrontabSchedule.cs (no issue)
mserafym opened this issue · comments
NCrontab/NCrontab/CrontabSchedule.cs
Lines 285 to 359 in 26c223f
new code (start with 285):
/**/ while(true)
{
if (day == nil)
{
second = seconds.GetFirst();
minute = _minutes.GetFirst();
hour = _hours.GetFirst();
day = _days.GetFirst();
month++;
}
else if (day > baseDay)
{
second = seconds.GetFirst();
minute = _minutes.GetFirst();
hour = _hours.GetFirst();
}
//
// Month
//
month = _months.Next(month);
if (month == nil)
{
second = seconds.GetFirst();
minute = _minutes.GetFirst();
hour = _hours.GetFirst();
day = _days.GetFirst();
month = _months.GetFirst();
year++;
}
else if (month > baseMonth)
{
second = seconds.GetFirst();
minute = _minutes.GetFirst();
hour = _hours.GetFirst();
day = _days.GetFirst();
}
//
// Stop processing when year is too large for the datetime or calendar
// object. Otherwise we would get an exception.
//
if (year > Calendar.MaxSupportedDateTime.Year)
return null;
//
// The day field in a cron expression spans the entire range of days
// in a month, which is from 1 to 31. However, the number of days in
// a month tend to be variable depending on the month (and the year
// in case of February). So a check is needed here to see if the
// date is a border case. If the day happens to be beyond 28
// (meaning that we're dealing with the suspicious range of 29-31)
// and the date part has changed then we need to determine whether
// the day still makes sense for the given year and month. If the
// day is beyond the last possible value, then the day/month part
// for the schedule is re-evaluated. So an expression like "0 0
// 15,31 * *" will yield the following sequence starting on midnight
// of Jan 1, 2000:
//
// Jan 15, Jan 31, Feb 15, Mar 15, Apr 15, Apr 31, ...
//
var dateChanged = day != baseDay || month != baseMonth || year != baseYear;
if (day > 28 && dateChanged && day > Calendar.GetDaysInMonth(year, month))
{
if (year >= endYear && month >= endMonth && day >= endDay)
return endTime;
day = nil;
continue;
}
break;
} /**/
(edited by @atifaziz to fix code formatting issues with the original post)
The very exceptional use of goto
here is completely intentional. An infinite while-loop with a flow continuation and break statement doesn't tell you much about what's going on, especially because the loop body is large. A goto
with a clearly named label (telling you that it's going to jump to a point where the day and month computation will be retried) on the other hand does seem more meaningful.
As this is a non-issue, I'm going to close it.
Thank you for response and the explanation! Now I understood the point. Most likely, I'm just "afraid" of goto