TimeGrid.NET
0.1.2
See the version list below for details.
dotnet add package TimeGrid.NET --version 0.1.2
NuGet\Install-Package TimeGrid.NET -Version 0.1.2
<PackageReference Include="TimeGrid.NET" Version="0.1.2" />
<PackageVersion Include="TimeGrid.NET" Version="0.1.2" />
<PackageReference Include="TimeGrid.NET" />
paket add TimeGrid.NET --version 0.1.2
#r "nuget: TimeGrid.NET, 0.1.2"
#:package TimeGrid.NET@0.1.2
#addin nuget:?package=TimeGrid.NET&version=0.1.2
#tool nuget:?package=TimeGrid.NET&version=0.1.2
TimeGrid
TimeGrid is a lightweight compiled timeline engine for .NET.
Define availability, breaks, downtime, holidays, capacity, and named schedule entries.
Serialize the source definition as JSON. Compile it once. Analyze timestamps and ranges fast.
Not a scheduler. Not a simulator. Not a DateRange wrapper.
TimeGrid is the operational time layer those systems can depend on.
Install
dotnet add package TimeGrid.NET
What It Answers
| Question | API |
|---|---|
| Can this machine work now? | timeline.Analyze(now).CanWork |
| Which state window contains this timestamp? | analysis.CurrentWindow |
| What is the effective capacity? | analysis.Capacity |
| When does the state change? | analysis.NextTransition |
| Why is this timestamp blocked? | calendar.At(now).Analyze().Matches |
| How much usable time exists in a range? | timeline.GetWorkingDuration(start, end) |
| Where is the first slot with enough capacity? | timeline.FindFirstSlot(start, 2.Hours(), 3) |
Quick Start
using TimeGrid;
var monthStart = new DateTime(2026, 1, 1);
var monthEnd = new DateTime(2026, 2, 1);
var timeline = TimeGridCalendar
.Weekdays(new TimeOnly(9, 0), new TimeOnly(18, 0))
.BreakWeekdays(new TimeOnly(12, 0), new TimeOnly(13, 0))
.Close(new DateOnly(2026, 1, 1))
.Down(new DateTime(2026, 1, 5, 15, 0, 0), new DateTime(2026, 1, 5, 16, 0, 0))
.Capacity(new DateTime(2026, 1, 5, 9, 0, 0), new DateTime(2026, 1, 5, 12, 0, 0), 3)
.Compile(monthStart, monthEnd);
var state = timeline.Analyze(new DateTime(2026, 1, 5, 10, 30, 0));
Console.WriteLine(state.CanWork); // true
Console.WriteLine(state.Capacity); // 3
Console.WriteLine(state.CurrentWindow); // 2026-01-05 10:00 -> 11:00
Console.WriteLine(state.NextTransition); // 2026-01-05 11:00
JSON Definitions
Store source schedules, not compiled runtime state.
var calendar = TimeGridCalendar
.Weekdays(new TimeOnly(8, 0), new TimeOnly(20, 0))
.BreakWeekdays(new TimeOnly(12, 0), new TimeOnly(13, 0))
.SetClosedWindow("machine-17-maintenance", downStart, downEnd)
.SetCapacityWindow("machine-17-boost", boostStart, boostEnd, capacity: 4);
var json = calendar.ToJson(indented: true);
var restored = TimeGridCalendar
.FromJson(json)
.Compile(monthStart, monthEnd);
TimeGrid uses System.Text.Json source generation for its definition model.
Manufacturing Pattern
Use one shared template and add equipment-specific exceptions.
var template = TimeGridCalendar
.Weekdays(new TimeOnly(9, 0), new TimeOnly(18, 0))
.BreakWeekdays(new TimeOnly(12, 0), new TimeOnly(13, 0))
.ToDefinition();
var machine = template.ToCalendar()
.SetClosedWindow("maintenance", maintenanceStart, maintenanceEnd)
.SetCapacityWindow("extra-line", boostStart, boostEnd, capacity: 3)
.Compile(monthStart, monthEnd);
var state = machine.Analyze(now);
This keeps common schedule rules reusable while each machine carries only its own downtime and capacity changes.
Why It Is Fast
Use Compile(start, end) for read-heavy systems:
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.
Before / After
Without TimeGrid, operational time rules spread across conditionals:
if (date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday) return false;
if (time < open || time >= close) return false;
if (lunchStart <= time && time < lunchEnd) return false;
if (holidays.Contains(DateOnly.FromDateTime(date))) return false;
if (downtimeStart <= date && date < downtimeEnd) return false;
return capacity > 0;
With TimeGrid, rules are data and queries stay small:
var analysis = timeline.Analyze(now);
if (analysis.CanWork)
{
Console.WriteLine($"capacity: {analysis.Capacity}");
}
Named Timeline Entries
var calendar = TimeGridCalendar.Create()
.SetOpenWindow("shift-a", start, end)
.SetClosedWindow("maintenance", downStart, downEnd)
.SetCapacityWindow("line-boost", boostStart, boostEnd, capacity: 4);
var maintenance = calendar.GetEntry("maintenance");
calendar.SetClosedWindow("maintenance", newDownStart, newDownEnd);
calendar.RemoveEntry("maintenance");
Good Fit
| Use TimeGrid for | Use something else for |
|---|---|
| Manufacturing availability | Running background jobs |
| Machine downtime analysis | Queue dispatching |
| Capacity-aware slot search | Calendar UI rendering |
| SLA working-time math | Full time-zone database behavior |
| Scheduler/simulator time layer | Optimization solving |
| JSON-backed schedule definitions | General-purpose DateRange value objects |
Core Rules
- 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.
<details> <summary>Direct APIs</summary>
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);
</details>
Links
- NuGet: https://www.nuget.org/packages/TimeGrid.NET
- Repository: https://github.com/code-gihan/timegrid-csharp
- License: MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Fix GitHub repository links in the README and NuGet package metadata.