Horae 1.0.6

dotnet add package Horae --version 1.0.6
                    
NuGet\Install-Package Horae -Version 1.0.6
                    
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="Horae" Version="1.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Horae" Version="1.0.6" />
                    
Directory.Packages.props
<PackageReference Include="Horae" />
                    
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 Horae --version 1.0.6
                    
#r "nuget: Horae, 1.0.6"
                    
#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 Horae@1.0.6
                    
#: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=Horae&version=1.0.6
                    
Install as a Cake Addin
#tool nuget:?package=Horae&version=1.0.6
                    
Install as a Cake Tool

Horae

Horae is a modern, minimalistic .NET library for elegant and precise time utilities. It provides syntactic sugar such as 1.January(2026), robust conversions between DateTimeOffset, DateOnly, and DateTime, DST-safe interval operations, and ISO 8601 serialization with System.Text.Json.

License: Apache-2.0 · Target frameworks: net8.0 · net9.0 · net10.0


Table of Contents


Configuration

HoraeSettings.CurrentTimeZone sets the default time zone used by all methods with an optional TimeZoneInfo? parameter when null is passed. The default value is TimeZoneInfo.Local.

The value is stored per execution context using AsyncLocal<T>, making it safe for concurrent use in asynchronous applications and unit tests.

// Set once during application startup
HoraeSettings.CurrentTimeZone = TimeZones.CentralEuropean;

// Or use a scoped override
using (HoraeSettings.Use(TimeZones.Japan))
{
    // CurrentTimeZone is Japan here
}

Date Construction

Fluent methods on int for readable date values:

DateTimeOffset d1 = 1.January(2026);         // 2026-01-01T00:00:00+00:00
DateTimeOffset d2 = 15.June(2026);           // 2026-06-15T00:00:00+00:00

// Add a time of day (preserves the base UTC offset)
DateTimeOffset d3 = 1.January(2026).At(14, 30);       // 2026-01-01T14:30:00+00:00
DateTimeOffset d4 = 1.January(2026).At(TimeSpan.FromHours(9));

// Relative arithmetic
DateTimeOffset d5 = 2.Hours().After(1.January(2026));
DateTimeOffset d6 = 30.Minutes().Before(1.January(2026));

// Nanosecond support (100 ns resolution)
DateTimeOffset d7 = 1.January(2026).AddNanoseconds(500);

TimeSpan Construction

Fluent methods on int, long, and double:

TimeSpan t1 = 15.Minutes();
TimeSpan t2 = 1.Hours();
TimeSpan t3 = 2.Days();
TimeSpan t4 = 500.Milliseconds();
TimeSpan t5 = 100.Microseconds();
TimeSpan t6 = 1000.Nanoseconds();   // precision below 100 ns is lost

// Chain with .And()
TimeSpan t7 = 1.Hours().And(30.Minutes());   // 1:30:00

// Offset overloads
TimeSpan t8 = 2.Hours(30.Minutes());         // 2:30:00

DateTimeOffset Operations

Day boundaries

All methods accept an optional TimeZoneInfo? (default: HoraeSettings.CurrentTimeZone).

var now = DateTimeOffset.UtcNow;

DateTimeOffset start  = now.StartOfDay(TimeZones.CentralEuropean);    // midnight in CET/CEST
DateTimeOffset startU = now.StartOfDayUtc(TimeZones.CentralEuropean); // same instant, UTC offset

DateTimeOffset end    = now.EndOfDay(TimeZones.CentralEuropean);      // next midnight (exclusive)
DateTimeOffset endU   = now.EndOfDayUtc(TimeZones.CentralEuropean);

// Intraday session (= current day)
DateTimeOffset is = now.StartOfIntraday();
DateTimeOffset ie = now.EndOfIntraday();

// Day-ahead session (= next calendar day)
DateTimeOffset das = now.StartOfDayAhead();
DateTimeOffset dae = now.EndOfDayAhead();

Rounding

DateTimeOffset r1 = now.RoundDown(Duration.QuarterHour);              // round down to 15 minutes
DateTimeOffset r2 = now.RoundUp(TimeSpan.FromHours(1));                 // round up to the hour
DateTimeOffset r3 = now.RoundToNearest(Duration.HalfHour, TimeZones.CentralEuropean);

