-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes #154 --------- Signed-off-by: mctaylors <[email protected]>
- Loading branch information
Showing
10 changed files
with
183 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
using System.Globalization; | ||
using System.Text.RegularExpressions; | ||
using JetBrains.Annotations; | ||
using Remora.Commands.Parsers; | ||
using Remora.Results; | ||
|
||
namespace Octobot.Parsers; | ||
|
||
/// <summary> | ||
/// Parses <see cref="TimeSpan"/>s. | ||
/// </summary> | ||
[PublicAPI] | ||
public partial class TimeSpanParser : AbstractTypeParser<TimeSpan> | ||
{ | ||
private static readonly Regex Pattern = ParseRegex(); | ||
|
||
/// <summary> | ||
/// Parses a <see cref="TimeSpan"/> from the <paramref name="timeSpanString"/>. | ||
/// </summary> | ||
/// <returns> | ||
/// The parsed <see cref="TimeSpan"/>, or <see cref="ArgumentInvalidError"/> if parsing failed. | ||
/// </returns> | ||
public static Result<TimeSpan> TryParse(string timeSpanString) | ||
{ | ||
if (timeSpanString.StartsWith('-')) | ||
{ | ||
return new ArgumentInvalidError(nameof(timeSpanString), "TimeSpans cannot be negative."); | ||
} | ||
|
||
if (TimeSpan.TryParse(timeSpanString, DateTimeFormatInfo.InvariantInfo, out var parsedTimeSpan)) | ||
{ | ||
return parsedTimeSpan; | ||
} | ||
|
||
var matches = ParseRegex().Matches(timeSpanString); | ||
return matches.Count > 0 | ||
? ParseFromRegex(matches) | ||
: new ArgumentInvalidError(nameof(timeSpanString), "The regex did not produce any matches."); | ||
} | ||
|
||
private static Result<TimeSpan> ParseFromRegex(MatchCollection matches) | ||
{ | ||
var timeSpan = TimeSpan.Zero; | ||
|
||
foreach (var groups in matches.Select(match => match.Groups | ||
.Cast<Group>() | ||
.Where(g => g.Success) | ||
.Skip(1) | ||
.Select(g => (g.Name, g.Value)))) | ||
{ | ||
foreach ((var key, var groupValue) in groups) | ||
{ | ||
if (!int.TryParse(groupValue, out var parsedIntegerValue)) | ||
{ | ||
return new ArgumentInvalidError(nameof(groupValue), "The input value was not an integer."); | ||
} | ||
|
||
var now = DateTimeOffset.UtcNow; | ||
timeSpan += key switch | ||
{ | ||
"Years" => now.AddYears(parsedIntegerValue) - now, | ||
"Months" => now.AddMonths(parsedIntegerValue) - now, | ||
"Weeks" => TimeSpan.FromDays(parsedIntegerValue * 7), | ||
"Days" => TimeSpan.FromDays(parsedIntegerValue), | ||
"Hours" => TimeSpan.FromHours(parsedIntegerValue), | ||
"Minutes" => TimeSpan.FromMinutes(parsedIntegerValue), | ||
"Seconds" => TimeSpan.FromSeconds(parsedIntegerValue), | ||
_ => throw new ArgumentOutOfRangeException(key) | ||
}; | ||
} | ||
} | ||
|
||
return timeSpan; | ||
} | ||
|
||
[GeneratedRegex("(?<Years>\\d+(?=y|л|г))|(?<Months>\\d+(?=mo|мес))|(?<Weeks>\\d+(?=w|н|нед))|(?<Days>\\d+(?=d|д|дн))|(?<Hours>\\d+(?=h|ч))|(?<Minutes>\\d+(?=m|min|мин|м))|(?<Seconds>\\d+(?=s|sec|с|сек))")] | ||
private static partial Regex ParseRegex(); | ||
} |