novolis-time / getting-started.md
Getting started
Prerequisites
- .NET 10 (
net10.0) - NuGet sources: nuget.org + GitHub Packages (
https://nuget.pkg.github.com/Novolis-Platform/index.json) - Local multi-repo work: ProjectReference mode via
-p:NovolisUseProjectReferences=true(see platform-project-ref-mode)
Install
dotnet add package Novolis.Time
dotnet add package Novolis.Time.Workday
dotnet add package Novolis.Time.WorktimeAdd Novolis.Time.Week for week-based calendars, and Novolis.Time.Worktime.Legal only when a product needs the draft presets.
Clock interval
using Novolis.Time;
var core = new ClockInterval(new TimeOnly(9, 0), new TimeOnly(15, 0));
var overlap = core.OverlapDuration(new ClockInterval(new TimeOnly(8, 0), new TimeOnly(12, 0)));An interval must end after it starts on the same local day. Overnight ranges are rejected.
Workdays
using Novolis.Time.Workday;
var calendar = WorkdayCalendar.FromGeneratedHolidays("no-workdays-2026", "NO", 2026);
var constitutionDay = calendar.IsWorkday(new DateOnly(2026, 5, 17));
var due = BusinessDayCalculator.AddBusinessDays(new DateOnly(2026, 5, 15), 1, calendar);Public holidays are frozen facts embedded in Novolis.Time.Workday. Regenerate them with:
dotnet run --project d:\novolis\novolis-time\tools\GeneratePublicHolidays\GeneratePublicHolidays.csproj -- d:\novolis\novolis-time\src\Novolis.Time.Workday\GeneratedHolidays.jsonExpected versus actual
using Novolis.Time;
using Novolis.Time.Workday;
using Novolis.Time.Worktime;
var profile = new WorktimeProfile(
"oslo-office",
"Oslo office",
new ClockInterval(new TimeOnly(7, 0), new TimeOnly(17, 0)),
new ClockInterval(new TimeOnly(9, 0), new TimeOnly(15, 0)),
new ClockInterval(new TimeOnly(11, 30), new TimeOnly(12, 0)),
TimeSpan.FromHours(37.5),
TimeSpan.FromHours(7.5),
PresenceClassification.Flex);
var template = new ExpectedDayTemplate(
"office-day",
"Office day",
[new KeyValuePair<DayOfWeek, ClockInterval>(DayOfWeek.Thursday, new ClockInterval(new TimeOnly(8, 0), new TimeOnly(16, 0)))]);
var settings = new EmploymentSettings(
"employee-1",
profile,
WorkdayCalendar.FromGeneratedHolidays("no-workdays-2026", "NO", 2026),
template,
1m);
var expected = WorktimeCalculator.CreateExpectedSnapshot(new DateOnly(2026, 10, 1), settings);settings freezes the profile, template, workday calendar, and employment fraction used for that day.
Build and test
dotnet test d:\novolis\novolis-time\tests\Novolis.Time.Unit\Novolis.Time.Unit.csproj -p:NovolisUseProjectReferences=true