Ir al contenido principal

Vali-Time

IValiTime proporciona conversiones de unidades de tiempo de alta precisión usando aritmética decimal — eliminando la deriva de punto flotante habitual en las conversiones basadas en double.

Instalación

dotnet add package Vali-Time

Registro

builder.Services.AddValiTime();
// o mediante el meta-paquete:
builder.Services.AddValiTempo();

Enumeraciones

TimeUnit

Representa una unidad de medida de tiempo:

ValorDescripción
Milliseconds1/1000 de un segundo
SecondsUnidad SI base de tiempo
Minutes60 segundos
Hours60 minutos
Days24 horas
Weeks7 días
MonthsMes calendario (promedio 30.4375 días)
YearsAño calendario (promedio 365.25 días)

DatePart

Se usa al extraer componentes de un DateTime:

ValorDescripción
YearEl componente año
MonthEl componente mes (1–12)
DayEl componente día del mes
HourEl componente hora (0–23)
MinuteEl componente minuto
SecondEl componente segundo
DayOfWeekDía de la semana (0=Domingo)

WeekStart

Define qué día inicia la semana, usado en los cálculos de semana del año:

ValorDescripción
SundayLa semana empieza el domingo (convención US)
MondayLa semana empieza el lunes (estándar ISO 8601)

API de IValiTime

Convert

Convierte un valor de una unidad de tiempo a otra:

decimal hours = time.Convert(90, TimeUnit.Minutes, TimeUnit.Hours);
// → 1.5

decimal ms = time.Convert(2.5m, TimeUnit.Seconds, TimeUnit.Milliseconds);
// → 2500

Firma: decimal Convert(decimal value, TimeUnit from, TimeUnit to)

SumTimes

Suma múltiples valores (todos en la misma unidad) y devuelve el total en una unidad destino:

decimal totalHours = time.SumTimes(
new[] { 30m, 45m, 90m },
TimeUnit.Minutes,
TimeUnit.Hours
);
// → 2.75

Firma: decimal SumTimes(IEnumerable<decimal> values, TimeUnit inputUnit, TimeUnit outputUnit)

SubtractTimes

Resta un valor de tiempo de otro:

decimal diff = time.SubtractTimes(120m, 45m, TimeUnit.Minutes, TimeUnit.Hours);
// → 1.25

Firma: decimal SubtractTimes(decimal a, decimal b, TimeUnit inputUnit, TimeUnit outputUnit)

FormatTime

Formatea un valor de tiempo decimal en una cadena legible para humanos con redondeo:

string s1 = time.FormatTime(1.5m, TimeUnit.Hours, 0);
// → "2 hours"

string s2 = time.FormatTime(90m, TimeUnit.Minutes, 1);
// → "1.5 hours"

string s3 = time.FormatTime(45m, TimeUnit.Seconds, 0);
// → "45 seconds"

Firma: string FormatTime(decimal value, TimeUnit unit, int decimalPlaces)

GetBestUnit

Dado un tiempo en segundos, devuelve la unidad más legible para humanos junto con el valor convertido:

var (value, unit) = time.GetBestUnit(3661);
// value: 1.0169..., unit: TimeUnit.Hours

var (value2, unit2) = time.GetBestUnit(90);
// value2: 1.5, unit2: TimeUnit.Minutes

Firma: (decimal time, TimeUnit unit) GetBestUnit(decimal seconds)

ParseTime

Analiza una cadena legible para humanos en un valor decimal y su unidad:

(decimal value, TimeUnit unit) = time.ParseTime("2.5 hours");
// value = 2.5, unit = TimeUnit.Hours

(decimal v2, TimeUnit u2) = time.ParseTime("90 minutes");
// v2 = 90, u2 = TimeUnit.Minutes

Firma: (decimal value, TimeUnit unit) ParseTime(string input)

Breakdown

Descompone un valor total en un diccionario de unidades componentes:

var parts = time.Breakdown(3661m, TimeUnit.Seconds);
// → { Hours: 1, Minutes: 1, Seconds: 1 }

var parts2 = time.Breakdown(90m, TimeUnit.Minutes);
// → { Hours: 1, Minutes: 30 }

Firma: Dictionary<TimeUnit, decimal> Breakdown(decimal value, TimeUnit sourceUnit)

ToTimeSpan

Convierte un valor decimal en una unidad dada a un TimeSpan:

TimeSpan ts = time.ToTimeSpan(2.5m, TimeUnit.Hours);
// → TimeSpan de 2h 30m

Firma: TimeSpan ToTimeSpan(decimal value, TimeUnit unit)

FromTimeSpan

Convierte un TimeSpan a un valor decimal en la unidad especificada:

decimal minutes = time.FromTimeSpan(TimeSpan.FromHours(1.5), TimeUnit.Minutes);
// → 90

Firma: decimal FromTimeSpan(TimeSpan span, TimeUnit unit)

Clamp

Restringe un valor dentro de un mínimo y un máximo (todos en la misma unidad):

decimal clamped = time.Clamp(150m, TimeUnit.Minutes, 0m, 120m);
// → 120 (restringido al máximo)

decimal clamped2 = time.Clamp(-5m, TimeUnit.Minutes, 0m, 120m);
// → 0 (restringido al mínimo)

Firma: decimal Clamp(decimal value, TimeUnit unit, decimal min, decimal max)

Compare

Compara dos valores de tiempo (que pueden estar en unidades distintas). Devuelve -1, 0 o 1:

int result = time.Compare(60m, TimeUnit.Minutes, 1m, TimeUnit.Hours);
// → 0 (iguales)

int result2 = time.Compare(90m, TimeUnit.Seconds, 2m, TimeUnit.Minutes);
// → -1 (90s < 2min)

Firma: int Compare(decimal a, TimeUnit aUnit, decimal b, TimeUnit bUnit)

MultiConvert

Convierte un valor de una unidad a múltiples unidades destino a la vez:

var results = time.MultiConvert(3600m, TimeUnit.Seconds,
TimeUnit.Hours, TimeUnit.Minutes, TimeUnit.Days);
// → { Hours: 1, Minutes: 60, Days: 0.0416... }

Firma: Dictionary<TimeUnit, decimal> MultiConvert(decimal value, TimeUnit from, params TimeUnit[] targets)

Ejemplo completo

public class WorklogService(IValiTime time)
{
public void AnalyzeWorklog(decimal[] taskDurationsInMinutes)
{
// Total en horas
decimal totalHours = time.SumTimes(taskDurationsInMinutes, TimeUnit.Minutes, TimeUnit.Hours);

// Mejor unidad de visualización
decimal totalSeconds = time.Convert(totalHours, TimeUnit.Hours, TimeUnit.Seconds);
var (bestValue, bestUnit) = time.GetBestUnit(totalSeconds);
string formatted = time.FormatTime(totalHours, TimeUnit.Hours, 1);

// Desglose en componentes
var parts = time.Breakdown(totalHours, TimeUnit.Hours);

Console.WriteLine($"Total work: {formatted}");
Console.WriteLine($"Hours: {parts[TimeUnit.Hours]}, Minutes: {parts[TimeUnit.Minutes]}");

// Comparar con una jornada de 8 horas
int cmp = time.Compare(totalHours, TimeUnit.Hours, 8m, TimeUnit.Hours);
if (cmp < 0) Console.WriteLine("Undertime");
else if (cmp > 0) Console.WriteLine("Overtime");
else Console.WriteLine("Exact 8 hours");
}
}