Table of Contents

Persistence and schedule-zone conversions — PrimeTime (NodaTime), production

This scenario uses IPrimeTime extension methods to project a persisted Instant into the clock’s schedule zone, and shows PrimeTimeOfDayConversion plus NodaDurationBclConversion for storage-friendly shapes and delay TimeSpan clamping.

For the conceptual background, see Persistence and time conversions.

ServiceCollection services = [];
services.AddPrimeClock();

using ServiceProvider serviceProvider = services.BuildServiceProvider();
IPrimeClock primeClock = serviceProvider.GetRequiredService<IPrimeClock>();
IPrimeTime time = primeClock;

Instant persistedUtc = Instant.FromUtc(2025, 7, 4, 15, 30, 0);

ScenarioConsole.WriteLine($"Schedule zoned: {time.ToScheduleZonedDateTime(persistedUtc)}");
ScenarioConsole.WriteLine($"Schedule local date: {time.ToScheduleLocalDate(persistedUtc)}");
ScenarioConsole.WriteLine($"Schedule DateTimeOffset: {time.ToScheduleDateTimeOffset(persistedUtc):O}");

LocalTime wallTime = time.ToScheduleLocalTime(persistedUtc);
LocalTimeOfDay storedTimeOfDay = PrimeTimeOfDayConversion.ToLocalTimeOfDay(wallTime);
ScenarioConsole.WriteLine(
    $"LocalTimeOfDay round-trip equals wall LocalTime: "
    + $"{PrimeTimeOfDayConversion.ToLocalTime(storedTimeOfDay).Equals(wallTime)}");

Duration beyondBclRange = Duration.FromTimeSpan(TimeSpan.MaxValue) + Duration.FromSeconds(1);
ScenarioConsole.WriteLine(
    $"Noda delay clamped to BCL: {NodaDurationBclConversion.ToTimeSpanForDelay(beyondBclRange)}");

return Task.CompletedTask;

What to notice

  • ToScheduleZonedDateTime, ToScheduleLocalDate, ToScheduleLocalTime, and ToScheduleDateTimeOffset all interpret the instant in LocalScheduleDateTimeZone (see IPrimeClock.LocalScheduleDateTimeZone).
  • LocalTimeOfDay round-trips with LocalTime via PrimeTimeOfDayConversion using midnight-based ticks.
  • NodaDurationBclConversion.ToTimeSpanForDelay clamps oversized Duration values so BCL delays remain representable.