Skip to main content

Vali-Duration

ValiDuration is a high-precision decimal duration value type. It provides factory methods, arithmetic operators, unit conversion, formatting, and seamless interop with TimeSpan.

Installation

dotnet add package Vali-Duration

ValiDuration Struct

ValiDuration stores its value as decimal milliseconds internally, avoiding floating-point drift in arithmetic operations.

Factory Methods

MethodDescription
ValiDuration.FromMilliseconds(decimal)Create from milliseconds
ValiDuration.FromSeconds(decimal)Create from seconds
ValiDuration.FromMinutes(decimal)Create from minutes
ValiDuration.FromHours(decimal)Create from hours
ValiDuration.FromDays(decimal)Create from days
ValiDuration.FromWeeks(decimal)Create from weeks (7-day)
ValiDuration.FromMonths(decimal)Create from months (30.4375 days average)
ValiDuration.FromYears(decimal)Create from years (365.25 days average)
ValiDuration.FromTimeSpan(TimeSpan)Create from a TimeSpan
ValiDuration.ZeroA zero-length duration
var d1 = ValiDuration.FromHours(2.5m);
var d2 = ValiDuration.FromMinutes(90m);
var d3 = ValiDuration.FromTimeSpan(TimeSpan.FromDays(7));
var d4 = ValiDuration.Zero;

Properties

PropertyTypeDescription
TotalMillisecondsdecimalTotal value in milliseconds
TotalSecondsdecimalTotal value in seconds
TotalMinutesdecimalTotal value in minutes
TotalHoursdecimalTotal value in hours
TotalDaysdecimalTotal value in days
var d = ValiDuration.FromHours(2.5m);
Console.WriteLine(d.TotalMinutes); // → 150
Console.WriteLine(d.TotalMilliseconds); // → 9_000_000

Instance Methods

As

Convert the duration to a decimal value in the specified unit:

var d = ValiDuration.FromDays(1.5m);
decimal hours = d.As(TimeUnit.Hours); // → 36
decimal mins = d.As(TimeUnit.Minutes); // → 2160

Signature: decimal As(TimeUnit unit)

Format

Format the duration as a human-readable string:

var d = ValiDuration.FromMinutes(90m);
Console.WriteLine(d.Format()); // → "1h 30m"
Console.WriteLine(d.Format(1)); // → "1.5 hours"

Signature: string Format(int decimalPlaces = 0)

ToTimeSpan

Convert to a TimeSpan. Note: TimeSpan uses double internally, so very large or very precise values may lose precision:

var d  = ValiDuration.FromHours(2.5m);
TimeSpan ts = d.ToTimeSpan();
// → TimeSpan of 2h 30m

Signature: TimeSpan ToTimeSpan()

Arithmetic Operators

ValiDuration supports all standard arithmetic operations:

var a = ValiDuration.FromHours(1.5m);
var b = ValiDuration.FromMinutes(30m);

ValiDuration sum = a + b; // 2 hours
ValiDuration diff = a - b; // 1 hour
ValiDuration scaled = a * 2m; // 3 hours
ValiDuration halved = a / 2m; // 45 minutes

bool equal = a == b;
bool greater = a > b;
bool less = a < b;

Comparison Operators

All six comparison operators are supported (==, !=, <, <=, >, >=):

var oneHour  = ValiDuration.FromHours(1m);
var twoHours = ValiDuration.FromHours(2m);

bool result = oneHour < twoHours; // → true

Implicit Conversions

// From TimeSpan
ValiDuration d = TimeSpan.FromHours(2); // implicit

// To TimeSpan
TimeSpan ts = ValiDuration.FromMinutes(90m); // implicit

Complete Example

public class BillingService
{
public void CalculateBilling(TimeSpan[] sessionDurations, decimal hourlyRate)
{
// Convert all sessions to ValiDuration
var durations = sessionDurations
.Select(ValiDuration.FromTimeSpan)
.ToArray();

// Sum all sessions
var total = durations.Aggregate(ValiDuration.Zero, (acc, d) => acc + d);

Console.WriteLine($"Total time: {total.Format(1)}");
Console.WriteLine($"Total hours: {total.TotalHours:F2}");

// Calculate billing
decimal billableHours = total.As(TimeUnit.Hours);
decimal amount = billableHours * hourlyRate;

Console.WriteLine($"Billable: {billableHours:F2}h × ${hourlyRate}/h = ${amount:F2}");

// Check if over 8-hour workday
var workday = ValiDuration.FromHours(8m);
if (total > workday)
{
ValiDuration overtime = total - workday;
Console.WriteLine($"Overtime: {overtime.Format(1)}");
}
}
}