diff --git a/src/Commands/RemindCommandGroup.cs b/src/Commands/RemindCommandGroup.cs index 3754bd2..77f2429 100644 --- a/src/Commands/RemindCommandGroup.cs +++ b/src/Commands/RemindCommandGroup.cs @@ -146,7 +146,7 @@ public class RemindCommandGroup : CommandGroup var data = await _guildData.GetData(guildId, CancellationToken); Messages.Culture = GuildSettings.Language.Get(data.Settings); - var parseResult = TimeSpanParser.TryParse(stringTimeSpan, CancellationToken); + var parseResult = TimeSpanParser.TryParse(stringTimeSpan); if (!parseResult.IsDefined(out var timeSpan)) { var failedEmbed = new EmbedBuilder() diff --git a/src/Parsers/TimeSpanParser.cs b/src/Parsers/TimeSpanParser.cs index 0033ed9..e00c09e 100644 --- a/src/Parsers/TimeSpanParser.cs +++ b/src/Parsers/TimeSpanParser.cs @@ -23,11 +23,11 @@ public partial class TimeSpanParser : AbstractTypeParser /// /// If parse wasn't successful, will return . /// - public static Result TryParse(string timeSpanString, CancellationToken ct = default) + public static Result TryParse(string timeSpanString) { if (timeSpanString.StartsWith('-')) { - return new ArgumentInvalidError(nameof(timeSpanString), "TimeSpan cannot be inverted."); + return new ArgumentInvalidError(nameof(timeSpanString), "TimeSpans cannot be negative."); } if (TimeSpan.TryParse(timeSpanString, DateTimeFormatInfo.InvariantInfo, out var parsedTimeSpan)) @@ -38,10 +38,16 @@ public partial class TimeSpanParser : AbstractTypeParser var matches = ParseRegex().Matches(timeSpanString); if (matches.Count is 0) { - return new ArgumentInvalidError(nameof(timeSpanString), "Invalid TimeSpan."); + return new ArgumentInvalidError(nameof(timeSpanString), "The regex did not produce any matches."); } + return ParseFromRegex(matches); + } + + private static TimeSpan ParseFromRegex(MatchCollection matches) + { var timeSpan = TimeSpan.Zero; + foreach (var groups in matches.Select(match => match.Groups .Cast() .Where(g => g.Success) @@ -50,61 +56,30 @@ public partial class TimeSpanParser : AbstractTypeParser { foreach ((var key, var groupValue) in groups) { - return double.TryParse(groupValue, out var parsedGroupValue) - ? ParseFromRegex(timeSpan, key, groupValue, parsedGroupValue) - : TimeSpan.Zero; + if (!double.TryParse(groupValue, out var parsedGroupValue) || + !int.TryParse(groupValue, out var parsedIntegerValue)) + { + return TimeSpan.Zero; + } + + var now = DateTimeOffset.UtcNow; + timeSpan += key switch + { + "Years" => now.AddYears(parsedIntegerValue) - now, + "Months" => now.AddMonths(parsedIntegerValue) - now, + "Weeks" => TimeSpan.FromDays(parsedGroupValue * 7), + "Days" => TimeSpan.FromDays(parsedGroupValue), + "Hours" => TimeSpan.FromHours(parsedGroupValue), + "Minutes" => TimeSpan.FromMinutes(parsedGroupValue), + "Seconds" => TimeSpan.FromSeconds(parsedGroupValue), + _ => throw new ArgumentOutOfRangeException(key) + }; } } return timeSpan; } - private static TimeSpan ParseFromRegex(TimeSpan timeSpan, - string key, string groupValue, double parsedGroupValue) - { - if (key is "Years" or "Months") - { - if (!int.TryParse(groupValue, out var parsedIntegerValue)) - { - return TimeSpan.Zero; - } - - switch (key) - { - case "Years": - { - var now = DateTimeOffset.UtcNow; - var then = now.AddYears(parsedIntegerValue); - - timeSpan += then - now; - break; - } - case "Months": - { - var now = DateTimeOffset.UtcNow; - var then = now.AddMonths(parsedIntegerValue); - - timeSpan += then - now; - break; - } - } - - return timeSpan; - } - - timeSpan += key switch - { - "Weeks" => TimeSpan.FromDays(parsedGroupValue * 7), - "Days" => TimeSpan.FromDays(parsedGroupValue), - "Hours" => TimeSpan.FromHours(parsedGroupValue), - "Minutes" => TimeSpan.FromMinutes(parsedGroupValue), - "Seconds" => TimeSpan.FromSeconds(parsedGroupValue), - _ => throw new ArgumentOutOfRangeException(key) - }; - - return timeSpan; - } - [GeneratedRegex("(?\\d+(?=y|л|г))|(?\\d+(?=mo|мес))|(?\\d+(?=w|н|нед))|(?\\d+(?=d|дн))|(?\\d+(?=h|ч))|(?\\d+(?=m|min|мин|м))|(?\\d+(?=s|sec|с|сек))")] private static partial Regex ParseRegex(); }