Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq连接和/或筛选日期时间评估?_C#_Linq - Fatal编程技术网

C# Linq连接和/或筛选日期时间评估?

C# Linq连接和/或筛选日期时间评估?,c#,linq,C#,Linq,我有一个时钟事件列表,问题是我不知道事件是打卡还是打卡。我的班级看起来像这样 private class TimeClock { public string EmployeeID { get; set; } public DateTime ShiftDate { get; set; } public DateTime TimeStamp { get; set; } } 给定一个具体的员工ID和轮班日期,我需要确定他们什么时候上班。这可以通过简单的

我有一个时钟事件列表,问题是我不知道事件是打卡还是打卡。我的班级看起来像这样

private class TimeClock
{
    public string EmployeeID { get; set; }
    public DateTime ShiftDate { get; set; }
    public DateTime TimeStamp { get; set; }
}
给定一个具体的员工ID和轮班日期,我需要确定他们什么时候上班。这可以通过简单的<评估来完成

var allShifts = (from p1 in punches
                 join p2 in punches 
                    on new { p1.EmployeeID, p1.ShiftDate } equals 
                       new { p2.EmployeeID, p2.ShiftDate }
                 where p1.TimeStamp < p2.TimeStamp
                 select new Shift
                 {
                      EmployeeID = p1.EmployeeID,
                      Hours = p2.TimeStamp.Subtract(p1.TimeStamp).TotalHours
                 }).ToList();
这很有效,但如果员工一天打卡打卡次数超过一次,显然会出现故障。在这种情况下,我希望看到返回两个班次,一个用于第一次打卡,另一个用于第二次打卡

我感谢你的帮助。
Derrick

您可以按员工和日期对穿孔进行分组。然后,您可以从每组中选择打孔对和打孔对,并计算总小时数:

 from p in punches
 group p by new { p.EmployeeID, p.ShiftDate } into g
 let punch = g.First()
 select new Shift
 {
      EmployeeID = punch.EmployeeID,
      FirstName = punch.FirstName,
      LastName = punch.LastName,
      TimeClockID = punch.TimeClockID,
      Hours = g.OrderBy(p => p.TimeStamp)
               .Select((p,i) => new {Punch = p, Index = i})
               .GroupBy(x => x.Index / 2)
               .Select(inOut => new {
                   PunchInTime = inOut.First().Punch.TimeStamp, 
                   PunchOutTime = inOut.Last().Punch.TimeStamp 
               })
               .Sum(x => x.PunchOutTime.Subtract(x.PunchInTime).TotalHours)
  }).ToList();
以下是选择输入输出对的工作原理

按时间戳显示当前日期的员工订单记录 在{punch,Index}对象上使用punch对象及其在穿孔有序列表中的索引投影每个穿孔组 按索引/2对这些对象进行分组,因此索引是一个整数,则此除法将为两个连续的穿孔生成相同的值,例如,对于索引0、1、2、3、4、5,您将有分组键值0、0、1、1、2、2 从每组两个穿孔计算总小时数的总和注意,inOut是两个匿名对象的分组{Punch,Index}
您可以按员工和日期对穿孔进行分组。然后,您可以从每组中选择打孔对和打孔对,并计算总小时数:

 from p in punches
 group p by new { p.EmployeeID, p.ShiftDate } into g
 let punch = g.First()
 select new Shift
 {
      EmployeeID = punch.EmployeeID,
      FirstName = punch.FirstName,
      LastName = punch.LastName,
      TimeClockID = punch.TimeClockID,
      Hours = g.OrderBy(p => p.TimeStamp)
               .Select((p,i) => new {Punch = p, Index = i})
               .GroupBy(x => x.Index / 2)
               .Select(inOut => new {
                   PunchInTime = inOut.First().Punch.TimeStamp, 
                   PunchOutTime = inOut.Last().Punch.TimeStamp 
               })
               .Sum(x => x.PunchOutTime.Subtract(x.PunchInTime).TotalHours)
  }).ToList();
以下是选择输入输出对的工作原理

按时间戳显示当前日期的员工订单记录 在{punch,Index}对象上使用punch对象及其在穿孔有序列表中的索引投影每个穿孔组 按索引/2对这些对象进行分组,因此索引是一个整数,则此除法将为两个连续的穿孔生成相同的值,例如,对于索引0、1、2、3、4、5,您将有分组键值0、0、1、1、2、2 从每组两个穿孔计算总小时数的总和注意,inOut是两个匿名对象的分组{Punch,Index}
如果您稍微调整了换档模式:

public class TimeClock
{
    public int EmployeeId { get; set; } 
    public int TimeClockId { get; set; }
    public DateTime TimeStamp { get; set; }
}

public class Shift
{
    public TimeClock PunchIn { get; set; }
    public TimeClock PunchOut { get; set; }
    public int EmployeeId { get; set; }

