首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从客户端向mongo db c#驱动程序和过滤器传递UTC数据?

如何从客户端向mongo db c#驱动程序和过滤器传递UTC数据?
EN

Stack Overflow用户
提问于 2018-10-16 22:01:11
回答 2查看 1.4K关注 0票数 1

有没有什么办法可以阻止mongodb c#驱动程序将过滤器查询中传递的任何日期转换为UTC,而不是接受UTC?

我正在使用带有一些telerik控件的.net核心2.1来显示网格。在网格的标题中,我有一个过滤器控件来过滤日期范围。

在过滤之前,在客户端事件中,我捕获日期并将其转换为utc:

代码语言:javascript
复制
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微服务,可以具有不同的时区,具体取决于它的部署位置):

代码语言:javascript
复制
// 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对象)和mongodb c#驱动程序(linq to mongo),我创建了一个mongo查询来过滤mongo数据库中的记录。

代码语言:javascript
复制
 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#驱动程序端的替代方案。我希望mongodb查询将所有日期读取为UTC,而不是将检索到的日期转换为UTC。

我知道有一种方法可以告诉属性它正通过BsonDateTimeOptions DateTimeKind保存为utc:

代码语言:javascript
复制
[BsonElement(elementName: "created")]
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime Created { get; set; }

对于查询也有类似的东西吗?

更新:解决方案是指定被过滤日期的DateTimeKind。

代码语言:javascript
复制
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;
            }
        }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-17 03:37:13

您可以尝试对日期使用DateTime.SpecifyKind,如下所示:

代码语言:javascript
复制
query = (from c in casesCollection.AsQueryable()
...
select new CaseListViewModel()
{
    ...
    Created = DateTime.SpecifyKind(c.Created, DateTimeKind.Utc)
}

在这种情况下,mongodb驱动程序应该将日期解释为utc格式,因此它不会执行转换。

票数 2
EN

Stack Overflow用户

发布于 2018-10-17 00:26:37

我不完全确定你在问什么,但我在你的代码中看到了一些东西:

  • 在您的客户端代码中,您拥有:

var isoDate =新日期(date.getUTCFullYear(),date.getUTCMonth(),date.getUTCDate(),date.getUTCHours(),date.getUTCMinutes(),date.getUTCSeconds());

这是一种常见的反模式,您永远不应该这样做。Date对象的参数需要以本地时间表示的值,而您要传递的值采用协调世界时的格式。这样做基本上与添加本地时区的UTC偏移量相同。换句话说,它不会将对象转换为不同的时区,它只是在时间上选取不同的时刻。

您可能想要做的是date.toISOString()。这将发出适合发送到服务器的ISO8601格式的基于UTC的字符串。

  • 在您的服务器端代码中,您拥有:

f.Value = dt.ToLocalTime();

这将转换为服务器的本地时区。在绝大多数情况下,您应该避免编写依赖于服务器时区设置的代码。取而代之的是,以UTC为单位保留输入时间。使用UTC存储,使用UTC查询,并返回基于UTC的响应。在接收响应的客户端代码中,使用Date对象或库将其转换回本地时间。

此外,在你的GetCollectionQuery中,我根本看不到任何与日期或时间相关的东西,所以我不确定这与你的问题有什么关系。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52837291

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档