Hello Quartz community! 👋
I've recently started introducing Quartz in our product and encountered with some issues. Here is one of this.
We allow user to specify some schedule for product tasks. The schedule converts to Quartz-triggers (one or a few). The schedule can be complex and to improve user experience, we provide an estimation feature that shows a preview of fire times for a given interval (from and to date times).
Initially, I relied on TriggerUtils.ComputeFireTimesBetween, but encountered unexpected behavior. The method modified StartTimeUtc and EndTimeUtc of trigger and I got "wierd" set of fire times. Here’s a test that reproduces the issue:
using Quartz;
using Quartz.Spi;
using Xunit.Abstractions;
namespace QuartzPitfalls;
public class TriggerUtilsTests
{
private readonly ITestOutputHelper _testOutputHelper;
public TriggerUtilsTests(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
[Theory]
[InlineData("2026-01-01 08:00:00Z","2026-01-07 08:00:01Z")] // Estimation interval matches trigger start and end
[InlineData("2026-01-01 07:50:00Z","2026-01-07 08:00:01Z")] // Estimation interval starts 10 minutes earlier than trigger
public void Trigger_should_run_only_first_week_of_january_2026(string fromUtc, string toUtc)
{
// Arrange: Start in the first week of January 2026 for one week
var startAt = DateTimeOffset.Parse("2026-01-01 08:00:00Z"); // Start at 8.00 exactly
var endAt = DateTimeOffset.Parse("2026-01-07 08:00:01Z"); // End after a week
var trigger = TriggerBuilder.Create()
.StartAt(startAt)
.EndAt(endAt)
.WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever()) // Each day
.Build();
ICalendar? calendar = null;
// Act
var from = DateTimeOffset.Parse(fromUtc);
var to = DateTimeOffset.Parse(toUtc);
var actualFireTimes = TriggerUtils.ComputeFireTimesBetween((IOperableTrigger) trigger, calendar, from, to);
// Assert: Run each day at 8.00 exactly for one week
var expectedFireTimes = new[]
{
"2026-01-01 08:00:00Z",
"2026-01-02 08:00:00Z",
"2026-01-03 08:00:00Z",
"2026-01-04 08:00:00Z",
"2026-01-05 08:00:00Z",
"2026-01-06 08:00:00Z",
"2026-01-07 08:00:00Z",
};
foreach (var actualFireTime in actualFireTimes)
_testOutputHelper.WriteLine($"{actualFireTime.UtcDateTime}");
Assert.Equal(expectedFireTimes.Select(DateTimeOffset.Parse), actualFireTimes);
}
}
If I shift start estimation interval then the schedule breaks:

The trigger is supposed to run at 8:00 but it shifts start at to 07.50:

I found the issue kinda related to my problem: #148
As far as I understand, this behavior is intentional and likely won’t change. But I’d like to propose:
- Add extra method that do not modified existing
StartTimeUtc and EndTimeUtc if they already set
- May
from and to should be renamed to start or end just to emphasize that the arguments of TriggerUtils.ComputeFireTimesBetween related to trigger properties
To work around the issue, I ended up writing my own version that builds on top of ComputeFireTimes, with support for fromUtc without modifying the trigger’s properties: ComputeFireTimes(ITrigger trigg, ICalendar? cal, DateTimeOffset fromUtc, int numTimes)
Thanks in advance for any insights!
Hello Quartz community! 👋
I've recently started introducing Quartz in our product and encountered with some issues. Here is one of this.
We allow user to specify some schedule for product tasks. The schedule converts to Quartz-triggers (one or a few). The schedule can be complex and to improve user experience, we provide an estimation feature that shows a preview of fire times for a given interval (
fromandtodate times).Initially, I relied on
TriggerUtils.ComputeFireTimesBetween, but encountered unexpected behavior. The method modifiedStartTimeUtcandEndTimeUtcof trigger and I got "wierd" set of fire times. Here’s a test that reproduces the issue:If I shift start estimation interval then the schedule breaks:
The trigger is supposed to run at 8:00 but it shifts start at to 07.50:
I found the issue kinda related to my problem: #148
As far as I understand, this behavior is intentional and likely won’t change. But I’d like to propose:
StartTimeUtcandEndTimeUtcif they already setfromandtoshould be renamed tostartorendjust to emphasize that the arguments ofTriggerUtils.ComputeFireTimesBetweenrelated to trigger propertiesTo work around the issue, I ended up writing my own version that builds on top of
ComputeFireTimes, with support forfromUtcwithout modifying the trigger’s properties:ComputeFireTimes(ITrigger trigg, ICalendar? cal, DateTimeOffset fromUtc, int numTimes)Thanks in advance for any insights!