    public bool HasShiftEnded 
    { 
        get { return PunchIn != null && PunchOut != null; } 
    }

    public double? DurationInHours
    {
        get
        {
            if (HasShiftEnded)
                return (PunchOut.TimeStamp - PunchIn.TimeStamp).TotalHours;

            return null;
        }
    }
}
您可以使用以下LINQ查询:

var shifts = punches
    .Where (x => x.EmployeeId == 1 )
    .OrderBy (x => x.TimeStamp)
    .Select ((x, i) => new { Index = i, Punch = x })
    .GroupBy (x => x.Index / 2)
    .Select (x => x.Select (v => v.Punch))
    .Select (x => new Shift
    {
        EmployeeId = x.ElementAt(0).EmployeeId,
        PunchIn = x.ElementAt(0),
        PunchOut = x.ElementAtOrDefault(1)
    });
以下哪项功能:

按员工id或任何其他标准(如轮班日期)过滤穿孔。 按时间顺序排列筛选的项目 将此列表拆分为包含两个相邻项的多个列表。 对于两个项目的每个列表-创建一个新班次。未加盖PunchOut印章的班次不完整或正在进行中。
以下是一个您可以尝试的方法。

如果您稍微调整换档模式:

public class TimeClock
{
    public int EmployeeId { get; set; } 
    public int TimeClockId { get; set; }
    public DateTime TimeStamp { get; set; }
}

public class Shift
{
    public TimeClock PunchIn { get; set; }
    public TimeClock PunchOut { get; set; }
    public int EmployeeId { get; set; }

    public bool HasShiftEnded 
    { 
        get { return PunchIn != null && PunchOut != null; } 
    }

    public double? DurationInHours
    {
        get
        {
            if (HasShiftEnded)
                return (PunchOut.TimeStamp - PunchIn.TimeStamp).TotalHours;

            return null;
        }
    }
}
您可以使用以下LINQ查询:

var shifts = punches
    .Where (x => x.EmployeeId == 1 )
    .OrderBy (x => x.TimeStamp)
    .Select ((x, i) => new { Index = i, Punch = x })
    .GroupBy (x => x.Index / 2)
    .Select (x => x.Select (v => v.Punch))
    .Select (x => new Shift
    {
        EmployeeId = x.ElementAt(0).EmployeeId,
        PunchIn = x.ElementAt(0),
        PunchOut = x.ElementAtOrDefault(1)
    });
以下哪项功能:

按员工id或任何其他标准(如轮班日期)过滤穿孔。 按时间顺序排列筛选的项目 将此列表拆分为包含两个相邻项的多个列表。 对于两个项目的每个列表-创建一个新班次。未加盖PunchOut印章的班次不完整或正在进行中。
这是一个你可以试试的方法。

我想打孔机的时钟ID应该是递增的。所以最小的一个是第一个在拳,最大的一个是最后一个在拳@AmarDuplantier但OP需要计算总小时数每位员工是否有自己的计时器ID计数器?如果是,则带有奇数ID号的时钟是打卡,而偶数ID号表示打卡。编辑:没关系,看到你的编辑了。TimeClockID是时钟位置的物理指示器,我已经更新了代码,谢谢你到目前为止的想法。我想打孔机的TimeClockID的顺序应该是递增的。所以最小的一个是第一个在拳,最大的一个是最后一个在拳@AmarDuplantier但OP需要计算总小时数每位员工是否有自己的计时器ID计数器?如果是,则带有奇数ID号的时钟是打卡,而偶数ID号表示打卡。编辑:没关系,看到你的编辑了。TimeClockID是时钟位置的物理指示器,我已经更新了代码,谢谢你到目前为止的想法。谢谢你,这是一个巨大的帮助,肯定回答了我的问题。然而,在我的例子中,我简化了小时数的计算,因为我认为它不相关。实际上,它看起来更像Hours=getHoursp1.TimeStamp,p2。TimeStamp@FrumRoll请参见上次编辑:我使用打孔时间和打孔时间向匿名对象添加了投影。你可以调用你的函数,而不是在最后一步简单地减去那些值。你的最终编辑对我有用。小时数不是双倍的,所以我必须为Sum创建一个扩展方法,但它工作得很好。我可能不得不开始更频繁地在GroupBy中思考。再次感谢-德里克谢谢,这是一个巨大的帮助,当然回答了我的问题,因为它被问到。然而,在我的例子中,我简化了小时数的计算,因为我认为它不相关。实际上,它看起来更像Hours=getHoursp1.TimeStamp,p2。TimeStamp@FrumRoll请参见上次编辑:我使用打孔时间和打孔时间向匿名对象添加了投影。你可以打电话
l你的函数,而不是简单地减去最后一步的值。你的最终编辑对我有用。小时数不是双倍的,所以我必须为Sum创建一个扩展方法,但它工作得很好。我可能不得不开始更频繁地在GroupBy中思考。再次感谢-德里克