Business-hours, availability, downtime, capacity, and SLA working-time calculations for .NET.
TimeGrid.NET turns schedule rules into a queryable operational timeline. Define working hours, lunch breaks, holidays, maintenance windows, capacity overrides, and named schedule entries; serialize the source definition as JSON; compile it once; then answer timestamp and range queries quickly.
Use it for factory calendars, machine availability, SLA clocks, business-hour math, capacity-aware slot search, and systems that need a dependable time layer before they schedule, simulate, dispatch, or report.
Not a scheduler. Not a simulator. Not a timezone database. TimeGrid.NET is the availability and working-time engine those systems can depend on.
dotnet add package TimeGrid.NETCalculate an SLA due date while skipping lunch, nights, weekends, and one-off closures:
using TimeGrid;
var calendar = TimeGridCalendar
.Weekdays(new TimeOnly(9, 0), new TimeOnly(17, 0))
.BreakWeekdays(new TimeOnly(12, 0), new TimeOnly(13, 0))
.Close(new DateOnly(2026, 1, 1))
.SetClosedWindow("company-offsite", new DateTime(2026, 1, 7, 13, 0, 0), new DateTime(2026, 1, 7, 17, 0, 0));
var openedAt = new DateTime(2026, 1, 5, 11, 0, 0);
var trace = calendar.At(openedAt).TraceWorkDuration(10.Hours());
Console.WriteLine(trace.Result);
foreach (var step in trace.Steps)
{
Console.WriteLine($"{step.Window}: {step.Duration}");
}Runnable examples live in examples/:
dotnet run --project examples/TimeGrid.Examples -- all
dotnet run --project examples/TimeGrid.Examples -- sla
dotnet run --project examples/TimeGrid.Examples -- manufacturing
dotnet run --project examples/TimeGrid.Examples -- fleet
dotnet run --project examples/TimeGrid.Examples -- json
dotnet run --project examples/TimeGrid.Examples -- overnight| Example | What it shows |
|---|---|
sla |
Business-hour due dates and consumed working windows. |
manufacturing |
Downtime, capacity boosts, and first slot with enough capacity. |
fleet |
Several compiled machine timelines queried at the same timestamp. |
json |
JSON schedule templates plus per-machine exceptions. |
overnight |
Open rules that cross midnight and breaks inside overnight shifts. |
| Question | API |
|---|---|
| Can this machine, team, or queue work now? | timeline.Analyze(now).CanWork |
| What is the effective capacity at this timestamp? | analysis.Capacity |
| Which state window contains this timestamp? | analysis.CurrentWindow |
| When does the state change next? | analysis.NextTransition |
| Why is this timestamp blocked or boosted? | calendar.At(now).Analyze().Matches |
| How much usable business time exists in a range? | timeline.GetWorkingDuration(start, end) |
| Where is the first continuous slot with enough capacity? | timeline.FindFirstSlot(start, 2.Hours(), 3) |
TimeGrid.NET stores source rules, not compiled runtime state. That makes definitions easy to save, review, ship, and apply to many operational entities:
using TimeGrid;
var templateJson = TimeGridCalendar
.Create()
.OpenWeekdays(new TimeOnly(7, 0), new TimeOnly(19, 0))
.BreakWeekdays(new TimeOnly(12, 0), new TimeOnly(12, 45))
.Capacity(3)
.ToJson(indented: true);
var template = TimeGridCalendar.FromJson(templateJson).ToDefinition();
var machine = template
.ToCalendar()
.SetClosedWindow("machine-42-maintenance", new DateTime(2026, 1, 5, 15, 0, 0), new DateTime(2026, 1, 5, 17, 0, 0))
.SetCapacityWindow("machine-42-overtime-crew", new DateTime(2026, 1, 5, 17, 0, 0), new DateTime(2026, 1, 5, 19, 0, 0), 5)
.Compile(new DateTime(2026, 1, 5), new DateTime(2026, 1, 6));TimeGrid.NET uses System.Text.Json source generation for its definition model.
Use Compile(start, end) when the same calendar will be queried many times. A compiled
timeline is read-only and answers point and range queries by searching precomputed state
segments.
var timeline = calendar.Compile(monthStart, monthEnd);
var point = timeline.Analyze(now);
var work = timeline.GetWorkingDuration(dayStart, dayEnd);
var slot = timeline.FindFirstSlot(dayStart, 4.Hours(), minimumCapacity: 2);| Operation | Runtime strategy |
|---|---|
| Point analysis | Binary search over compiled state segments |
| Range analysis | Binary search, then scan touched segments only |
| Transition lookup | Segment boundary lookup |
| Working duration | Sum usable segment ticks |
| Slot search | Scan continuous capacity-matching segments |
| JSON | Source-generated System.Text.Json definition serialization |
Local quick-query measurement on .NET 8.0, Windows 10, Intel Core i7-10700, Release build:
| Scenario | Operation | Result |
|---|---|---|
| 50,000 compiled state segments | GetCapacityAt |
0.053 us/query |
| 50,000 compiled state segments | Analyze |
0.067 us/query |
| 1,000 compiled machine timelines | GetCapacityAt sweep |
25.752 us |
| 1,000 compiled machine timelines | Analyze sweep |
35.944 us |
Measurements exclude compile time and run against already compiled timelines.
| Use TimeGrid.NET for | Use something else for |
|---|---|
| Business-hours and working-time calculations | Calendar UI rendering |
| Manufacturing availability and machine downtime | Queue dispatching |
| Capacity-aware slot search | Optimization solving |
| SLA clocks and operational reporting | Full timezone database behavior |
| JSON-backed schedule definitions | General-purpose date-range value objects |
| Scheduler or simulator availability layer | Running background jobs |
- Time windows are half-open:
[start, end). - Capacity
0means unavailable. - Capacity overrides split the timeline into state segments.
- JSON stores source definitions, not compiled timelines.
- Compiled timelines are read-only and optimized for repeated analysis.
- Use
DateTimeconsistently in your chosen local or UTC convention.
calendar.CanWork(now);
calendar.GetCapacityAt(now);
calendar.GetWindowsAt(now);
calendar.GetPreviousTransitionTime(now);
calendar.GetNextTransitionTime(now);
calendar.GetOpenWindows(start, end);
calendar.GetUnavailableWindows(start, end);
calendar.GetStateWindows(start, end);
calendar.GetWorkingDuration(start, end);
calendar.FindFirstSlot(start, 2.Hours(), minimumCapacity: 2);- NuGet: https://www.nuget.org/packages/TimeGrid.NET
- Repository: https://github.com/code-gihan/timegrid-csharp
- Issues: https://github.com/code-gihan/timegrid-csharp/issues
- Python package: https://pypi.org/project/timegrid/
- License: MIT
If TimeGrid.NET gives you a wrong answer, a confusing error, or a missing API for a real scheduling or availability problem, please open a GitHub issue with the smallest calendar definition and query that reproduces it.