Skip to content

Commit 67d068f

Browse files
committed
Adds null/empty checks to date math parsing
Ensures that the `DateMath.Parse` and `TimeUnit.Parse` methods handle null or empty expressions gracefully by throwing `ArgumentException` or `ArgumentNullException` as appropriate. This prevents unexpected behavior and improves the robustness of the date parsing logic. Also updates `TryParse` methods to accept nullable string parameters.
1 parent 18e4d95 commit 67d068f

4 files changed

Lines changed: 20 additions & 13 deletions

File tree

src/Exceptionless.DateTimeExtensions/DateMath.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public static partial class DateMath
4949
/// <exception cref="ArgumentException">Thrown when the expression is invalid or cannot be parsed</exception>
5050
public static DateTimeOffset Parse(string expression, DateTimeOffset relativeBaseTime, bool isUpperLimit = false)
5151
{
52+
ArgumentException.ThrowIfNullOrEmpty(expression);
53+
5254
if (!TryParse(expression, relativeBaseTime, isUpperLimit, out DateTimeOffset result))
5355
throw new ArgumentException($"Invalid date math expression: {expression}", nameof(expression));
5456

@@ -63,7 +65,7 @@ public static DateTimeOffset Parse(string expression, DateTimeOffset relativeBas
6365
/// <param name="isUpperLimit">Whether this is for an upper limit (affects rounding behavior)</param>
6466
/// <param name="result">The parsed DateTimeOffset if successful</param>
6567
/// <returns>True if parsing succeeded, false otherwise</returns>
66-
public static bool TryParse(string expression, DateTimeOffset relativeBaseTime, bool isUpperLimit, out DateTimeOffset result)
68+
public static bool TryParse(string? expression, DateTimeOffset relativeBaseTime, bool isUpperLimit, out DateTimeOffset result)
6769
{
6870
result = default;
6971

@@ -90,6 +92,7 @@ public static bool TryParse(string expression, DateTimeOffset relativeBaseTime,
9092
/// <exception cref="ArgumentNullException">Thrown when timeZone is null</exception>
9193
public static DateTimeOffset Parse(string expression, TimeZoneInfo timeZone, bool isUpperLimit = false)
9294
{
95+
ArgumentException.ThrowIfNullOrEmpty(expression);
9396
ArgumentNullException.ThrowIfNull(timeZone);
9497

9598
if (!TryParse(expression, timeZone, isUpperLimit, out DateTimeOffset result))
@@ -107,7 +110,7 @@ public static DateTimeOffset Parse(string expression, TimeZoneInfo timeZone, boo
107110
/// <param name="result">The parsed DateTimeOffset if successful</param>
108111
/// <returns>True if parsing succeeded, false otherwise</returns>
109112
/// <exception cref="ArgumentNullException">Thrown when timeZone is null</exception>
110-
public static bool TryParse(string expression, TimeZoneInfo timeZone, bool isUpperLimit, out DateTimeOffset result)
113+
public static bool TryParse(string? expression, TimeZoneInfo timeZone, bool isUpperLimit, out DateTimeOffset result)
111114
{
112115
ArgumentNullException.ThrowIfNull(timeZone);
113116

@@ -216,7 +219,7 @@ public static bool TryParseFromMatch(Match match, TimeZoneInfo timeZone, bool is
216219
/// </summary>
217220
/// <param name="expression">The expression to validate</param>
218221
/// <returns>True if the expression is valid date math, false otherwise</returns>
219-
public static bool IsValidExpression(string expression)
222+
public static bool IsValidExpression(string? expression)
220223
{
221224
if (String.IsNullOrEmpty(expression))
222225
return false;

src/Exceptionless.DateTimeExtensions/DateTimeRange.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public static IReadOnlyList<IPartParser> PartParsers
123123
/// Parses the date range from the passed in content.
124124
/// </summary>
125125
/// <param name="content">String date range</param>
126-
public static DateTimeRange Parse(string content)
126+
public static DateTimeRange Parse(string? content)
127127
{
128128
return Parse(content, DateTimeOffset.Now);
129129
}
@@ -133,7 +133,7 @@ public static DateTimeRange Parse(string content)
133133
/// </summary>
134134
/// <param name="content">String date range</param>
135135
/// <param name="relativeBaseTime">Relative dates will be base on this time.</param>
136-
public static DateTimeRange Parse(string content, DateTimeOffset relativeBaseTime)
136+
public static DateTimeRange Parse(string? content, DateTimeOffset relativeBaseTime)
137137
{
138138
if (String.IsNullOrEmpty(content))
139139
return Empty;

src/Exceptionless.DateTimeExtensions/TimeUnit.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ public static class TimeUnit
44
{
55
public static TimeSpan Parse(string value)
66
{
7-
if (String.IsNullOrEmpty(value))
8-
throw new ArgumentNullException(nameof(value));
7+
ArgumentException.ThrowIfNullOrEmpty(value);
98

109
var time = ParseTime(value);
1110
if (time.HasValue)
@@ -14,7 +13,7 @@ public static TimeSpan Parse(string value)
1413
throw new ArgumentException($"Unable to parse value '{value}' as a valid time value.");
1514
}
1615

17-
public static bool TryParse(string value, out TimeSpan? time)
16+
public static bool TryParse(string? value, out TimeSpan? time)
1817
{
1918
time = null;
2019
if (String.IsNullOrEmpty(value))

tests/Exceptionless.DateTimeExtensions.Tests/DateMathTests.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ public void Parse_ExplicitDateWithOperations_ReturnsCorrectResult(string express
305305
}
306306

307307
[Theory]
308-
[InlineData("")]
309308
[InlineData(" ")]
310309
[InlineData("invalid")]
311310
[InlineData("now+1x")] // Invalid unit
@@ -332,13 +331,19 @@ public void Parse_InvalidExpressions_ThrowsArgumentException(string expression)
332331
}
333332

334333
[Fact]
335-
public void Parse_NullExpression_ThrowsArgumentException()
334+
public void Parse_NullExpression_ThrowsArgumentNullException()
336335
{
337-
_logger.LogDebug("Testing Parse with null expression, expecting ArgumentException");
336+
_logger.LogDebug("Testing Parse with null expression, expecting ArgumentNullException");
338337

339-
var exception = Assert.Throws<ArgumentException>(() => DateMath.Parse(null!, _baseTime));
338+
Assert.Throws<ArgumentNullException>(() => DateMath.Parse(null!, _baseTime));
339+
}
340340

341-
_logger.LogDebug("Exception thrown as expected: {Message}", exception.Message);
341+
[Fact]
342+
public void Parse_EmptyExpression_ThrowsArgumentException()
343+
{
344+
_logger.LogDebug("Testing Parse with empty expression, expecting ArgumentException");
345+
346+
Assert.Throws<ArgumentException>(() => DateMath.Parse("", _baseTime));
342347
}
343348

344349
[Theory]

0 commit comments

Comments
 (0)