Change time zone

DateTimeOffset cest = now.ToTimeZone(TimeZones.CentralEuropean);        // same instant, different offset

Conversions

var dto  = new DateTimeOffset(2026, 6, 15, 12, 0, 0, TimeSpan.Zero);
var date = new DateOnly(2026, 6, 15);

// DateTimeOffset → DateOnly
DateOnly d1 = dto.AsDateOnly(TimeZones.Japan);    // calendar day in JST
DateOnly d2 = dto.AsUtcDateOnly();                // calendar day in UTC

// DateTimeOffset → DateTime
DateTime t1 = dto.AsDateTime(TimeZones.CentralEuropean); // DateTimeKind.Unspecified
DateTime t2 = dto.AsUtcDateTime();                        // DateTimeKind.Utc

// DateOnly → DateTimeOffset
DateTimeOffset m1 = date.AsDateTimeOffset(TimeZones.CentralEuropean); // midnight in CET/CEST
DateTimeOffset m2 = date.AsUtcDateTimeOffset();                        // midnight UTC

Regional Time Zones

Converts a DateTimeOffset value into a specific time zone. The returned value represents the same instant with the correct regional offset, including DST.

var utc = new DateTimeOffset(2026, 6, 15, 12, 0, 0, TimeSpan.Zero);

DateTimeOffset cet  = utc.ToCentralEuropeanTime();  // 14:00 +02:00 (CEST)
DateTimeOffset lon  = utc.ToLondonTime();           // 13:00 +01:00 (BST)
DateTimeOffset lis  = utc.ToLisbonTime();           // 13:00 +01:00 (WEST)
DateTimeOffset eet  = utc.ToEasternEuropeTime();    // 15:00 +03:00 (EEST)
DateTimeOffset msk  = utc.ToMoscowTime();           // 15:00 +03:00 (MSK)
DateTimeOffset ist  = utc.ToIstanbulTime();         // 15:00 +03:00 (TRT)
DateTimeOffset est  = utc.ToEasternUsTime();        //  8:00 -04:00 (EDT)
DateTimeOffset pst  = utc.ToPacificUsTime();        //  5:00 -07:00 (PDT)
DateTimeOffset gst  = utc.ToDubaiTime();            // 16:00 +04:00 (GST)
DateTimeOffset ind  = utc.ToIndiaTime();            // 17:30 +05:30 (IST)
DateTimeOffset jst  = utc.ToJapanTime();            // 21:00 +09:00 (JST)
DateTimeOffset aest = utc.ToAustraliaEasternTime(); // 22:00 +10:00 (AEST)

// Back to UTC
DateTimeOffset back = cet.ToUtc();                  // 12:00 +00:00

ISO 8601 Formatting & Parsing

Formatting

var dto  = new DateTimeOffset(2026, 1, 1, 23, 0, 0, TimeSpan.Zero);
var dto2 = new DateTimeOffset(2026, 1, 1, 23, 0, 0, 500, TimeSpan.Zero); // 500 ms
var date = new DateOnly(2026, 6, 15);
var time = new TimeOnly(14, 30, 0);
var time2 = new TimeOnly(14, 30, 0, 500); // 500 ms

// Default: IsoDateTimePrecision.Seconds — sub-second digits always omitted
dto.ToIsoString();   // "2026-01-01T23:00:00Z"
dto2.ToIsoString();  // "2026-01-01T23:00:00Z"  (500 ms dropped)

// Explicit precision control
dto2.ToIsoString(IsoDateTimePrecision.Auto);        // "2026-01-01T23:00:00.5Z" (only when ≠ 0)
dto2.ToIsoString(IsoDateTimePrecision.Fractional);  // "2026-01-01T23:00:00.5000000Z" (always 7 digits)
dto.ToIsoString(IsoDateTimePrecision.Fractional);   // "2026-01-01T23:00:00.0000000Z"

date.ToIsoString();  // "2026-06-15"

