From bef1c46f9f3604efc066dfc66c11c55373115037 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Thu, 4 Jul 2024 00:57:28 -0400 Subject: [PATCH 1/4] Trim input string --- TwitchDownloaderCLI/Models/TimeDuration.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TwitchDownloaderCLI/Models/TimeDuration.cs b/TwitchDownloaderCLI/Models/TimeDuration.cs index 67daabf9..e43c8b79 100644 --- a/TwitchDownloaderCLI/Models/TimeDuration.cs +++ b/TwitchDownloaderCLI/Models/TimeDuration.cs @@ -37,6 +37,8 @@ public static TimeDuration Parse(string str) throw new FormatException(); } + str = str.Trim(); + if (str.Contains(':')) { var timeSpan = TimeSpan.Parse(str); From b894c3f3badcfd8f398d51cdb1056bf6823456db Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Thu, 4 Jul 2024 21:28:20 -0400 Subject: [PATCH 2/4] Fix parsing timespans >24 hours --- TwitchDownloaderCLI/Models/TimeDuration.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/TwitchDownloaderCLI/Models/TimeDuration.cs b/TwitchDownloaderCLI/Models/TimeDuration.cs index e43c8b79..e9d1c269 100644 --- a/TwitchDownloaderCLI/Models/TimeDuration.cs +++ b/TwitchDownloaderCLI/Models/TimeDuration.cs @@ -41,7 +41,7 @@ public static TimeDuration Parse(string str) if (str.Contains(':')) { - var timeSpan = TimeSpan.Parse(str); + var timeSpan = ParseTimeSpan(str); return new TimeDuration(timeSpan); } @@ -55,6 +55,24 @@ public static TimeDuration Parse(string str) throw new FormatException(); } + private static TimeSpan ParseTimeSpan(string str) + { + // TimeSpan.Parse interprets '36:01:02' as 36 days, 1 hour, and 2 minutes, so we need to manually parse it ourselves + var match = Regex.Match(str, @"^(?:(\d{1,})[.:])?(\d{2,}):(\d{1,2}):(\d{1,2})(?:\.(\d{1,3})\d*)?$"); + if (match.Success) + { + if (!int.TryParse(match.Groups[1].ValueSpan, out var days)) days = 0; + if (!int.TryParse(match.Groups[2].ValueSpan, out var hours)) hours = 0; + if (!int.TryParse(match.Groups[3].ValueSpan, out var minutes)) minutes = 0; + if (!int.TryParse(match.Groups[4].ValueSpan, out var seconds)) seconds = 0; + if (!int.TryParse(match.Groups[5].Value.PadRight(3, '0'), out var milliseconds)) milliseconds = 0; + + return new TimeSpan(days, hours, minutes, seconds, milliseconds); + } + + return TimeSpan.Parse(str); // Parse formats not covered by the regex + } + private static long GetMultiplier(string input, out ReadOnlySpan trimmedInput) { if (char.IsDigit(input[^1])) From 7a11617bf853bb78839807400a1b62afa161d328 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Thu, 4 Jul 2024 21:28:34 -0400 Subject: [PATCH 3/4] Update tests --- .../ModelTests/TimeDurationTests.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/TwitchDownloaderCLI.Tests/ModelTests/TimeDurationTests.cs b/TwitchDownloaderCLI.Tests/ModelTests/TimeDurationTests.cs index 6a320f7f..22e14a8f 100644 --- a/TwitchDownloaderCLI.Tests/ModelTests/TimeDurationTests.cs +++ b/TwitchDownloaderCLI.Tests/ModelTests/TimeDurationTests.cs @@ -16,6 +16,11 @@ public class TimeDurationTests [InlineData("0:09:27", 9 * TicksPerMinute + 27 * TicksPerSecond)] [InlineData("11:30", 11 * TicksPerHour + 30 * TicksPerMinute)] [InlineData("12:03:45", 12 * TicksPerHour + 3 * TicksPerMinute + 45 * TicksPerSecond)] + [InlineData("39:23:02", 39 * TicksPerHour + 23 * TicksPerMinute + 2 * TicksPerSecond)] + [InlineData("47:22:08.123", 47 * TicksPerHour + 22 * TicksPerMinute + 8 * TicksPerSecond + 123 * TicksPerMillisecond)] + [InlineData("47:22:08.12345", 47 * TicksPerHour + 22 * TicksPerMinute + 8 * TicksPerSecond + 123 * TicksPerMillisecond)] + [InlineData("1.2:3:4.5", 1 * TicksPerDay + 2 * TicksPerHour + 3 * TicksPerMinute + 4 * TicksPerSecond + 500 * TicksPerMillisecond)] + [InlineData("2:03:54:27.26", 2 * TicksPerDay + 3 * TicksPerHour + 54 * TicksPerMinute + 27 * TicksPerSecond + 260 * TicksPerMillisecond)] public void CorrectlyParsesTimeStrings(string input, long expectedTicks) { var expected = new TimeDuration(expectedTicks); @@ -33,10 +38,7 @@ public void CorrectlyParsesTimeStrings(string input, long expectedTicks) [InlineData("0:12345")] public void ThrowsOnBadFormat(string input) { - Assert.ThrowsAny(() => - { - _ = TimeDuration.Parse(input); - }); + Assert.ThrowsAny(() => TimeDuration.Parse(input)); } } } \ No newline at end of file From 6af6f74685e1551d8c280c708303767f9575729e Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Fri, 5 Jul 2024 20:59:29 -0400 Subject: [PATCH 4/4] Override TimeDuration.ToString() --- TwitchDownloaderCLI/Models/TimeDuration.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TwitchDownloaderCLI/Models/TimeDuration.cs b/TwitchDownloaderCLI/Models/TimeDuration.cs index e9d1c269..1b28d504 100644 --- a/TwitchDownloaderCLI/Models/TimeDuration.cs +++ b/TwitchDownloaderCLI/Models/TimeDuration.cs @@ -1,11 +1,9 @@ using System; -using System.Diagnostics; using System.Globalization; using System.Text.RegularExpressions; namespace TwitchDownloaderCLI.Models { - [DebuggerDisplay("{_timeSpan}")] public readonly record struct TimeDuration { public static TimeDuration MinusOneSeconds { get; } = new(-1 * TimeSpan.TicksPerSecond); @@ -30,6 +28,8 @@ public TimeDuration(long ticks) _timeSpan = TimeSpan.FromTicks(ticks); } + public override string ToString() => _timeSpan.ToString(); + public static TimeDuration Parse(string str) { if (string.IsNullOrWhiteSpace(str))