Entity Framework LINQ中DateTimeOffset日期匹配问题求助
解决DateTimeOffset跨时区日期匹配的LINQ to DB方案
我太懂你这个痛点了——之前用.Date或者TruncateTime的时候,完全没考虑时区转换,结果要么EF报错,要么筛出来的结果根本不对,尤其是跨多个时区存储数据的时候,这个问题特别头疼。
问题核心
你需要的是:把数据库里所有DateTimeOffset类型的数据,转换到指定参数的时区后,判断是否和参数的日期为同一天。之前的方法都是直接取本地日期(不带时区转换),自然会漏掉那些跨时区的有效数据。
正确的LINQ to DB实现方案
这里有两种可靠的写法,都能正确处理时区转换,而且LINQ to DB会把它们转换成对应的SQL(比如SQL Server的SWITCHOFFSET函数),不会出现客户端评估或者报错的问题:
方案1:转换到目标时区后比较日期
直接把每条数据的DateTimeOffset转换为参数的时区,再取日期和参数日期对比:
// 定义目标参数:+01:00时区的2018-11-15 DateTimeOffset parameter = new DateTimeOffset(2018, 11, 15, 0, 0, 0, TimeSpan.FromHours(1)); var results = from item in db.data // 将存储的DateTimeOffset转换到参数的时区 let convertedDate = item.DateTimeOffsetValue.ToOffset(parameter.Offset).Date // 对比转换后的日期是否和参数日期一致 where convertedDate == parameter.Date select item;
方案2:计算UTC范围进行匹配
另一种思路是把目标日期转换成UTC的时间范围,然后判断存储数据的UTC时间是否在这个范围内,这种写法在某些数据库上性能可能更好(如果有UTC相关的索引):
DateTimeOffset parameter = new DateTimeOffset(2018, 11, 15, 0, 0, 0, TimeSpan.FromHours(1)); // 计算目标时区当天的起始和结束(转换为UTC时间) DateTime targetUtcStart = parameter.Date.UtcDateTime; DateTime targetUtcEnd = parameter.Date.AddDays(1).UtcDateTime; var results = from item in db.data let utcValue = item.DateTimeOffsetValue.UtcDateTime where utcValue >= targetUtcStart && utcValue < targetUtcEnd select item;
为什么之前的方法不行?
.Date属性:EF/LINQ to DB里直接调用.Date不会自动进行时区转换,它只会取DateTimeOffset本地部分的日期,比如14.11.2018 22:00 +05:00的.Date是14号,但转换到+01:00时区后其实是15号,所以会被错误排除。TruncateTime:和.Date类似,只是截断时间部分,但同样没有处理时区转换,结果自然不对。
这两种方案都能正确匹配你例子里的有效数据:比如14.11.2018 22:00 +05:00转换到+01:00时区后是15.11.2018 00:00 +01:00,会被正确筛选出来;而不符合的比如14.11.2018 22:00 +01:00转换后还是14号,会被排除。
内容的提问来源于stack exchange,提问作者Osel Miko Dřevorubec
相关产品推荐
相关产品推荐

