diff --git a/QueryKit.IntegrationTests/Tests/FilterParsingRegressionTests.cs b/QueryKit.IntegrationTests/Tests/FilterParsingRegressionTests.cs index 211c198..a87ce98 100644 --- a/QueryKit.IntegrationTests/Tests/FilterParsingRegressionTests.cs +++ b/QueryKit.IntegrationTests/Tests/FilterParsingRegressionTests.cs @@ -145,7 +145,6 @@ public async Task date_time_offset_value_with_offset_matches_same_instant(string [Theory] [InlineData("SpecificDateTime == 2024-01-15T08:00:00.500Z", true)] - [InlineData("SpecificDateTime == 2024-01-15T08:00:00Z.5", true)] [InlineData("SpecificDate == 2024-01-15T10:00:00.5+02:00", true)] [InlineData("Time == 08:30:00.5", true)] [InlineData("Time == \"08:30:00.500\"", true)] diff --git a/QueryKit.UnitTests/FilterParsingRegressionTests.cs b/QueryKit.UnitTests/FilterParsingRegressionTests.cs index 74a38a0..3892da6 100644 --- a/QueryKit.UnitTests/FilterParsingRegressionTests.cs +++ b/QueryKit.UnitTests/FilterParsingRegressionTests.cs @@ -150,8 +150,6 @@ public void enum_list_value_is_split_into_items() [InlineData("SpecificDateTime ^^ [2024-01-15T08:00:00.5Z]")] [InlineData("SpecificDate == 2024-01-15T10:00:00.5+02:00")] [InlineData("SpecificDate == 2024-01-15T08:00:00.5000000Z")] - [InlineData("SpecificDateTime == 2024-01-15T08:00:00Z.5")] - [InlineData("SpecificDate == 2024-01-15T10:00:00+02:00.500")] [InlineData("Time == 08:30:00.5")] [InlineData("Time == \"08:30:00.500\"")] [InlineData("Time == \"08:30:00.5\"")] @@ -164,6 +162,16 @@ public void fractional_seconds_are_kept(string input) result.Select(x => x.Title).Should().Equal("match"); } + [Theory] + [InlineData("SpecificDateTime == 2024-01-15T08:00:00Z.5")] + [InlineData("SpecificDate == 2024-01-15T10:00:00+02:00.500")] + public void zone_before_the_fraction_throws(string input) + { + var act = () => FilterParser.ParseFilter(input); + + act.Should().Throw(); + } + private static TestingPerson[] FractionalSecondPeople() => new[] { new TestingPerson diff --git a/QueryKit/FilterParser.cs b/QueryKit/FilterParser.cs index 551d5ff..1b5daad 100644 --- a/QueryKit/FilterParser.cs +++ b/QueryKit/FilterParser.cs @@ -297,14 +297,12 @@ private static readonly Parser DoubleQuoteParser private static readonly Parser DateTimeTimeParser = Parse.Regex(@"T\d{2}:\d{2}:\d{2}").Text().Optional().Select(x => x.GetOrElse("")); private static readonly Parser DateTimeMicrosParser = Parse.Regex(@"\.\d{1,7}").Text().Optional().Select(x => x.GetOrElse("")); private static readonly Parser DateTimeZoneParser = Parse.Regex(@"Z|[+-]\d{2}(:\d{2})?").Text().Optional().Select(x => x.GetOrElse("")); - // v1.14.2 read the zone before the fraction, so 2022-07-01T00:00:02Z.5 is a valid value. A zone after the fraction is also valid. private static readonly Parser DateTimeFormatParser = from dateFormat in Parse.Regex(@"\d{4}-\d{2}-\d{2}").Text() from timeFormat in DateTimeTimeParser - from zoneBeforeMicros in DateTimeZoneParser from micros in DateTimeMicrosParser - from zoneAfterMicros in zoneBeforeMicros == "" ? DateTimeZoneParser : Parse.Return("") - select dateFormat + timeFormat + micros + zoneBeforeMicros + zoneAfterMicros; + from timeZone in DateTimeZoneParser + select dateFormat + timeFormat + micros + timeZone; // A number always uses the '.' decimal point, so a filter has the same meaning in every culture. private static readonly Parser NumberParser = diff --git a/README.md b/README.md index 7299a7f..8edcf02 100644 --- a/README.md +++ b/README.md @@ -262,6 +262,7 @@ Property list grouping is particularly useful for: * `var filterInput = """Time == "12:30:00" """;` * `var filterInput = """Time == "12:30:00.678722" """;` * A time fraction keeps every digit. For example, `"12:30:00.5"` is 12:30:00 and 500 milliseconds. + * In a date and time value, write the zone after the fraction: `2022-07-01T00:00:03.5Z`. An unquoted value with the zone before the fraction (`2022-07-01T00:00:03Z.5`) throws a `ParsingException`. * `bool` properties need to use `== true`, `== false`, or the same using the `!=` operator. they can not be standalone properies: