AspNetCoreOData
AspNetCoreOData copied to clipboard
DateTime not being parsed correctly for functions.
Version: Microsoft.AspNetCore.OData v8.0.10
Description: DateTime not being parsed correctly for functions.
Steps to Reproduce Add a function with DateTime parameters. Example:
var getAvailabilityFunction = builder.EntityType<TourPackage>().Collection.Function("GetAvailability");
getAvailabilityFunction.Parameter<Guid>("tourPackageId");
getAvailabilityFunction.Parameter<string>("hotelName");
getAvailabilityFunction.Parameter<DateTime>("dateFrom");
getAvailabilityFunction.Parameter<DateTime>("dateTo");
getAvailabilityFunction.ReturnsCollection<TourPackageAvailable>();
Implement it:
public async Task<IActionResult> GetAvailability(
ODataQueryOptions<TourPackageAvailable> options,
[FromODataUri] Guid tourPackageId,
[FromODataUri] string hotelName,
[FromODataUri] DateTime dateFrom,
[FromODataUri] DateTime dateTo)
{
// etc
Try to use it:
/odata/TourPackageApi/Default.GetAvailability(tourPackageId=4cc24078-a1ad-4ec5-abfc-29b8ef535f41,hotelName='Brim%20Hotel%20Tbilisi%204*',dateFrom=2022-05-08,dateTo=2022-05-09)
Result:
Notice the month and day are the wrong way around.
Try with adding time as well (just in case):
/odata/TourPackageApi/Default.GetAvailability(tourPackageId=4cc24078-a1ad-4ec5-abfc-29b8ef535f41,hotelName='Brim%20Hotel%20Tbilisi%204*',dateFrom=2022-05-08T00:00:00Z,dateTo=2022-05-09T00:00:00Z)
Same result.
- Can you enable route debug:
app.UseODataRouteDebug();
and send the '$odata' to get a routing table as follows:
- It's weird, at my debug,
If i config the OData without the time zone settings as:
builder.Services.AddControllers()
.AddOData(opt => opt.AddRouteComponents("odata", EdmModelBuilder.BuildEdmModel()));
My debug shows as follows for
/odata/TourPackageApi/Default.GetAvailability(tourPackageId=4cc24078-a1ad-4ec5-abfc-29b8ef535f41,hotelName='Brim%20Hotel%20Tbilisi%204*',dateFrom=2022-05-08,dateTo=2022-05-09)
- if I config the timezone settings as
builder.Services.AddControllers()
//.AddOData(opt => opt.AddRouteComponents("odata", EdmModelBuilder.BuildEdmModel()));
.AddOData(opt => opt.AddRouteComponents("odata", EdmModelBuilder.BuildEdmModel()).TimeZone = TimeZoneInfo.Utc);
I can get the following:
It looks the data time-binding works fine at our side.
Thanks, -Sam
@gordon-matt If you don't care about the time, only care about the date, you can use Date
getAvailabilityFunction.Parameter<Date>("dateFrom");
getAvailabilityFunction.Parameter<Date>("dateTo");
@xuzhg My route table is pretty large. Here is the portion for the GetAvailability
function:
MyCompany.TMS.Areas.Admin.Controllers.Api.TourPackageApiController.GetAvailability (MyCompany.TMS) GET odata/TourPackageApi/Default.GetAvailability(tourPackageId={tourPackageId},hotelName={hotelName},dateFrom={dateFrom},dateTo={dateTo})
MyCompany.TMS.Areas.Admin.Controllers.Api.TourPackageApiController.GetAvailability (MyCompany.TMS) GET odata/TourPackageApi/GetAvailability(tourPackageId={tourPackageId},hotelName={hotelName},dateFrom={dateFrom},dateTo={dateTo})
If I change to Microsoft.OData.Edm.Date
, as you've suggested, that does work.. But then it is inconvenient for use.. I first have to create DateTime
objects from those to use them in my queries:
var fromDate = new DateTime(dateFrom.Year, dateFrom.Month, dateFrom.Day).AsUtc();
var toDate = new DateTime(dateTo.Year, dateTo.Month, dateTo.Day).AsUtc();
var existingRecords = await tourPackageAvailableRepository.Value.FindAsync(x =>
x.TourPackageId == tourPackageId &&
x.HotelName == hotelName &&
x.Date >= fromDate &&
x.Date <= toDate);
// etc..
If that, I might as well just send a string and parse it myself.
It is an ok workaround, I guess.. but it would still be good to fix whatever is wrong with the DateTime
type. Not just for this one case, but also I might want to have time available in some other functions.. then what?
Please note that in my case, I do not change any time zone settings like you showed. Besides, I don't think it's a time zone problem.. it seems more like a date format problem.. like it's forcing the American MM/dd/yyyy
format and then display it as yyyy-MM-dd
after it parsed it with the incorrect format..
@gordon-matt You can easily convert between DateTime and Date type. It's implicit converting. And Date also supports logical comparison. Just for your information.
@xuzhg Thanks.. never used it before. In any case, I still think DateTime should be fixed so it gets parsed correctly.
@gordon-matt I tried this and got the same results as @xuzhg. I'm not sure the regional date and time settings have anything to do with the behaviour you're observing. Here's what I have locally. Maybe you could share what you have then we can try and repro.
Results
@gathogojr even if there is no problem with DateTime
, there appears to be an inconsistency between it and Date
as per this:
If I change to
Microsoft.OData.Edm.Date
, as you've suggested, that does work.
IMHO they should work consistently: if one uses a culture for formatting, the other should also use the same culture.
@gathogojr Here's my regional format settings:
@gordon-matt From your screenshot in the issue description, would you mind sharing the dateFrom
parameter expanded? Just to be sure which component is which in the date displayed as {5/7/2022 5:00:00 PM}
@gathogojr That is not my comment.. it is @xuzhg 's comment
argh! Meant from your issue description https://github.com/OData/AspNetCoreOData/issues/590#issue-1229027990 @gordon-matt
Here you go..