47 lines
1.5 KiB
C#
47 lines
1.5 KiB
C#
using System.Text.RegularExpressions;
|
|
|
|
namespace w4c_workflows.Services;
|
|
|
|
/// <summary>
|
|
/// Parses human durations like "45s", "30m", "2h", "1d" (also compound forms
|
|
/// like "1h30m"). Used by YAML validation and the interval trigger scheduler.
|
|
/// </summary>
|
|
public static partial class DurationParser
|
|
{
|
|
[GeneratedRegex(@"(?<num>\d+(?:\.\d+)?)(?<unit>ms|s|m|h|d)", RegexOptions.Compiled)]
|
|
private static partial Regex PartRegex();
|
|
|
|
public static bool TryParse(string? text, out TimeSpan result)
|
|
{
|
|
result = TimeSpan.Zero;
|
|
if (string.IsNullOrWhiteSpace(text))
|
|
return false;
|
|
|
|
var matches = PartRegex().Matches(text);
|
|
if (matches.Count == 0)
|
|
return false;
|
|
|
|
var total = TimeSpan.Zero;
|
|
foreach (Match match in matches)
|
|
{
|
|
var value = double.Parse(match.Groups["num"].Value, System.Globalization.CultureInfo.InvariantCulture);
|
|
var unit = match.Groups["unit"].Value;
|
|
total += unit switch
|
|
{
|
|
"ms" => TimeSpan.FromMilliseconds(value),
|
|
"s" => TimeSpan.FromSeconds(value),
|
|
"m" => TimeSpan.FromMinutes(value),
|
|
"h" => TimeSpan.FromHours(value),
|
|
"d" => TimeSpan.FromDays(value),
|
|
_ => throw new InvalidOperationException($"Unknown unit {unit}"),
|
|
};
|
|
}
|
|
|
|
if (total <= TimeSpan.Zero)
|
|
return false;
|
|
|
|
result = total;
|
|
return true;
|
|
}
|
|
}
|