CosmosDB - UTC 查询的 DateTimeOffset 问题
CosmosDB - DateTimeOffset Issue with UTC Querying
在 CosmosDb 中使用 DateTimeOffset 时存在问题。参考在 microsoft docs 上与他们合作的指南,它指出...
To convert a local DateTime to UTC, the offset must be known/stored as a property in the JSON and the client can use the offset to compute the UTC DateTime value.
所以我将我的日期以 "2021-04-23T12:15:00+01:00" 的格式存储在我的文档中。这在为本地用户查询和显示时效果很好。但是,我在对这些 DateTimes 执行查询时遇到问题...
在我的服务器上,我将执行这样的查询...
Linq 查询
.Where(x => x.ExpiresAt.UtcDateTime <= DateTime.UtcNow)
如果 expiresAt = "2021-04-23T12:15:00+01:00"
现在的 UTC 时间 = "2021-04-23T11:15:00+00:00"
然后我希望查询 return 一个项目。但是,直到一个小时后才 return 编辑任何项目,几乎就像 .UtcDateTime 扩展名不起作用一样。如果是这样,那么你如何比较这样的 DateTimeOffsets 呢?微软文档听起来好像您需要另一个字段来存储偏移量并且不能将其与日期时间本身内联使用。喜欢...
{
"expiresAt":"2021-04-23T11:15:00",
"expiresAtOffset":"1"
}
肯定是我误会了吧?
注意: 我试过使用 SQL 查询而不是像这样的 linq...
"SELECT * FROM c WHERE c.expiresAt <= \"2021-04-23T11:58:05\""
但仍然是同样的问题,因为问题是 cosmos 值是需要转换和查看的值 docs 无法将 cosmos 值转换为 UTC 时间...
另一个 建议用 Z 缩写存储它。
我试过了,它似乎大致按照我想要的方式工作,但并不完美。所有日期现在都存储为附加了 Z 的 DateTime 值。然后使用 DateTimeOffset DTO,它将在客户端适当地转换值。
不得不改变它的序列化设置,就像这样...
var jsonSerializerSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffZ"
};
然后我在创建 DocumentClient 时添加了...
new DocumentClient(serviceEndpoint, authKey, serializerSettings: jsonSerializerSettings);
我唯一的问题是我有一些电子邮件需要从服务器发送,其中包含时间。这些时间不正确,因为服务器不知道如何将它们转换为客户端本地时间。
根据我的经验,这种组合可以通过 .NET 上的 Cosmos 和日期时间实现快乐:
- 将日期和时间建模为 docs
中建议的 ISO 8601 值
- 使用
DateTime
.NET 类型,而不是 DateTimeOffset
- 确保完整的日期时间以准确的格式序列化
yyyy-MM-ddTHH:mm:ss.fffffffZ
- 始终存储 UTC 值,从不存储本地时间
- 如果值表示特定时区发生的事情,请将 IANA time zone 与值一起存储。然后在显示给用户之前使用它进行转换。
- 使用 .NET SDK 3 中基于流的方法 (sample) 和
System.Text.Json
直接控制序列化,并获得按预期工作的默认值
- 避免使用 LINQ,而是使用 QueryDefinition
从字符串构造查询
在 CosmosDb 中使用 DateTimeOffset 时存在问题。参考在 microsoft docs 上与他们合作的指南,它指出...
To convert a local DateTime to UTC, the offset must be known/stored as a property in the JSON and the client can use the offset to compute the UTC DateTime value.
所以我将我的日期以 "2021-04-23T12:15:00+01:00" 的格式存储在我的文档中。这在为本地用户查询和显示时效果很好。但是,我在对这些 DateTimes 执行查询时遇到问题...
在我的服务器上,我将执行这样的查询...
Linq 查询
.Where(x => x.ExpiresAt.UtcDateTime <= DateTime.UtcNow)
如果 expiresAt = "2021-04-23T12:15:00+01:00"
现在的 UTC 时间 = "2021-04-23T11:15:00+00:00"
然后我希望查询 return 一个项目。但是,直到一个小时后才 return 编辑任何项目,几乎就像 .UtcDateTime 扩展名不起作用一样。如果是这样,那么你如何比较这样的 DateTimeOffsets 呢?微软文档听起来好像您需要另一个字段来存储偏移量并且不能将其与日期时间本身内联使用。喜欢...
{
"expiresAt":"2021-04-23T11:15:00",
"expiresAtOffset":"1"
}
肯定是我误会了吧?
注意: 我试过使用 SQL 查询而不是像这样的 linq...
"SELECT * FROM c WHERE c.expiresAt <= \"2021-04-23T11:58:05\""
但仍然是同样的问题,因为问题是 cosmos 值是需要转换和查看的值 docs 无法将 cosmos 值转换为 UTC 时间...
另一个
var jsonSerializerSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffZ"
};
然后我在创建 DocumentClient 时添加了...
new DocumentClient(serviceEndpoint, authKey, serializerSettings: jsonSerializerSettings);
我唯一的问题是我有一些电子邮件需要从服务器发送,其中包含时间。这些时间不正确,因为服务器不知道如何将它们转换为客户端本地时间。
根据我的经验,这种组合可以通过 .NET 上的 Cosmos 和日期时间实现快乐:
- 将日期和时间建模为 docs 中建议的 ISO 8601 值
- 使用
DateTime
.NET 类型,而不是DateTimeOffset
- 确保完整的日期时间以准确的格式序列化
yyyy-MM-ddTHH:mm:ss.fffffffZ
- 始终存储 UTC 值,从不存储本地时间
- 如果值表示特定时区发生的事情,请将 IANA time zone 与值一起存储。然后在显示给用户之前使用它进行转换。
- 使用 .NET SDK 3 中基于流的方法 (sample) 和
System.Text.Json
直接控制序列化,并获得按预期工作的默认值 - 避免使用 LINQ,而是使用 QueryDefinition 从字符串构造查询