Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.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

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,我有一个时间表条目列表,通常每个用户在同一天会有多个条目,因为他们在午餐时间打卡进出 我的时间表课程如下所示: public class TimeSheetEntry { public Guid EmployeeId { get; set; } public DateTime ClockInTimeStamp { get; set; } public DateTime ClockOutTimeStamp { get; set; } } context.TimeSheet

我有一个时间表条目列表,通常每个用户在同一天会有多个条目,因为他们在午餐时间打卡进出

我的时间表课程如下所示:

public class TimeSheetEntry
{
    public Guid EmployeeId { get; set; }
    public DateTime ClockInTimeStamp { get; set; }
    public DateTime ClockOutTimeStamp { get; set; }
}
context.TimeSheetEntries.Select(e => e.ClockInTimeStamp.Date).Distinct();
我想确定用户工作的天数。我想通过计算我的
列表()
中的唯一天数,使用
ClockInTimeStamp
属性来完成此操作

如何使用LINQ获取此列表中的唯一天数?

.Distinct()可能就是您想要的。只需指定使用Distinct()对哪个属性进行筛选

.Distinct()可能就是您要查找的内容。只需指定使用Distinct()对哪个属性进行筛选


你是想严格计算日期而不考虑时间吗?如果是这样,您可能希望查看更改两个DateTime属性类型并使用库,它具有仅日期类型


鉴于您对我对您的OP的评论的回应,我强烈建议您远离DateTime,看看野田时间。

您是否希望严格计算日期,而不考虑时间?如果是这样,您可能希望查看更改两个DateTime属性类型并使用库,它具有仅日期类型

timesheetEntries
    .GroupBy( te => te.EmployeeId )
    .Select(
        grp => new {
            EmployeeId = grp.Key,
            DayCount = grp
                .Select( te => te.ClockInTimeStamp.Date )
                .Distinct()
                .Count()
        }
    )
    .ToDictionary(
        t => t.EmployeeId,
        t => t.DayCount
    );
考虑到你对我对你的评论的回应,我强烈建议你远离DateTime,看看Noda Time

timesheetEntries
    .GroupBy( te => te.EmployeeId )
    .Select(
        grp => new {
            EmployeeId = grp.Key,
            DayCount = grp
                .Select( te => te.ClockInTimeStamp.Date )
                .Distinct()
                .Count()
        }
    )
    .ToDictionary(
        t => t.EmployeeId,
        t => t.DayCount
    );
我意识到中间
Select
可以省略:

timesheetEntries
    .GroupBy( te => te.EmployeeId )
    .ToDictionary(
        grp => grp.Key /* EmployeeId */,
        grp => grp
            .Select( te => te.ClockInTimeStamp.Date )
            .Distinct()
            .Count()
    );
我意识到中间
Select
可以省略:

timesheetEntries
    .GroupBy( te => te.EmployeeId )
    .ToDictionary(
        grp => grp.Key /* EmployeeId */,
        grp => grp
            .Select( te => te.ClockInTimeStamp.Date )
            .Distinct()
            .Count()
    );

由于时间部分的原因,您可能无法区分日期时间。您应该能够通过以下方式获取
DateTime.Date
,从而实现这一点:

public class TimeSheetEntry
{
    public Guid EmployeeId { get; set; }
    public DateTime ClockInTimeStamp { get; set; }
    public DateTime ClockOutTimeStamp { get; set; }
}
context.TimeSheetEntries.Select(e => e.ClockInTimeStamp.Date).Distinct();

注意:如果这是通过EF直接从sql中提取LINQ,则“.Date”部分可能会有问题,因此您可能必须在该部分之前的某个时间强制集合枚举。

由于时间部分的原因,您可能无法区分日期时间。您应该能够通过以下方式获取
DateTime.Date
,从而实现这一点:

public class TimeSheetEntry
{
    public Guid EmployeeId { get; set; }
    public DateTime ClockInTimeStamp { get; set; }
    public DateTime ClockOutTimeStamp { get; set; }
}
context.TimeSheetEntries.Select(e => e.ClockInTimeStamp.Date).Distinct();

注意:如果这是通过EF直接从sql中提取LINQ,则您可能对“.Date”部分有一些问题,因此您可能必须在该部分之前的某个时间强制集合枚举。