// TimeOnly — same precision control as DateTimeOffset
time.ToIsoString();                                    // "14:30:00"
time2.ToIsoString(IsoDateTimePrecision.Auto);          // "14:30:00.5"
time2.ToIsoString(IsoDateTimePrecision.Fractional);    // "14:30:00.5000000"
time.ToIsoString(IsoDateTimePrecision.Fractional);     // "14:30:00.0000000"

// Nullable overloads
DateTimeOffset? nullDto  = null;
DateOnly?       nullDate = null;
TimeOnly?       nullTime = null;
nullDto.ToIsoString();   // null
nullDate.ToIsoString();  // null
nullTime.ToIsoString();  // null

Parsing

// DateTimeOffset – accepts "Z", "+HH:mm", and "-HH:mm" offsets, including fractional seconds
DateTimeOffset dto1 = "2026-01-01T23:00:00Z".ParseIsoDateTime();
DateTimeOffset dto2 = "2026-01-01T23:00:00+01:00".ParseIsoDateTime();
DateTimeOffset dto3 = "2026-01-01T23:00:00.5Z".ParseIsoDateTime(); // 500 ms

bool ok = "2026-01-01T23:00:00Z".TryParseIsoDateTime(out DateTimeOffset result);

// DateOnly – strict "yyyy-MM-dd"
DateOnly date = "2026-06-15".ParseIsoDate();
bool ok2 = "2026-06-15".TryParseIsoDate(out DateOnly dateResult);

// TimeOnly – accepts "HH:mm:ss", "HH:mm:ss.FFFFFFF" (trailing zeros suppressed), and "HH:mm:ss.fffffff"
TimeOnly time  = "14:30:00".ParseIsoTime();
TimeOnly time2 = "14:30:00.5".ParseIsoTime(); // 500 ms
bool ok3 = "09:15:30".TryParseIsoTime(out TimeOnly timeResult);

Day Offset

DayOffset describes a calendar day relative to the current instant in a specific time zone. It resolves to a DateOnly on demand, staying valid indefinitely (unlike a fixed date).

// Named presets (no embedded timezone — pass it at resolve time)
DateOnly today     = DayOffset.Today.Resolve(TimeZones.CentralEuropean);
DateOnly dayAhead  = DayOffset.DayAhead.Resolve(TimeZones.CentralEuropean);
DateOnly yesterday = DayOffset.Yesterday.Resolve(TimeZones.CentralEuropean);

// Arbitrary offset via implicit int conversion
DateOnly twoDaysOut = ((DayOffset)2).Resolve(TimeZones.CentralEuropean);

// Self-contained with embedded timezone — resolves without any argument
var dto = new DayOffset(1, TimeZones.CentralEuropean);
DateOnly date = dto.Resolve();
// Serializes as: { "days": 1, "timezone": "Europe/Berlin" }

// Inject a reference instant (useful in tests or scheduled jobs)
DateOnly pinned = new DayOffset(1).Resolve(
    new DateTimeOffset(2026, 5, 9, 0, 0, 0, TimeSpan.Zero),
    TimeZones.CentralEuropean);
// → DateOnly(2026, 5, 10)

// Bridge to TimeInterval
TimeInterval interval = TimeInterval.Day(DayOffset.DayAhead.Resolve(TimeZones.CentralEuropean),
                                         TimeZones.CentralEuropean);

Timezone resolution priority

  1. Explicit tz argument passed to Resolve
  2. TimeZone embedded in the DayOffset instance
  3. HoareSettings.CurrentTimeZone (ambient fallback)

JSON serialization

DayOffset carries a [JsonConverter] attribute and serializes automatically. The format depends on whether a time zone is embedded:

// No embedded timezone → plain integer
1

// With embedded timezone → object
{ "days": 1, "timezone": "Europe/Berlin" }

Both formats are accepted when reading, enabling a smooth migration from the compact integer form.


Duration

Duration represents an ISO 8601 duration (positive TimeSpan) with named presets and automatic JSON serialization.

