A .NET 8 library for temporal reasoning with second-resolution instants and time intervals.
Vegas.Time provides two core value types — Instant and Interval — with a rich set of relational and set-operation methods for working with points and ranges on the timeline. All values are anchored to UTC.
The library is distributed as a NuGet package (version 1.1.0, target net8.0).
dotnet add package Vegas.Time
Represents a single point on the UTC timeline with second resolution, backed by a Unix epoch seconds long.
var now = new Instant(); // current UTC second
var epoch = new Instant(0); // 1970-01-01 00:00:00 UTC
var fromDto = Instant.FromDateTimeOffset(dto);
var fromDt = Instant.FromDateTime(dateTime);
instant.ToDateTime(); // UTC DateTime
instant.ToDateTimeOffset(); // DateTimeOffset
instant.SecondsSinceEpoch; // underlying longRange: 0001-01-01 00:00:00 UTC (MinValue) → 9999-12-31 23:59:59 UTC (MaxValue). Construction outside this range throws OverflowException.
Operators: ==, !=, <, <=, >, >=, - (returns TimeSpan).
Relation methods (IInstantRelation):
| Method | Description |
|---|---|
Before(Instant) |
Returns true if this instant is strictly earlier |
Before(Interval) |
Returns true if this instant is before the interval's start |
Starts(Interval) |
Returns true if this instant equals the interval's start |
During(Interval) |
Returns true if this instant is strictly inside the interval (exclusive of endpoints) |
Ends(Interval) |
Returns true if this instant equals the interval's end |
After(Instant) |
Returns true if this instant is strictly later |
After(Interval) |
Returns true if this instant is after the interval's end |
Rounding is hour-based, relative to UTC.
| Extension | Result |
|---|---|
RoundDown() |
Floor to the current hour (:00:00) |
RoundUp() |
Ceil to the next hour if minutes > 0 |
RoundDownHalf() |
Floor to the nearest half-hour (:00:00 or :30:00) |
RoundUpHalf() |
Ceil to the next half-hour |
Represents a contiguous span between two Instants (Start ≤ End). Constructing with end < start throws ArgumentOutOfRangeException.
var interval = new Interval(start, end);
var fromDt = Interval.FromDateTime(begin, end);
var fromDto = Interval.FromDateTimeOffset(begin, end);
interval.Duration; // TimeSpan
interval.Instantaneous; // true when Start == End
var (s, e) = interval; // deconstruct| Method | Description |
|---|---|
Before(Instant) / Before(Interval) |
Interval ends before the target |
After(Instant) / After(Interval) |
Interval starts after the target |
Touches(Interval) |
Endpoints share exactly one boundary point |
Touches(Interval, out TouchEnum?) |
Same, with StartTouching / EndTouching discriminator |
Contains(Instant/DateTime) |
Instant is strictly inside (exclusive of endpoints) |
Contains(Interval) |
Other interval is strictly inside |
ContainsInclusive(Instant/DateTime) |
Instant is inside including endpoints |
ContainsInclusive(Interval) |
Other interval is within including shared endpoints |
Within(Interval) |
This interval is strictly contained by the other |
WithinInclusive(Interval) |
This interval is contained by the other (inclusive) |
Overlaps(Interval) |
Intervals share more than a single boundary point |
Intersects(Interval) |
Overlaps or touches |
RelatesTo(Interval) |
Returns IntervalRelationEnum flags |
| Method | Description |
|---|---|
Intersect(Interval) |
Returns the overlapping Interval. Throws ArgumentOutOfRangeException if disjoint. |
Clip(Interval) |
Intersects and returns a ClipResult with duration/ratio metadata. Throws if disjoint. |
record ClipResult(
double PreviousDuration, // duration of the original interval (seconds)
double CurrentDuration, // duration of the clipped result (seconds)
double Ratio, // CurrentDuration / PreviousDuration [0..1]
Interval Result // the clipped interval
);Flags enum returned by RelatesTo:
| Value | Meaning |
|---|---|
Disjoint |
No contact |
Touch |
Single boundary point shared |
Overlaps |
Shared span > 0 |
Intersects |
Overlaps or touches |
using Vegas.Time.Abstractions;
// --- Instant ---
var a = new Instant(5000);
var b = new Instant(10000);
var window = new Interval(a, b);
var probe = new Instant(7500);
bool inside = probe.During(window); // true
bool starts = probe.Starts(window); // false
TimeSpan gap = b - a; // 5000 seconds
// --- Rounding ---
var rounded = probe.RoundDown(); // floors to the current UTC hour
// --- Interval relations ---
var other = new Interval(new Instant(8000), new Instant(12000));
bool overlaps = window.Overlaps(other); // true
bool intersects = window.Intersects(other);// true
bool touches = window.Touches(other); // false
IntervalRelationEnum rel = window.RelatesTo(other);
// rel == IntervalRelationEnum.Overlaps | IntervalRelationEnum.Intersects
// --- Intersect / Clip ---
Interval shared = window.Intersect(other);
// shared: [8000] => [10000]
ClipResult clip = window.Clip(other);
// clip.PreviousDuration == 5000
// clip.CurrentDuration == 2000
// clip.Ratio == 0.4
// clip.Result == [8000] => [10000]src/
Vegas.Time/ # library (net8.0)
Vegas.Time.UnitTest/ # NUnit test suite
dotnet build src/Vegas.Time/Vegas.Time.csproj
dotnet test src/Vegas.Time.UnitTest/Vegas.Time.UnitTest.csprojCopyright © Vegas Tecnologia.