odata datetimeoffset 过滤器因正时区而失败
odata datetimeoffset filter fails with positive timezone
我遇到了 odata 过滤问题。我已将我的场景简化为以下内容:
我的模型是这样构建的:
public class MyModel
{
public int ID { get; set; }
public DateTimeOffset DATE { get; set; }
}
控制器和 GET 实现如下:
public class MyModelController:ODataController
{
[HttpGet]
[EnableQuery]
public IHttpActionResult Get()
{
var list = new List<MyModel>();
list.Add(new MyModel{
ID = 1,
DATE = DateTimeOffset.Now.AddDays(-1)
});
list.Add(new MyModel {
ID = 2,
DATE = DateTimeOffset.Now.AddDays(-2)
});
list.Add(new MyModel {
ID = 3,
DATE = DateTimeOffset.Now.AddDays(-3)
});
return Ok(list.AsQueryable());
}
}
在 DATE 列上执行以下过滤器,结果不错。请注意时区是 negative:
GET https://localhost:44349/odata/MyModel?$filter=DATE le 2020-06-24T15:57:44.3780001-03:00
在 DATE 列上执行以下过滤器会引发 异常。请注意,本例中的时区是 positive.
GET https://localhost:44349/odata/MyModel?$filter=DATE le 2020-06-24T15:57:44.3780001+03:00
我是不是漏掉了什么?
{
"error": {
"code": "",
"message": "The query specified in the URI is not valid. The DateTimeOffset text '2020-06-24T15:57:44.3780001' should be in format 'yyyy-mm-ddThh:mm:ss('.'s+)?(zzzzzz)?' and each field value is within valid range.",
"innererror": {
"message": "The DateTimeOffset text '2020-06-24T15:57:44.3780001' should be in format 'yyyy-mm-ddThh:mm:ss('.'s+)?(zzzzzz)?' and each field value is within valid range.",
"type": "Microsoft.OData.ODataException",
"stacktrace": " at Microsoft.OData.UriUtils.ConvertUriStringToDateTimeOffset(String text, DateTimeOffset& targetValue)\r\n at Microsoft.OData.UriParser.ExpressionLexer.TryParseDateTimeoffset(Int32 tokenPos)\r\n at Microsoft.OData.UriParser.ExpressionLexer.ParseFromDigit()\r\n at Microsoft.OData.UriParser.ExpressionLexer.NextTokenImplementation(Exception& error)\r\n at Microsoft.OData.UriParser.ExpressionLexer.NextToken()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseComparison()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseLogicalAnd()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseLogicalOr()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseExpression()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseExpressionText(String expressionText)\r\n at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilterImplementation(String filter, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo)\r\n at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilter()\r\n at Microsoft.AspNet.OData.Query.FilterQueryOption.get_FilterClause()\r\n at Microsoft.AspNet.OData.Query.Validators.FilterQueryValidator.Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)\r\n at Microsoft.AspNet.OData.Query.FilterQueryOption.Validate(ODataValidationSettings validationSettings)\r\n at Microsoft.AspNet.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n at Microsoft.AspNet.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.<>c__DisplayClass0_0.<OnActionExecuted>b__1(ODataQueryContext queryContext)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.ExecuteQuery(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, Func`2 modelFunction, IWebApiRequestMessage request, Func`2 createQueryOptionFunction)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.OnActionExecuted(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, IWebApiRequestMessage request, Func`2 modelFunction, Func`2 createQueryOptionFunction, Action`1 createResponseAction, Action`3 createErrorAction)",
"internalexception": {
"message": "The time zone information is missing on the DateTimeOffset value '2020-06-24T15:57:44.3780001'. A DateTimeOffset value must contain the time zone information.",
"type": "System.FormatException",
"stacktrace": " at Microsoft.OData.PlatformHelper.ValidateTimeZoneInformationInDateTimeOffsetString(String text)\r\n at Microsoft.OData.PlatformHelper.ConvertStringToDateTimeOffset(String text)\r\n at Microsoft.OData.UriUtils.ConvertUriStringToDateTimeOffset(String text, DateTimeOffset& targetValue)"
}
}
}
}
同时我发现,+ 在 URL 中有特殊含义。您需要对其进行如下编码:
获取 https://localhost:44349/odata/MyModel?$filter=日期 2020-06-24T15:57:44.3780001%2b03:00
即+ => %2b
我遇到了 odata 过滤问题。我已将我的场景简化为以下内容: 我的模型是这样构建的:
public class MyModel
{
public int ID { get; set; }
public DateTimeOffset DATE { get; set; }
}
控制器和 GET 实现如下:
public class MyModelController:ODataController
{
[HttpGet]
[EnableQuery]
public IHttpActionResult Get()
{
var list = new List<MyModel>();
list.Add(new MyModel{
ID = 1,
DATE = DateTimeOffset.Now.AddDays(-1)
});
list.Add(new MyModel {
ID = 2,
DATE = DateTimeOffset.Now.AddDays(-2)
});
list.Add(new MyModel {
ID = 3,
DATE = DateTimeOffset.Now.AddDays(-3)
});
return Ok(list.AsQueryable());
}
}
在 DATE 列上执行以下过滤器,结果不错。请注意时区是 negative:
GET https://localhost:44349/odata/MyModel?$filter=DATE le 2020-06-24T15:57:44.3780001-03:00
在 DATE 列上执行以下过滤器会引发 异常。请注意,本例中的时区是 positive.
GET https://localhost:44349/odata/MyModel?$filter=DATE le 2020-06-24T15:57:44.3780001+03:00
我是不是漏掉了什么?
{
"error": {
"code": "",
"message": "The query specified in the URI is not valid. The DateTimeOffset text '2020-06-24T15:57:44.3780001' should be in format 'yyyy-mm-ddThh:mm:ss('.'s+)?(zzzzzz)?' and each field value is within valid range.",
"innererror": {
"message": "The DateTimeOffset text '2020-06-24T15:57:44.3780001' should be in format 'yyyy-mm-ddThh:mm:ss('.'s+)?(zzzzzz)?' and each field value is within valid range.",
"type": "Microsoft.OData.ODataException",
"stacktrace": " at Microsoft.OData.UriUtils.ConvertUriStringToDateTimeOffset(String text, DateTimeOffset& targetValue)\r\n at Microsoft.OData.UriParser.ExpressionLexer.TryParseDateTimeoffset(Int32 tokenPos)\r\n at Microsoft.OData.UriParser.ExpressionLexer.ParseFromDigit()\r\n at Microsoft.OData.UriParser.ExpressionLexer.NextTokenImplementation(Exception& error)\r\n at Microsoft.OData.UriParser.ExpressionLexer.NextToken()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseComparison()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseLogicalAnd()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseLogicalOr()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseExpression()\r\n at Microsoft.OData.UriParser.UriQueryExpressionParser.ParseExpressionText(String expressionText)\r\n at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilterImplementation(String filter, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo)\r\n at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilter()\r\n at Microsoft.AspNet.OData.Query.FilterQueryOption.get_FilterClause()\r\n at Microsoft.AspNet.OData.Query.Validators.FilterQueryValidator.Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)\r\n at Microsoft.AspNet.OData.Query.FilterQueryOption.Validate(ODataValidationSettings validationSettings)\r\n at Microsoft.AspNet.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n at Microsoft.AspNet.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.<>c__DisplayClass0_0.<OnActionExecuted>b__1(ODataQueryContext queryContext)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.ExecuteQuery(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, Func`2 modelFunction, IWebApiRequestMessage request, Func`2 createQueryOptionFunction)\r\n at Microsoft.AspNet.OData.EnableQueryAttribute.OnActionExecuted(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, IWebApiRequestMessage request, Func`2 modelFunction, Func`2 createQueryOptionFunction, Action`1 createResponseAction, Action`3 createErrorAction)",
"internalexception": {
"message": "The time zone information is missing on the DateTimeOffset value '2020-06-24T15:57:44.3780001'. A DateTimeOffset value must contain the time zone information.",
"type": "System.FormatException",
"stacktrace": " at Microsoft.OData.PlatformHelper.ValidateTimeZoneInformationInDateTimeOffsetString(String text)\r\n at Microsoft.OData.PlatformHelper.ConvertStringToDateTimeOffset(String text)\r\n at Microsoft.OData.UriUtils.ConvertUriStringToDateTimeOffset(String text, DateTimeOffset& targetValue)"
}
}
}
}
同时我发现,+ 在 URL 中有特殊含义。您需要对其进行如下编码:
获取 https://localhost:44349/odata/MyModel?$filter=日期 2020-06-24T15:57:44.3780001%2b03:00
即+ => %2b