Chneau.OpenHours 1.0.2

dotnet add package Chneau.OpenHours --version 1.0.2
                    
NuGet\Install-Package Chneau.OpenHours -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Chneau.OpenHours" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Chneau.OpenHours" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Chneau.OpenHours" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Chneau.OpenHours --version 1.0.2
                    
#r "nuget: Chneau.OpenHours, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Chneau.OpenHours@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Chneau.OpenHours&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Chneau.OpenHours&version=1.0.2
                    
Install as a Cake Tool

openhours-cs

A high-performance, zero-allocation C# (.NET 10) parser and interval-math evaluator for OpenStreetMap opening_hours specifications.

.NET 10 License: MIT


โšก Features & Performance

  • $O(1)$ Hardware-Accelerated Bitmask Table: Evaluates IsOpen in ~2.0 nanoseconds (>500 Million ops/sec) via embedded [InlineArray(158)] Bitmask158 scalar bit tests (BTQ).
  • Zero-Allocation Interval Math: Zero heap allocations on query paths (IsOpen, GetTimeToOpen, GetTimeToOpenForDuration, When, NextDur, NextDate).
  • Span-Based Parsing: Zero string allocations when parsing UTF-8 bytes or raw ReadOnlySpan<char>.
  • Lock-Free Interning: Automatic lock-free deduplication and caching of parsed expressions.
  • Overnight Shifts: Full support for shifts spanning midnight (e.g. Mo 22:00-04:00, Su 22:00-04:00).
  • Overrides & Exclusions: Handles off / closed rules overriding previous rules (e.g. Mo-Su 00:00-24:00; Tu 12:00-13:00 off).
  • Duration Availability: Find wait times for contiguous tasks of duration $D$ (GetTimeToOpenForDuration / When).
  • Reflection-free JSON Decode: High-speed, zero-allocation DecodeJson(ReadOnlySpan<byte>) deserializing in ~31 nanoseconds.
  • Source-Generated JSON: Native System.Text.Json converter and OpenHoursJsonContext for seamless serialization.

๐Ÿง  Optimizations & Engineering Architecture

The C# (.NET 10) implementation applies several state-of-the-art runtime and JIT-level optimizations:

  1. Dual State Representation & [InlineArray(158)]:

    • Disjoint Interval Array (TimeWindow[]): Flat sorted array of { int Start, int End } minute intervals.
    • Contiguous Bitmask Struct: Employs .NET C# 12 [InlineArray(158)] struct Bitmask158 (158 ร— ulong = 10,080 bits) embedded directly inside the object payload. This enables zero heap indirection and compiles to single BTQ / bit-test instructions for IsOpen (~2.0 ns).
  2. Reflection-Free JSON Fast Path:

    • DecodeJson(ReadOnlySpan<byte>) performs direct UTF-8 byte scanning, escape validation, and resolves directly to interned instances via zero-allocation span lookups in ~31 ns.
  3. Zero-Allocation Stack & Span Parsing:

    • Parses expressions directly using ReadOnlySpan<char> with stackalloc OpeningRule[8] and stackalloc TimeWindow[32] buffers.
    • Character classification uses fast ASCII bitwise arithmetic ((c0 << 8) | c1 pair matching for day tokens), completely avoiding string allocations during parsing.
  4. Two-Tier Lock-Free Caching Hierarchy:

    • L1 [ThreadStatic] Fast Cache: Caches the last resolved string key and OpenHours instance per thread, skipping dictionary lookups for tight loops and consecutive parses.
    • L2 Concurrent Dictionary: Uses ConcurrentDictionary<string, OpenHours> with GetAlternateLookup<ReadOnlySpan<char>>() to query span inputs without allocating string keys.
  5. $O(\log N)$ Interval Binary Search:

    • Fast binary search over the windows array for duration calculations (GetTimeToOpen, When, NextDur), unrolled for small window counts.
  6. [MethodImpl(MethodImplOptions.AggressiveInlining)]:

    • Applied across all hot evaluation paths to eliminate function call overhead and enable downstream JIT optimizations.

๐Ÿš€ Quick Start

Installation

dotnet add package Chneau.OpenHours

Usage Example

using Chneau.OpenHours;

// 1. Parse an OSM opening_hours string
var oh = OpenHours.Parse("Mo-Fr 08:00-12:00, 13:00-17:00; Sa 08:00-12:00");

var monday10am = new DateTime(2026, 5, 18, 10, 0, 0, DateTimeKind.Utc);

// 2. Fast point-in-time check (2.0 ns/op)
bool isOpen = oh.IsOpen(monday10am); // true

// 3. Current shift end
DateTime? shiftEnd = oh.GetCurrentShiftEnd(monday10am); // 2026-05-18 12:00:00 UTC

// 4. Time to next open
var tuesdayLunch = new DateTime(2026, 5, 19, 12, 30, 0, DateTimeKind.Utc);
TimeSpan? timeToOpen = oh.GetTimeToOpen(tuesdayLunch); // 00:30:00 (opens at 13:00)

// 5. Find when a 3-hour job can be serviced
TimeSpan? waitFor3h = oh.GetTimeToOpenForDuration(tuesdayLunch, TimeSpan.FromHours(3));
DateTime? whenCanStart = oh.When(tuesdayLunch, TimeSpan.FromHours(3)); // 2026-05-19 13:00:00 UTC

// 6. Next state transitions
var (isOpenNow, durationRemaining) = oh.NextDur(monday10am);
var (_, nextTransitionDate) = oh.NextDate(monday10am); // 2026-05-18 12:00:00 UTC

๐Ÿ“Š Benchmark Suite (.NET 10 on AMD Ryzen 9)

# Workload Calls Latency / Op Throughput
1 IsOpen (Rolling timeline) 100,000 2.0 ns 500,000,000 ops/sec
2 IsOpen (Pure call) 1,000,000 2.0 ns 500,000,000 ops/sec
3 GetTimeToOpen 10,000 8.0 ns 125,000,000 ops/sec
4 GetTimeToOpenForDuration 10,000 9.0 ns 111,000,000 ops/sec
5 When 10,000 12.0 ns 83,000,000 ops/sec
6 NextDur 10,000 67.0 ns 15,000,000 ops/sec
7 NextDate 10,000 100.0 ns 10,000,000 ops/sec
8 Parse (Cached) 1,000 26.0 ns 38,000,000 ops/sec
9 JSON Deserialize 1,000 220 ns 4,500,000 ops/sec
10 Stress Test (5,000 unique objects) 5,000 0.50 ยตs/obj 2,000,000 objs/sec

๐Ÿ› ๏ธ Development & Quality Commands

# Run all unit tests
dotnet test

# Run tests in continuous watch mode during development
dotnet watch test

# Run full release build
dotnet build -c Release

๐Ÿ“„ License

MIT License. Copyright (c) 2026 chneau.

Product Compatible and additional computed target framework versions.
.NET 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Chneau.OpenHours:

Package Downloads
Chneau.TimeTable

Modern, high-performance capacity and schedule constraint evaluation engine in .NET 10.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 152 9/4/2026
1.0.1 115 8/26/2026
1.0.0 109 8/26/2026