Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions QueryKit.UnitTests/FilterParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ public void can_handle_datetime_comparison_with_timezone()
{
var input = """SpecificDate == 2022-07-01T00:00:03+01:00""";
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input);
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922304030000000, 01:00:00)))");
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922268030000000, 00:00:00)))");
}

[Theory]
Expand Down Expand Up @@ -308,7 +308,7 @@ public void can_handle_datetime_comparison_with_timezone_another()
{
var input = """SpecificDate == "2022-07-01T00:00:03+01:00" """;
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input);
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922304030000000, 01:00:00)))");
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922268030000000, 00:00:00)))");
}

[Fact]
Expand All @@ -324,15 +324,15 @@ public void can_handle_datetime_comparison_with_negative_timezone()
{
var input = """SpecificDate == 2022-07-01T00:00:03-02:00""";
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input);
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922304030000000, -02:00:00)))");
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922376030000000, 00:00:00)))");
}

[Fact]
public void can_handle_datetime_comparison_with_timezone_no_minutes()
{
var input = """SpecificDate == 2022-07-01T00:00:03+02""";
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input);
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922304030000000, 02:00:00)))");
filterExpression.ToDisplayString().Should().Be("x => (x.SpecificDate == new Nullable`1(new DateTimeOffset(637922232030000000, 00:00:00)))");
}

[Fact]
Expand Down
10 changes: 3 additions & 7 deletions QueryKit/FilterParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,6 @@ from trailingSpaces in Parse.WhiteSpace.Many()
select LogicalOperator.GetByOperatorString(match.Operator)));
}

// Npgsql only accepts a DateTimeOffset parameter with offset 0, so a parameter gets the same instant in UTC.
// A literal keeps its offset, like v1.14.2.
private static DateTimeOffset ToParameterOffset(DateTimeOffset value)
=> FilterValue.Parameterize ? value.ToUniversalTime() : value;

private static readonly Dictionary<Type, Func<string, object>> TypeConversionFunctions = new()
{
{ typeof(string), value => value },
Expand All @@ -432,7 +427,7 @@ private static DateTimeOffset ToParameterOffset(DateTimeOffset value)
{ typeof(short), value => short.Parse(value, CultureInfo.InvariantCulture) },
{ typeof(byte), value => byte.Parse(value, CultureInfo.InvariantCulture) },
{ typeof(DateTime), value => DateTime.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal) },
{ typeof(DateTimeOffset), value => ToParameterOffset(DateTimeOffset.Parse(value)) },
{ typeof(DateTimeOffset), value => DateTimeOffset.Parse(value).ToUniversalTime() },
{ typeof(DateOnly), value => DateOnly.Parse(value) },
{ typeof(TimeOnly), value => TimeOnly.Parse(value) },
{ typeof(TimeSpan), value => TimeSpan.Parse(value) },
Expand Down Expand Up @@ -635,7 +630,8 @@ private static Expression CreateRightExprFromType(Type leftExprType, string righ
{
var dtStyle = right.EndsWith("Z") ? DateTimeStyles.AdjustToUniversal : DateTimeStyles.AssumeLocal;
var dto = DateTimeOffset.Parse(right, CultureInfo.InvariantCulture, dtStyle);
return FilterValue.Create(ToParameterOffset(dto), rawType);
// Npgsql only accepts a DateTimeOffset parameter with offset 0. The UTC value is the same instant.
return FilterValue.Create(dto.ToUniversalTime(), rawType);
}

if (targetType == typeof(DateOnly))
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ Property list grouping is particularly useful for:
* `DateOnly`: `var filterInput = """Birthday == "2022-07-01" """;`
* `DateTimeOffset`:
* `var filterInput = """Birthday == "2022-07-01T00:00:03Z" """;`
* QueryKit converts a `DateTimeOffset` value to UTC. `"2022-07-01T00:00:03+01:00"` becomes the same instant with offset 0: `2022-06-30T23:00:03Z`.
* `DateTime`: `var filterInput = """Birthday == "2022-07-01" """;`
* `var filterInput = """Birthday == "2022-07-01T00:00:03" """;`
* `var filterInput = """Birthday == "2022-07-01T00:00:03+01:00" """;`
Expand Down
Loading