// Predefined instances
Duration r1 = Duration.Minute;      // PT1M
Duration r2 = Duration.FiveMinutes; // PT5M
Duration r3 = Duration.QuarterHour; // PT15M
Duration r4 = Duration.HalfHour;    // PT30M
Duration r5 = Duration.Hour;        // PT1H
Duration r6 = Duration.Day;         // P1D
Duration r7 = Duration.Week;        // P7D

// Custom values
var r2 = new Duration(TimeSpan.FromMinutes(10));
var r3 = Duration.Parse("PT10M");
bool ok = Duration.TryParse("P1D", out Duration daily);

// To/from TimeSpan (implicit)
TimeSpan ts = Duration.QuarterHour;           // 00:15:00
Duration res = TimeSpan.FromHours(1);         // equivalent to Duration.Hour

// ToString → ISO 8601
Duration.QuarterHour.ToString(); // "PT15M"
Duration.Day.ToString();         // "P1D"

JSON Serialization

Duration carries a [JsonConverter] attribute and serializes automatically:

{ "duration": "PT15M" }

TimeInterval

TimeInterval represents a half-open interval [Start, End) with UTC-normalized boundaries.

// Construction
var interval = new TimeInterval(
    new DateTimeOffset(2026, 6, 15, 0, 0, 0, TimeSpan.Zero),
    new DateTimeOffset(2026, 6, 16, 0, 0, 0, TimeSpan.Zero));

// Factory methods
TimeInterval day      = TimeInterval.Day(new DateOnly(2026, 6, 15), TimeZones.CentralEuropean);
TimeInterval intraday = TimeInterval.Intraday(DateTimeOffset.UtcNow, TimeZones.CentralEuropean);
TimeInterval ahead    = TimeInterval.DayAhead(DateTimeOffset.UtcNow, TimeZones.CentralEuropean);

// Contains an instant?
bool contains = interval.Contains(DateTimeOffset.UtcNow);

// Deconstruction
var (start, end) = interval;

// Split by resolution
foreach (DateTimeOffset slot in interval.SplitBy(Duration.QuarterHour))
    Console.WriteLine(slot); // 96 × 15-minute slots

// Split by hours
foreach (DateTimeOffset slot in interval.SplitBy(TimeSpan.FromHours(1)))
    Console.WriteLine(slot); // 24 × 1-hour slots

// Split by calendar days (DST-safe)
foreach (DateTimeOffset midnight in interval.SplitByDays(TimeZones.CentralEuropean))
    Console.WriteLine(midnight); // UTC equivalent of each midnight in CET/CEST

DST note: SplitBy(Duration.Day) and SplitByDays() iterate over DateOnly calendar days in the target time zone. This correctly handles days with 23 hours (DST start) and 25 hours (DST end).


ZonedTimeInterval

ZonedTimeInterval represents a half-open interval [Start, End) whose boundaries are expressed in a specific time zone, preserving the local UTC offset rather than normalising to UTC. Use this type when the local time context matters — for example, a trading day in CET or a session window such as "15:00–18:00 Europe/Berlin".

The constructor converts start and end to the supplied time zone, so Start.Offset always reflects the correct DST offset for that instant (+01:00 CET, +02:00 CEST). TimeZoneInfo is required because a raw UTC offset alone is insufficient for DST-safe operations.

// Trading day in CET — boundaries are stored as local CET/CEST offsets
ZonedTimeInterval day = ZonedTimeInterval.Day(new DateOnly(2026, 1, 15), TimeZones.CentralEuropean);
// day.Start = 2026-01-15T00:00:00+01:00
// day.End   = 2026-01-16T00:00:00+01:00

// Summer day — offset is automatically +02:00 (CEST)
ZonedTimeInterval summerDay = ZonedTimeInterval.Day(new DateOnly(2026, 6, 15), TimeZones.CentralEuropean);
// summerDay.Start = 2026-06-15T00:00:00+02:00
// summerDay.End   = 2026-06-16T00:00:00+02:00

// Session window: 15:00–18:00 CET
ZonedTimeInterval session = ZonedTimeInterval.Create(
    new DateTimeOffset(2026, 1, 1, 15, 0, 0, TimeSpan.FromHours(1)),
    new DateTimeOffset(2026, 1, 1, 18, 0, 0, TimeSpan.FromHours(1)),
    TimeZones.CentralEuropean);

