w4c-workflows-api/Services/DurationParser.cs

47 lines
1.5 KiB
C#
Raw Permalink Normal View History

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;
}
}