c# - 如何将linq c#中日期之间的期间相加到特定期间
问题描述
我有一个包含三列的数据表,我需要通过 LINQ 查询减去和求和差值Date1
来检查每个员工 ID 何时达到两年或将达到两年。Date2
如果Date2
value 为 null,则表示ID
到目前为止仍在工作。
ID Date1 Date2
> 100 10/01/2016 09/01/2017
> 100 20/09/2017 25/05/2019
> 101 05/07/2018
我需要如下输出:
ID two_years
> 100 19/09/2018
> 101 04/07/2020
解决方案
Using my Scan
extension which is based on the APL Scan operator (like Aggregate
, only it returns the intermediate results):
public static class IEnumerableExt {
// TRes seedFn(T FirstValue)
// TRes combineFn(TRes PrevResult, T CurValue)
public static IEnumerable<TRes> Scan<T, TRes>(this IEnumerable<T> src, Func<T, TRes> seedFn, Func<TRes, T, TRes> combineFn) {
using (var srce = src.GetEnumerator()) {
if (srce.MoveNext()) {
var prev = seedFn(srce.Current);
while (srce.MoveNext()) {
yield return prev;
prev = combineFn(prev, srce.Current);
}
yield return prev;
}
}
}
}
Then assuming by two years, you mean 2 * 365 days, and assuming you count the beginning and ending dates of each period as part of the total, this LINQ will find the answer:
var ans = src.Select(s => new { s.ID, s.Date1, s.Date2, Diff = (s.Date2.HasValue ? s.Date2.Value-s.Date1 : DateTime.Now.Date-s.Date1).TotalDays+1 })
.GroupBy(s => s.ID)
.Select(sg => new { ID = sg.Key, sg = sg.Scan(s => new { s.Date1, s.Date2, s.Diff, DiffAccum = s.Diff }, (res, s) => new { s.Date1, s.Date2, s.Diff, DiffAccum = res.DiffAccum + s.Diff }) })
.Select(IDsg => new { IDsg.ID, two_year_base = IDsg.sg.FirstOrDefault(s => s.DiffAccum > twoYears) ?? IDsg.sg.Last() })
.Select(s => new { s.ID, two_years = s.two_year_base.Date1.AddDays(twoYears-(s.two_year_base.DiffAccum - s.two_year_base.Diff)).Date });
If your original data is not sorted in Date1
order, or ID
+Date1
order, you will need to add OrderBy
to sort by Date1
.
Explanation:
First we compute the days worked(?) represented by each row, using today if we don't have an ending Date2
. Then group by ID and work on each group. For each ID, we compute the running sum of days worked. Next find the Date1
that proceeds the two year mark using the running sum (DiffAccum
) and compute the two year date from Date1
and the remaining time needed in that period.
If it is possible a particular ID could have a lot of periods, you could use another variation of Scan
, ScanUntil
which short circuits evaluation based on a predicate.
推荐阅读
- python-3.x - 如何使用python从字符串中仅检查和提取数字
- java - 如何确定数组的合法索引范围?
- jquery - 如何选择可见的复选框?
- r - 在 R 中编写自己的逻辑回归函数:如何处理序数数据
- rust - 我可以在返回永不类型(!)的发散函数中使用问号运算符(?)吗?
- angular - chrome和IE中的复选框选择
- angular - 行为主体行为不正常?
- google-chrome-extension - 加载解压后的扩展,但它不起作用
- javascript - 表示不使用绝对路径加载图像
- html - 我使用“npm run dev”命令运行的 webpack-simple 项目无法在真实服务器上运行