// Contains check
bool active = day.Contains(DateTimeOffset.UtcNow);

// Deconstruct
var (start, end) = day;

// Convert to UTC-normalized TimeInterval
TimeInterval utc = day.ToUtc();

// Split — no TimeZoneInfo parameter needed (stored in the interval)
foreach (DateTimeOffset slot in day.SplitBy(Duration.QuarterHour))
    Console.WriteLine(slot); // 96 × 15-minute slots in CET offset

// Split by calendar days (DST-safe)
foreach (DateTimeOffset midnight in day.SplitByDays())
    Console.WriteLine(midnight); // midnights in the interval's time zone

DST note: SplitBy(Duration.Day) and SplitByDays() use DateOnly.AddDays() in the stored time zone, correctly handling 23-hour and 25-hour DST transition days.


Calendar Queries

Extension methods on DateOnly and DateTimeOffset for common calendar properties. DateTimeOffset overloads always use the UTC date.

var date = new DateOnly(2026, 6, 15);
var dto  = new DateTimeOffset(2026, 6, 15, 12, 0, 0, TimeSpan.Zero);

// Leap year
bool leap1 = date.IsLeapYear();  // false
bool leap2 = dto.IsLeapYear();   // false

// Days in month / year
int dim1 = date.DaysInMonth();   // 30
int dim2 = dto.DaysInMonth();    // 30
int diy1 = date.DaysInYear();    // 365
int diy2 = dto.DaysInYear();     // 365

// Quarter (1–4)
int q1 = date.Quarter();  // 2
int q2 = dto.Quarter();   // 2

// Day of year / ordinal (1–366)
int ord1 = date.DayOfYear();  // 166
int ord2 = dto.DayOfYear();   // 166

// Weekend / weekday
bool we1 = date.IsWeekend();  // false (Monday)
bool wd1 = date.IsWeekday();  // true

// DateTimeOffset overloads accept an optional TimeZoneInfo
bool we2 = dto.IsWeekend(TimeZones.CentralEuropean);
bool wd2 = dto.IsWeekday(TimeZones.Japan);

ISO Week

ISO 8601 week-calendar helpers on DateOnly and DateTimeOffset. DateTimeOffset overloads use the UTC date.

var date = new DateOnly(2025, 12, 29);  // belongs to ISO week year 2026
var dto  = new DateTimeOffset(2026, 1, 5, 0, 0, 0, TimeSpan.Zero); // Monday

// Week number (1–53)
int wn1 = date.IsoWeekNumber();  // 1
int wn2 = dto.IsoWeekNumber();   // 2

// ISO week-year (may differ from calendar year near year boundaries)
int wy1 = date.IsoWeekYear();  // 2026
int wy2 = dto.IsoWeekYear();   // 2026

// ISO weekday: 1 = Monday … 7 = Sunday
int wd1 = date.IsoWeekday();  // 1 (Monday)
int wd2 = dto.IsoWeekday();   // 1 (Monday)

DST Queries

DST-awareness helpers on DateTimeOffset.

var summer = new DateTimeOffset(2026, 6, 15, 12, 0, 0, TimeSpan.Zero); // CEST
var winter = new DateTimeOffset(2026, 1, 15, 12, 0, 0, TimeSpan.Zero); // CET

// Is the instant in DST for a given time zone?
bool inDst1 = summer.IsInDst(TimeZones.CentralEuropean);  // true
bool inDst2 = winter.IsInDst(TimeZones.CentralEuropean);  // false

// Is the wall-clock time ambiguous (fall-back hour)?
// 2026-10-25 02:30 exists twice in Europe/Berlin
var ambiguous = new DateTimeOffset(2026, 10, 25, 0, 30, 0, TimeSpan.Zero); // 02:30 UTC+2
bool isAmbiguous = ambiguous.IsDstAmbiguous(TimeZones.CentralEuropean);    // true

Unix Time

