【问题标题】:Linq query summing dates in rangeLinq查询范围内的求和日期
【发布时间】:2011-02-09 16:57:57
【问题描述】:

尝试确定是否有一种很好的方法来做到这一点,最好是在 Linq 中而不是循环中,这就是我现在所做的。

我想要我的产品在两个日期之间有效的天数。

Product 有很多 ProductHistory,ProductHistory 有 DateActive 和 DateInactive 的值。 DateInactive 可以为空,并且通常会为空,以表明此历史记录正在进行中。历史不会重叠。

我想将我的 startDate 或 ProductHistory 的 DateActive 的最大值相加,然后从 endDate 或 ProductHistory 的 DateInactive 的最小值之和中减去该总数(如果 DateInactive 没有值,则默认为 endDate)。

工作示例:

获取 2011-01-01(1 月 1 日)和 2011-02-01(2 月 1 日)之间的活跃天数

历史:

Active 2010-12-25 : Inactive 2011-01-05
Active 2011-01-15 : Inactive 2011-01-20
Active 2011-01-25 : Inactive null

这应该总共 16 天 (4 + 5 + 7)

我目前最好的是相当丑陋的:

    Dim a As Integer = (From h In histories
            Select If(h.ActiveDate > startDate, h.ActiveDate, startDate)).Sum(Function(d) d.Ticks) / TimeSpan.TicksPerDay

    Dim b As Integer = (From h In histories
            Select If(h.InactiveDate.HasValue AndAlso h.InactiveDate < endDate, h.InactiveDate, endDate)).Sum(Function(d) d.Value.Ticks) / TimeSpan.TicksPerDay

Return b - a

有什么想法吗? (C#或者VB都可以,我会翻译)

【问题讨论】:

    标签: c# vb.net linq datetime


    【解决方案1】:

    这样的? (假设没有重叠的历史)

    var numDays = product
                 .ProductHistories
                 .Where(ph => ph.Active >= start && ph.Active < end)
                 .Sum(ph => ph.Active
                              .Subtract(end > ph.Inactive ? ph.Inactive.Value : end)
                              .Duration() // because we are doing start - end
                              .Days);
    
    1. 仅考虑在日期范围内开始的历史记录。
    2. 对于每个历史记录,将时间跨度构造为活动日期与非活动日期和结束日期的较早日期之间的增量。
    3. 总结一下。

    为了改善这一点,我建议:

    1. 编写一个 IsBetween 扩展,让您可以将 where lambda 写为 ph.Active.IsBetween(start, end)
    2. 将 sum lambda 提取到不同的方法中,并更直观地编写它。在DateTime? 上使用了“提升”运算符,许多人会觉得这很不直观。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-23
      • 1970-01-01
      • 2016-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多