如何将 UTC 日期从客户端传递到 mongo db c# driver 并进行过滤?
How to pass UTC date from client to mongo db c# driver and filter?
有没有办法阻止 mongodb c# driver 将过滤器查询中传递的任何日期转换为 UTC,而是接受该日期作为 UTC?
我正在使用 .net core 2.1 和一些 telerik 控件来显示网格。在网格的 header 内部,我有一个过滤器控件来过滤日期范围。
在过滤之前的客户端事件中,我正在捕获日期并将其转换为 utc:
function onGridFilter(e) {
// check if it is a date field
if (e.filter && e.field === "created"){
convertDateToUTC(e.filter);
}
}
function convertDateToUTC(filter) {
var filters = filter.filters;
for (var i = 0; i < filters.length; i++) {
if (filters[i].field === "created") {
var date = filters[i].value;
var isoDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
filter.filters[i].value = isoDate;
}
}
}
在 API 调用中,我像这样将 UTC 日期转换为服务器的本地时间(这个 API 是一个 kubernetes 微服务,可以有不同的时区取决于它已部署):
// Update the dates to server times for filtering, mongo will accept dates and convert to UTC based on the server location
foreach (var f in this.Filters)
{
if (f.ConvertedValue.GetType() == typeof(DateTime))
{
DateTime dt = (DateTime)f.Value;
f.Value = dt.ToLocalTime();
}
}
使用 telerik 过滤器 (DataSourceRequest object) 和 mongodb c# driver (linq to mongo) 我正在创建一个 mongo 查询过滤 mongo 数据库中的记录。
public DataSourceResult GetCollectionQuery(string organizationId, DataSourceRequest request)
{
IMongoCollection<Case> casesCollection = _db.GetCollection<Case>(_collection);
IMongoCollection<Person> personCollection = _db.GetCollection<Person>(_personCollection);
IQueryable<CaseListViewModel> query;
// Setup full results query
query = (from c in casesCollection.AsQueryable()
where c.OrganizationId == organizationId
join p in personCollection.AsQueryable() on c.ClientId equals p.Id into p
from person in p.DefaultIfEmpty()
select new CaseListViewModel()
{
Id = c.Id,
DisplayName = person != null ? person.LastName + ", " + person.FirstName : string.Empty,
OrganizationCaseId = c.OrganizationCaseId,
ServiceName = c.ServiceName,
ClientType = c.ClientType,
Addresses = c.ClientTypeValue == ClientTypeValue.Person ? person.Addresses != null ?
person.Addresses.Where(o => !o.End.HasValue).Select(o => o.AddressLine1) : null : null,
Worker = string.Empty, //c.Assignments,
Created = c.Created,
Status = c.Status,
OrganizationGeography = person != null ? person.OrganizationGeography != null ? person.OrganizationGeography.Name : string.Empty : string.Empty
});
// Filter/Sort/Page results
return query.ToDataSourceResult(request);
}
我将客户端转换为 UTC,将 UTC 转换为服务器然后将该日期传递给 mongo 查询的原因是因为客户端和服务器可以位于不同的时区。
过滤网格上的日期似乎是很多不必要的工作。目前此解决方案确实有效,但我正在 mongodb c# driver 方面寻找替代方案。我希望 mongodb 查询以 UTC 格式读取所有日期,而不是将检索到的日期转换为 UTC。
我知道有一种方法可以告诉 属性 它正在使用 BsonDateTimeOptions DateTimeKind 保存为 utc:
[BsonElement(elementName: "created")]
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime Created { get; set; }
是否有类似的查询?
更新:
解决方案是指定要过滤的日期的 DateTimeKind。
foreach (var f in this.Filters)
{
if (f.ConvertedValue.GetType() == typeof(DateTime))
{
DateTime dt = (DateTime)f.Value;
dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
f.Value = dt;
}
}
我不完全确定你在问什么,但我在你的代码中看到了一些东西:
在您的客户端代码中,您有:
var isoDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
这是一种常见的反模式,永远不要这样做。 Date
对象的参数需要本地时间的值,而您正在传递 UTC 中的值。这样做基本上与添加本地时区的 UTC 偏移量相同。换句话说,它不会将对象转换到不同的时区,它只是及时选择不同的时刻。
您可能想要做的是 date.toISOString()
。这将发出适合发送到服务器的 ISO 8601 格式的基于 UTC 的字符串。
在您的服务器端代码中,您有:
f.Value = dt.ToLocalTime();
这将转换为 服务器的 本地时区。在绝大多数情况下,您应该避免编写依赖于服务器时区设置的代码。相反,将输入的时间保留为提供给您的 UTC 时间。使用 UTC 存储,使用 UTC 查询,以及 return 基于 UTC 的响应。在接收响应的客户端代码中,使用 Date
对象或库将时间转换回本地时间。
此外,在您的 GetCollectionQuery
中,我根本没有看到任何与日期或时间相关的内容,所以我不确定这与您的问题有什么关系。
您可以尝试使用 DateTime.SpecifyKind
作为约会日期:
query = (from c in casesCollection.AsQueryable()
...
select new CaseListViewModel()
{
...
Created = DateTime.SpecifyKind(c.Created, DateTimeKind.Utc)
}
在这种情况下 mongodb 驱动程序应该将日期解释为已经在 utc 中,因此它不会执行转换。
有没有办法阻止 mongodb c# driver 将过滤器查询中传递的任何日期转换为 UTC,而是接受该日期作为 UTC?
我正在使用 .net core 2.1 和一些 telerik 控件来显示网格。在网格的 header 内部,我有一个过滤器控件来过滤日期范围。
在过滤之前的客户端事件中,我正在捕获日期并将其转换为 utc:
function onGridFilter(e) {
// check if it is a date field
if (e.filter && e.field === "created"){
convertDateToUTC(e.filter);
}
}
function convertDateToUTC(filter) {
var filters = filter.filters;
for (var i = 0; i < filters.length; i++) {
if (filters[i].field === "created") {
var date = filters[i].value;
var isoDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
filter.filters[i].value = isoDate;
}
}
}
在 API 调用中,我像这样将 UTC 日期转换为服务器的本地时间(这个 API 是一个 kubernetes 微服务,可以有不同的时区取决于它已部署):
// Update the dates to server times for filtering, mongo will accept dates and convert to UTC based on the server location
foreach (var f in this.Filters)
{
if (f.ConvertedValue.GetType() == typeof(DateTime))
{
DateTime dt = (DateTime)f.Value;
f.Value = dt.ToLocalTime();
}
}
使用 telerik 过滤器 (DataSourceRequest object) 和 mongodb c# driver (linq to mongo) 我正在创建一个 mongo 查询过滤 mongo 数据库中的记录。
public DataSourceResult GetCollectionQuery(string organizationId, DataSourceRequest request)
{
IMongoCollection<Case> casesCollection = _db.GetCollection<Case>(_collection);
IMongoCollection<Person> personCollection = _db.GetCollection<Person>(_personCollection);
IQueryable<CaseListViewModel> query;
// Setup full results query
query = (from c in casesCollection.AsQueryable()
where c.OrganizationId == organizationId
join p in personCollection.AsQueryable() on c.ClientId equals p.Id into p
from person in p.DefaultIfEmpty()
select new CaseListViewModel()
{
Id = c.Id,
DisplayName = person != null ? person.LastName + ", " + person.FirstName : string.Empty,
OrganizationCaseId = c.OrganizationCaseId,
ServiceName = c.ServiceName,
ClientType = c.ClientType,
Addresses = c.ClientTypeValue == ClientTypeValue.Person ? person.Addresses != null ?
person.Addresses.Where(o => !o.End.HasValue).Select(o => o.AddressLine1) : null : null,
Worker = string.Empty, //c.Assignments,
Created = c.Created,
Status = c.Status,
OrganizationGeography = person != null ? person.OrganizationGeography != null ? person.OrganizationGeography.Name : string.Empty : string.Empty
});
// Filter/Sort/Page results
return query.ToDataSourceResult(request);
}
我将客户端转换为 UTC,将 UTC 转换为服务器然后将该日期传递给 mongo 查询的原因是因为客户端和服务器可以位于不同的时区。
过滤网格上的日期似乎是很多不必要的工作。目前此解决方案确实有效,但我正在 mongodb c# driver 方面寻找替代方案。我希望 mongodb 查询以 UTC 格式读取所有日期,而不是将检索到的日期转换为 UTC。
我知道有一种方法可以告诉 属性 它正在使用 BsonDateTimeOptions DateTimeKind 保存为 utc:
[BsonElement(elementName: "created")]
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime Created { get; set; }
是否有类似的查询?
更新: 解决方案是指定要过滤的日期的 DateTimeKind。
foreach (var f in this.Filters)
{
if (f.ConvertedValue.GetType() == typeof(DateTime))
{
DateTime dt = (DateTime)f.Value;
dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
f.Value = dt;
}
}
我不完全确定你在问什么,但我在你的代码中看到了一些东西:
在您的客户端代码中,您有:
var isoDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
这是一种常见的反模式,永远不要这样做。
Date
对象的参数需要本地时间的值,而您正在传递 UTC 中的值。这样做基本上与添加本地时区的 UTC 偏移量相同。换句话说,它不会将对象转换到不同的时区,它只是及时选择不同的时刻。您可能想要做的是
date.toISOString()
。这将发出适合发送到服务器的 ISO 8601 格式的基于 UTC 的字符串。在您的服务器端代码中,您有:
f.Value = dt.ToLocalTime();
这将转换为 服务器的 本地时区。在绝大多数情况下,您应该避免编写依赖于服务器时区设置的代码。相反,将输入的时间保留为提供给您的 UTC 时间。使用 UTC 存储,使用 UTC 查询,以及 return 基于 UTC 的响应。在接收响应的客户端代码中,使用
Date
对象或库将时间转换回本地时间。
此外,在您的 GetCollectionQuery
中,我根本没有看到任何与日期或时间相关的内容,所以我不确定这与您的问题有什么关系。
您可以尝试使用 DateTime.SpecifyKind
作为约会日期:
query = (from c in casesCollection.AsQueryable()
...
select new CaseListViewModel()
{
...
Created = DateTime.SpecifyKind(c.Created, DateTimeKind.Utc)
}
在这种情况下 mongodb 驱动程序应该将日期解释为已经在 utc 中,因此它不会执行转换。