使用linq根据日期集合获取第二天的第一次输入和最后一次输出

本文关键字:第一次 输入 输出 最后一次 第二天 获取 linq 日期 集合 使用 | 更新日期: 2023-09-27 17:58:49

当生物识别读数超过第二天用户超时时,我在获取结构化的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)},

有什么变通方法或建议吗??

使用linq根据日期集合获取第二天的第一次输入和最后一次输出

    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();