当生物识别读数超过第二天用户超时时,我在获取结构化的First Entry和Last Entry时遇到问题。但如果时间在同一天,我可以按照我想要的方式格式化。。
这是我的代码:
IEnumerable<biometric> dtrs = new List<biometric>()
{
new biometric{Id = 1, InOut = 0, DateTime = new DateTime(2013,5,5,8,0,0)},
new biometric{Id = 2, InOut = 0, DateTime = new DateTime(2013,5,5,8,0,5)},
new biometric{Id = 3, InOut = 0, DateTime = new DateTime(2013,5,5,8,1,0)},
new biometric{Id = 4, InOut = 0, DateTime = new DateTime(2013,5,5,8,2,0)},
//here is my problem getting this paired to
new biometric{Id = 5, InOut = 0, DateTime = new DateTime(2013,5,5,18,0,0)},
new biometric{Id = 1, InOut = 1, DateTime = new DateTime(2013,5,5,18,0,0)},
new biometric{Id = 2, InOut = 1, DateTime = new DateTime(2013,5,5,17,5,5)},
new biometric{Id = 3, InOut = 1, DateTime = new DateTime(2013,5,5,17,5,10)},
new biometric{Id = 4, InOut = 1, DateTime = new DateTime(2013,5,5,17,10,0)},
//this Entry here
new biometric{Id = 5, InOut = 1, DateTime = new DateTime(2013,5,6,3,0,0)},
};
var asd = dtrs.GroupBy(x => new { x.Id, x.DateTime.Date }, (key, group) => new
{
Key1 = key.Date,
Key2 = key.Id,
Result = group.OrderBy(a => a.DateTime).ToList()
})
//checks if the grouping result has one timein and 1 timeout or more
.Where(a => a.Result.Where(z => z.InOut == 1).Count() >= 1 && a.Result.Where(z => z.InOut == 0).Count() >= 1)
.Select(a => new dtr() { employeeId = a.Key2, TimeIn = a.Result.FirstOrDefault(b => b.InOut == 1).DateTime, TimeOut = a.Result.LastOrDefault(c => c.InOut == 0).DateTime });
private class biometric
{
public int Id { get; set; }
public DateTime DateTime { get; set; }
public int InOut { get; set; }
}
private class dtr
{
public int employeeId { get; set; }
public DateTime TimeIn { get; set; }
public DateTime TimeOut { get; set; }
}
我想配对
新的生物特征{Id=5,InOut=0,DateTime=新的DateTime(2013,5,5,18,0,0)},
到此
新的生物特征{Id=5,InOut=1,DateTime=新的DateTime(2013,5,6,3,0,0)},
有什么变通方法或建议吗??
var asd3 = from d1 in dtrs
join d2 in dtrs on d1.Id equals d2.Id
where d1.InOut ==0
&& d2.InOut == 1
&& d2.DateTime > d1.DateTime
&& d2.DateTime.AddHours(-18) < d1.DateTime
orderby d1.DateTime.Date, d1.Id
select new dtr {employeeId = d1.Id,
TimeIn=d1.DateTime,
TimeOut= d2.DateTime};
我添加了第二天的数据,以确保过滤是正确的。这是假设没有人一天工作超过18个小时。假设大多数人的标准工作时间为8小时,那么这一数字可能高达31小时。
employeeId TimeIn TimeOut
1 05/05/2013 08:00:00.000 05/05/2013 18:00:00.000
2 05/05/2013 08:00:05.000 05/05/2013 17:05:05.000
3 05/05/2013 08:01:00.000 05/05/2013 17:05:10.000
4 05/05/2013 08:02:00.000 05/05/2013 17:10:00.000
5 05/05/2013 18:00:00.000 05/06/2013 03:00:00.000
1 05/06/2013 08:00:00.000 05/06/2013 18:00:00.000
2 05/06/2013 08:00:05.000 05/06/2013 17:05:05.000
3 05/06/2013 08:01:00.000 05/06/2013 17:05:10.000
4 05/06/2013 08:02:00.000 05/06/2013 17:10:00.000
5 05/06/2013 18:00:00.000 05/07/2013 03:00:00.000
此外,附带说明一下,您的原始代码包含a.Result.Where(z => z.InOut == 1).Count() >= 1
。这可以简化为a.Result.Any(z => z.InOut == 1)
;更容易阅读,可能会执行得更快。
更新:添加这两条记录(员工1去吃午饭)
new biometric{Id = 1, InOut = 1, DateTime = new DateTime(2013,5,5,12,0,0)},
new biometric{Id = 1, InOut = 0, DateTime = new DateTime(2013,5,5,13,0,1)},
var sorted = dtrs.OrderBy (d =>d.Id).ThenBy (d =>d.DateTime ).ToList();
var zipped = sorted.Where (d =>d.InOut==0 ).Zip(sorted.Where (s =>s.InOut==1),
(i,o)=>{
Debug.Assert(i.Id == o.Id);
return new dtr
{
employeeId = i.Id,
TimeIn=i.DateTime,
TimeOut= o.DateTime
};
}).OrderBy (d =>d.TimeIn);
zipped.Dump();