有两个细节我在其他答案中没有说明:

  • 如果用户在某一天打卡上班,第二天打卡下班怎么办?那是两天
  • 如果用户在几天后打卡上班又打卡下班怎么办?我相信这不应该发生,但如果发生了呢?我确信您需要某种方法来确保员工不会在五天内守时,但返回错误结果的函数无法实现这一点。你可以在别的地方查一下
  • 出于这个原因,我建议从一个单独的函数开始,这样就可以使用各种输入对其进行单元测试。编写单元测试将允许您“伪造”各种条目组合,仔细考虑您想要的结果是什么,测试以确定函数是否输出您期望的结果,然后轻松地进行调试以找出它不输出的原因

    这里有一种方法。由于任何单独的日期都可能重复(给定日期可能有任意数量的时间戳),我只是将它们添加到一个
    HashSet
    中,这将消除重复

    然后,如果开始日期和结束日期之间至少有一整天,则循环遍历该范围内的日期并添加所有日期

    public static class TimeSheetCalculations
    {
        public static int CalculateDistinctDays(this IEnumerable<TimeSheetEntry> entries)
        {
            var uniqueDays = new HashSet<DateTime>();
            foreach (var entry in entries)
            {
                var clockInDate = entry.ClockInTimeStamp.Date;
                var clockOutDate = entry.ClockOutTimeStamp.Date;
                uniqueDays.Add(clockInDate);
                uniqueDays.Add(clockOutDate);
                var totalDays = (clockOutDate - clockInDate).TotalDays;
                if (totalDays < 2) continue;
                for (var x = 1; x < totalDays; x++)
                {
                    uniqueDays.Add(clockInDate.AddDays(x));
                }
            }
            return uniqueDays.Count;
        }
    }
    
    如果有人在1/1打孔,在1/5打孔,在1/5打孔,在1/6打孔,在1/7打孔,那就是7天,即使他们从来没有在1/2、1/3或1/4打孔

    单元测试确认了预期结果


    我要检查的另一个错误条件是确认打卡时间在打卡之后。但我不会在这里这么做。我会在其他地方验证该条目(您可能已经验证过了)。

    我在其他答案中没有看到两个细节:

  • 如果用户在某一天打卡上班,第二天打卡下班怎么办?那是两天
  • 如果用户在几天后打卡上班又打卡下班怎么办?我相信这不应该发生,但如果发生了呢?我确信您需要某种方法来确保员工不会在五天内守时,但返回错误结果的函数无法实现这一点。你可以在别的地方查一下
  • 出于这个原因,我建议从一个单独的函数开始,这样就可以使用各种输入对其进行单元测试。编写单元测试将允许您“伪造”各种条目组合,仔细考虑您想要的结果是什么,测试以确定函数是否输出您期望的结果,然后轻松地进行调试以找出它不输出的原因

    这里有一种方法。由于任何单独的日期都可能重复(给定日期可能有任意数量的时间戳),我只是将它们添加到一个
    HashSet
    中,这将消除重复

    然后,如果开始日期和结束日期之间至少有一整天,则循环遍历该范围内的日期并添加所有日期

    public static class TimeSheetCalculations
    {
        public static int CalculateDistinctDays(this IEnumerable<TimeSheetEntry> entries)
        {
            var uniqueDays = new HashSet<DateTime>();
            foreach (var entry in entries)
            {
                var clockInDate = entry.ClockInTimeStamp.Date;
                var clockOutDate = entry.ClockOutTimeStamp.Date;
                uniqueDays.Add(clockInDate);
                uniqueDays.Add(clockOutDate);
                var totalDays = (clockOutDate - clockInDate).TotalDays;
                if (totalDays < 2) continue;
                for (var x = 1; x < totalDays; x++)
                {
                    uniqueDays.Add(clockInDate.AddDays(x));
                }
            }
            return uniqueDays.Count;
        }
    }
    
    如果有人在1/1打孔,在1/5打孔,在1/5打孔,在1/6打孔,在1/7打孔,那就是7天,即使他们从来没有在1/2、1/3或1/4打孔

    单元测试确认了预期结果


    我要检查的另一个错误条件是确认打卡时间在打卡之后。但我不会在这里这么做。我会在其他地方验证该条目(您可能已经验证过了)。

    您尝试过什么?您看过
    Distinct
    linq方法吗?它是谷歌上最热门的“linq distinct”之一,我怀疑它可能对你有用……是的,我有,但它没有返回准确的结果。这可能是因为我处理的是
    DateTime
    ,而不仅仅是date。我现在通过转换我的
    DateTime再次尝试<