Skip to content

Commit a5b72bc

Browse files
committed
feat(filter): Added ability to only filter by date, instead of datetime
1 parent e8691df commit a5b72bc

File tree

7 files changed

+45
-7
lines changed

7 files changed

+45
-7
lines changed

src/GoatQuery/src/Ast/StringLiteral.cs renamed to src/GoatQuery/src/Ast/Literals.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,14 @@ public DateTimeLiteral(Token token, DateTime value) : base(token)
6868
{
6969
Value = value;
7070
}
71+
}
72+
73+
public sealed class DateLiteral : QueryExpression
74+
{
75+
public DateTime Value { get; set; }
76+
77+
public DateLiteral(Token token, DateTime value) : base(token)
78+
{
79+
Value = value.Date;
80+
}
7181
}

src/GoatQuery/src/Evaluator/FilterEvaluator.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ public static Result<Expression> Evaluate(QueryExpression expression, ParameterE
5151
case DateTimeLiteral literal:
5252
value = Expression.Constant(literal.Value, property.Type);
5353
break;
54+
case DateLiteral literal:
55+
property = Expression.Property(property, "Date");
56+
57+
value = Expression.Constant(literal.Value.Date, property.Type);
58+
break;
5459
default:
5560
return Result.Fail($"Unsupported literal type: {exp.Right.GetType().Name}");
5661
}

src/GoatQuery/src/Lexer/Lexer.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ public Token NextToken()
6464

6565
if (IsDigit(token.Literal[0]))
6666
{
67+
if (IsDate(token.Literal))
68+
{
69+
token.Type = TokenType.DATE;
70+
return token;
71+
}
72+
6773
if (IsDateTime(token.Literal))
6874
{
6975
token.Type = TokenType.DATETIME;
@@ -103,6 +109,11 @@ public Token NextToken()
103109
return token;
104110
}
105111

112+
private bool IsDate(string value)
113+
{
114+
return DateTime.TryParseExact(value, new[] { "yyyy-MM-dd" }, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out _);
115+
}
116+
106117
private bool IsDateTime(string value)
107118
{
108119
return DateTime.TryParse(value, out _);

src/GoatQuery/src/Parser/Parser.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ private Result<InfixExpression> ParseFilterStatement()
140140

141141
var statement = new InfixExpression(_currentToken, identifier, _currentToken.Literal);
142142

143-
if (!PeekTokenIn(TokenType.STRING, TokenType.INT, TokenType.GUID, TokenType.DATETIME, TokenType.DECIMAL, TokenType.FLOAT, TokenType.DOUBLE))
143+
if (!PeekTokenIn(TokenType.STRING, TokenType.INT, TokenType.GUID, TokenType.DATETIME, TokenType.DECIMAL, TokenType.FLOAT, TokenType.DOUBLE, TokenType.DATE))
144144
{
145145
return Result.Fail("Invalid value type within filter");
146146
}
@@ -152,7 +152,7 @@ private Result<InfixExpression> ParseFilterStatement()
152152
return Result.Fail("Value must be a string when using 'contains' operand");
153153
}
154154

155-
if (statement.Operator.In(Keywords.Lt, Keywords.Lte, Keywords.Gt, Keywords.Gte) && !CurrentTokenIn(TokenType.INT, TokenType.DECIMAL, TokenType.FLOAT, TokenType.DOUBLE, TokenType.DATETIME))
155+
if (statement.Operator.In(Keywords.Lt, Keywords.Lte, Keywords.Gt, Keywords.Gte) && !CurrentTokenIn(TokenType.INT, TokenType.DECIMAL, TokenType.FLOAT, TokenType.DOUBLE, TokenType.DATETIME, TokenType.DATE))
156156
{
157157
return Result.Fail($"Value must be an integer when using '{statement.Operator}' operand");
158158
}
@@ -204,6 +204,12 @@ private Result<InfixExpression> ParseFilterStatement()
204204
statement.Right = new DateTimeLiteral(_currentToken, dateTimeValue);
205205
}
206206
break;
207+
case TokenType.DATE:
208+
if (DateTime.TryParse(_currentToken.Literal, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out var dateValue))
209+
{
210+
statement.Right = new DateLiteral(_currentToken, dateValue);
211+
}
212+
break;
207213
}
208214

209215
return statement;

src/GoatQuery/src/Token/Token.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public enum TokenType
1010
DOUBLE,
1111
GUID,
1212
DATETIME,
13+
DATE,
1314
LPAREN,
1415
RPAREN,
1516
}

src/GoatQuery/tests/Filter/FilterLexerTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ public static IEnumerable<object[]> Parameters()
331331
{
332332
new (TokenType.IDENT, "dateOfBirth"),
333333
new (TokenType.IDENT, "eq"),
334-
new (TokenType.DATETIME, "2000-01-01"),
334+
new (TokenType.DATE, "2000-01-01"),
335335
}
336336
};
337337

@@ -342,7 +342,7 @@ public static IEnumerable<object[]> Parameters()
342342
{
343343
new (TokenType.IDENT, "dateOfBirth"),
344344
new (TokenType.IDENT, "lt"),
345-
new (TokenType.DATETIME, "2000-01-01"),
345+
new (TokenType.DATE, "2000-01-01"),
346346
}
347347
};
348348

@@ -353,7 +353,7 @@ public static IEnumerable<object[]> Parameters()
353353
{
354354
new (TokenType.IDENT, "dateOfBirth"),
355355
new (TokenType.IDENT, "lte"),
356-
new (TokenType.DATETIME, "2000-01-01"),
356+
new (TokenType.DATE, "2000-01-01"),
357357
}
358358
};
359359

@@ -364,7 +364,7 @@ public static IEnumerable<object[]> Parameters()
364364
{
365365
new (TokenType.IDENT, "dateOfBirth"),
366366
new (TokenType.IDENT, "gt"),
367-
new (TokenType.DATETIME, "2000-01-01"),
367+
new (TokenType.DATE, "2000-01-01"),
368368
}
369369
};
370370

@@ -375,7 +375,7 @@ public static IEnumerable<object[]> Parameters()
375375
{
376376
new (TokenType.IDENT, "dateOfBirth"),
377377
new (TokenType.IDENT, "gte"),
378-
new (TokenType.DATETIME, "2000-01-01"),
378+
new (TokenType.DATE, "2000-01-01"),
379379
}
380380
};
381381

src/GoatQuery/tests/Filter/FilterTest.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ public static IEnumerable<object[]> Parameters()
174174
new[] { _users["Egg"] }
175175
};
176176

177+
yield return new object[] {
178+
"dateOfBirth eq 2020-05-09",
179+
new[] { _users["Jane"] }
180+
};
181+
177182
yield return new object[] {
178183
"dateOfBirth lt 2010-01-01",
179184
new[] { _users["John"], _users["Apple"], _users["Harry"], _users["Egg"] }

0 commit comments

Comments
 (0)