-
-
Notifications
You must be signed in to change notification settings - Fork 24
[Breaking] Enforce case-sensitive date math parsing per Elasticsearch spec #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -23,10 +23,14 @@ public static class DateMath | |||||
| // Match date math expressions with positional and end anchors for flexible matching | ||||||
| // Uses \G for positional matching and lookahead for boundary detection to support both | ||||||
| // full string parsing and positional matching within TwoPartFormatParser | ||||||
| // NOTE: Case-sensitive matching is intentional per Elasticsearch spec. The anchor 'now' must | ||||||
| // be lowercase, and date-math units are case-sensitive: y, M, w, d, h, H, m, s. | ||||||
| // Uppercase D is NOT a valid unit. See: | ||||||
| // https://www.elastic.co/docs/reference/elasticsearch/rest-apis/common-options | ||||||
| internal static readonly Regex Parser = new( | ||||||
| @"\G(?<anchor>now|(?<date>\d{4}-?\d{2}-?\d{2}(?:[T\s](?:\d{1,2}(?::?\d{2}(?::?\d{2})?)?(?:\.\d{1,3})?)?(?:[+-]\d{2}:?\d{2}|Z)?)?)\|\|)" + | ||||||
| @"(?<operations>(?:[+\-/]\d*[yMwdhHms])*)(?=\s|$|[\]\}])", | ||||||
| RegexOptions.Compiled | RegexOptions.IgnoreCase); | ||||||
| RegexOptions.Compiled); | ||||||
|
|
||||||
| // Pre-compiled regex for operation parsing to avoid repeated compilation | ||||||
| private static readonly Regex _operationRegex = new(@"([+\-/])(\d*)([yMwdhHms])", RegexOptions.Compiled); | ||||||
|
|
@@ -141,7 +145,7 @@ public static bool TryParseFromMatch(Match match, DateTimeOffset relativeBaseTim | |||||
| DateTimeOffset baseTime; | ||||||
| string anchor = match.Groups["anchor"].Value; | ||||||
|
|
||||||
| if (anchor.Equals("now", StringComparison.OrdinalIgnoreCase)) | ||||||
| if (String.Equals(anchor, "now")) | ||||||
| { | ||||||
| baseTime = relativeBaseTime; | ||||||
| } | ||||||
|
|
@@ -183,7 +187,7 @@ public static bool TryParseFromMatch(Match match, TimeZoneInfo timeZone, bool is | |||||
| DateTimeOffset baseTime; | ||||||
| string anchor = match.Groups["anchor"].Value; | ||||||
|
|
||||||
| if (anchor.Equals("now", StringComparison.OrdinalIgnoreCase)) | ||||||
| if (String.Equals(anchor, "now")) | ||||||
| { | ||||||
| // Use current time in the specified timezone | ||||||
| baseTime = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, timeZone); | ||||||
|
|
@@ -463,7 +467,7 @@ public static DateTimeOffset ApplyOperations(DateTimeOffset baseTime, string ope | |||||
| for (int i = 0; i < matches.Count; i++) | ||||||
| { | ||||||
| string operation = matches[i].Groups[1].Value; | ||||||
| if (operation == "/") | ||||||
| if (String.Equals(operation, "/")) | ||||||
|
||||||
| if (String.Equals(operation, "/")) | |
| if (String.Equals(operation, "/", StringComparison.Ordinal)) |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -102,7 +102,7 @@ private static bool IsValidBracketPair(string opening, string closing) | |||||||||
| return false; | ||||||||||
|
|
||||||||||
| // Check for proper matching pairs | ||||||||||
| return (opening == "[" && closing == "]") || | ||||||||||
| (opening == "{" && closing == "}"); | ||||||||||
| return (String.Equals(opening, "[") && String.Equals(closing, "]")) || | ||||||||||
| (String.Equals(opening, "{") && String.Equals(closing, "}")); | ||||||||||
|
Comment on lines
+105
to
+106
|
||||||||||
| return (String.Equals(opening, "[") && String.Equals(closing, "]")) || | |
| (String.Equals(opening, "{") && String.Equals(closing, "}")); | |
| return (String.Equals(opening, "[", StringComparison.Ordinal) && String.Equals(closing, "]", StringComparison.Ordinal)) || | |
| (String.Equals(opening, "{", StringComparison.Ordinal) && String.Equals(closing, "}", StringComparison.Ordinal)); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||
| using System; | ||||||
| using System; | ||||||
| using System.Text; | ||||||
|
|
||||||
| namespace Exceptionless.DateTimeExtensions; | ||||||
|
|
@@ -205,7 +205,7 @@ private static bool AppendPart(StringBuilder builder, string partName, double pa | |||||
|
|
||||||
| string partValueString = partCount > 0 ? Math.Abs(partValue).ToString("0.##") : partValue.ToString("0.##"); | ||||||
|
|
||||||
| if (shortForm && partName == "millisecond") | ||||||
| if (shortForm && String.Equals(partName, "millisecond")) | ||||||
|
||||||
| if (shortForm && String.Equals(partName, "millisecond")) | |
| if (shortForm && String.Equals(partName, "millisecond", StringComparison.Ordinal)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This String.Equals call omits a StringComparison. Using String.Equals(anchor, "now", StringComparison.Ordinal) keeps the case-sensitive intent explicit and avoids potential analyzer warnings.