如何判断时间是否在一组范围内?

5
我正在创建一款考勤应用程序,我正在寻找一种方法来检查员工的出勤记录是否在他们计划的时间内一个小时之内。
假设员工1的计划是2019年1月31日@ 00:30,但他提前到达并且在记录中签到,因此他的记录显示他在2019年1月30日@ 23:45签到。所以我正在尝试找到如果员工在计划时间的前一个小时或后一个小时内登录,则该时间将作为他的登录时间。例如他可以在2019年1月30日23:30至2019年1月31日01:30之间登录。
目前我有4个DateTime变量来处理这些,但似乎不起作用。
以下是我的Employee类:
public class Emp1
    {
        public int ID { get; set; }
        public DateTime In { get; set; }
        public DateTime Out { get; set; }
        public DateTime dateTime1 { get; set; }
        public DateTime dateTime2 { get; set; }
        public DateTime dateTime3 { get; set; }
        public DateTime dateTime4 { get; set; }
    }

我的实际出勤日志课程

public class Actual
    {
        public int ID { get; set; }
        public DateTime ActualLog { get; set; }
        public int LogStatus { get; set; }
        public DateTime date { get; set; }
    }

所以这是我填充员工时间表的代码:
List<Emp1> em = new List<Emp1>();

                foreach (DataRow row in empContainer.Rows)
                {
                    em.Add(new Emp1()
                    {
                        ID = Convert.ToInt32(row[0].ToString()),
                        In = Convert.ToDateTime(row[1].ToString()),
                        Out = Convert.ToDateTime(row[2].ToString()),
                        dateTime1 = Convert.ToDateTime(row[1].ToString()).AddHours(1),
                        dateTime2 = Convert.ToDateTime(row[1].ToString()).AddHours(-1),
                        dateTime3 = Convert.ToDateTime(row[2].ToString()).AddHours(1),
                        dateTime4 = Convert.ToDateTime(row[2].ToString()).AddHours(-1)
                    });
                }

这是我当前用来填充数据网格的LINQ语句。
public void Main()
        {
            List<Emp1> emps;
            List<Actual> actuals;

            actuals = emp.GetActual(@"C:\Users\IT\Desktop\Sample\SampleActual.dat");
            emps = GetEmpSched();



            var final = (from a1 in actuals
                         join a2 in actuals on a1.ID equals a2.ID
                         join t1 in emps on a1.ID equals t1.ID
                         join t2 in emps on a2.ID equals t2.ID
                         where ((a1.LogStatus == 0) && (a2.LogStatus == 1)) && ((t1.In == t2.In) && (t1.Out==t2.Out)) && ((t1.dateTime1 > a1.ActualLog) && (a1.ActualLog > t1.dateTime2)) && ((t2.dateTime3 > a2.ActualLog) && (a2.ActualLog > t2.dateTime4))
                         select new
                         {
                             User_ID = t1.ID,
                             Scheduled_In = t1.In,
                             Actual_Login = a1.ActualLog,
                             Scheduled_Out = t2.Out,
                             Actual_Out = a2.ActualLog
                         }).Distinct(). ToList();

            tbContainer = StaticClasses.ToDataTable(final);

            dgvAttendance.ItemsSource = emp.CalculateEmployeeAttendance(tbContainer);
        }

这是我的员工排班表:

Employee Schedule

这是我的员工考勤记录:

Attendance Logs

如您所见,我添加了4个额外的DateTime变量来处理额外或减少的工作小时数,但仍然无法正常工作,而我不知道为什么。
这是当前的输出:

Actual Output

所以因为我的条件,我缺少一些数据,这应该可以正常工作,但却产生错误的输出。
有什么想法吗?
任何能帮助我的答案都将是极好的。谢谢!

@AndreiDragotoniu 初学者的错误,正如我所说,我的预期输出是要检查员工计划班次前后一小时内是否有考勤记录。我的主要问题是当员工在午夜后30分钟有一个计划班次并且他提前打卡时,它不会注册。这就是为什么我使用AddHours函数的原因。 - Nate
1
我猜他使用了.ToString(),因为DataRow的索引返回一个对象。也许更聪明的做法是使用其他机制来访问单元格数据。比如:Field扩展。 不管怎样,这不是问题所在。 你真的想用一次选择处理这种数据吗?我猜顺序处理可以给你更多的空间。 - sac1
@newboooooo,据我所见,你的代码背后没有数据库引擎,所以一切都将在你的可执行文件中完成。它不会被编译为SQL或任何其他查询语言,如EF。这就是为什么我问你关于顺序的原因。因为你需要所有数据,而且你已经解析了所有数据。没有 - 或者不是主要的 - 性能问题。 - sac1
@sac1 是的,这将只是即时处理。 - Nate
让我们在聊天中继续这个讨论 - sac1
显示剩余6条评论
1个回答

1
我认为你正在走一条艰难的路,这应该更简单。
要比较实际登录时间和计划时间,并检查是否在一小时内,只需相减并检查差异即可。
使用c#很容易:
    var scheduledLogIn = new TimeSpan(8, 0, 0);
    var actualLogIn = new DateTime(2019, 1, 31, 8, 15, 27);

    var delay = (actualLogIn.TimeOfDay - scheduledLogIn).Duration();

    if (delay.TotalHours < 1)
    {
        // It's ok
    } else
    {
        // more than 1h earlier or late!
    }

如果您想检查时间是否早于或晚于实际时间,请删除 Duration 并检查 TotalHours 是否为负数/正数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接