Unix epoch timestamp helpers for DateTimeOffset. Inspired by Luxon's DateTime.fromSeconds() / DateTime.fromMillis().

// Create from Unix timestamp
DateTimeOffset dto1 = UnixTimeExtensions.FromUnixSeconds(1_750_000_000L);
DateTimeOffset dto2 = UnixTimeExtensions.FromUnixMilliseconds(1_750_000_000_000L);

// Convert to Unix timestamp (sub-second precision is truncated)
long seconds = dto1.ToUnixSeconds();
long millis  = dto1.ToUnixMilliseconds();

JSON Converters

All converters live in the Horae.Converters namespace and can be used via [JsonConverter] attributes or through JsonSerializerOptions.Converters.

Converter Type JSON representation
IsoDateTimeOffsetConverter DateTimeOffset "2026-01-01T23:00:00Z"
NullableIsoDateTimeOffsetConverter DateTimeOffset? "2026-01-01T23:00:00Z" / null
IsoDateConverter DateOnly "2026-01-01"
NullableIsoDateConverter DateOnly? "2026-01-01" / null
DurationConverter Duration "PT15M"
NullableDurationConverter Duration? "PT15M" / null
record DeliveryPeriod(
    [property: JsonConverter(typeof(IsoDateTimeOffsetConverter))]
    DateTimeOffset Start,

    [property: JsonConverter(typeof(IsoDateTimeOffsetConverter))]
    DateTimeOffset End,

    [property: JsonConverter(typeof(IsoDateConverter))]
    DateOnly DeliveryDate,

    [property: JsonConverter(typeof(DurationConverter))]
    Duration Duration);

IsoDateTimeFormatAttribute

Use [IsoDateTimeFormat] instead of [JsonConverter(typeof(...))] on DateTimeOffset and DateTimeOffset? properties to control sub-second precision directly on the attribute:

record Event(
    // Always emit 7 fractional digits: "2026-01-01T23:00:00.0000000Z"
    [property: IsoDateTimeFormat(IsoDateTimePrecision.Fractional)]
    DateTimeOffset Timestamp,

    // Always omit sub-seconds (default): "2026-01-01T23:00:00Z"
    [property: IsoDateTimeFormat]
    DateTimeOffset Start,

    // Include sub-seconds only when non-zero
    [property: IsoDateTimeFormat(IsoDateTimePrecision.Auto)]
    DateTimeOffset? End);

IsoDateTimePrecision values:

Value Behavior
Seconds (default) Always omit sub-second digits — "...T23:00:00Z"
Auto Include sub-second digits only when non-zero
Fractional Always include 7 sub-second digits — "...T23:00:00.0000000Z"

Time Zone Constants

TimeZones provides TimeZoneInfo instances for common regions (IANA IDs, supported on all platforms since .NET 6).

Property IANA ID Offset (standard time)
TimeZones.Utc UTC +00:00
TimeZones.CentralEuropean Europe/Berlin +01:00 / +02:00
TimeZones.London Europe/London +00:00 / +01:00
TimeZones.Lisbon Europe/Lisbon +00:00 / +01:00
TimeZones.EasternEurope Europe/Athens +02:00 / +03:00
TimeZones.Moscow Europe/Moscow +03:00 (no DST)
TimeZones.Istanbul Europe/Istanbul +03:00 (no DST)
TimeZones.EasternUs America/New_York -05:00 / -04:00
TimeZones.PacificUs America/Los_Angeles -08:00 / -07:00
TimeZones.Dubai Asia/Dubai +04:00 (no DST)
TimeZones.India Asia/Kolkata +05:30 (no DST)
TimeZones.Japan Asia/Tokyo +09:00 (no DST)
TimeZones.AustraliaEastern Australia/Sydney +10:00 / +11:00
Product 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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.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.

Version Downloads Last Updated
1.0.6 131 5/10/2026

Initial public release (v1.0.0). See CHANGELOG.md for full details. Highlights: ZonedTimeInterval (timezone-preserving interval), IsoDateTimePrecision (sub-second control for JSON serialization), Duration type (ISO 8601 durations with named presets), DST-safe TimeInterval.SplitByDays, SourceLink support.