员工时钟计算

时间:2016-05-21 10:31:05

标签: c# datetime time timespan

我希望有人能帮助我找到最佳解决方案。我有一份时间日志列表。它包含每位员工每天每个clockin的数据时间条目。

我正在努力想出一个很好的解决方案来计算每天的工作时间。一个员工每次进入和退出时间之间的时间间隔。

最终结果必须给我以下内容。

  • 工作总时间
  • 总时间
  • 每个日志/行之间用于提取和显示工作时间和超时的时间。

例如 时钟:06:00 ClockedOut:10:00 ClockedIn:10:15

BreakTime = 00:15

等等。

我试图避免对循环/ foreach循环使用很多。

这是代表时间日志列表的代码示例。类型是。 I =用于时钟输入和O =时钟输出。每个Shift都有一个块开始时间和块结束时间。

var blockStart = new TimeSpan(0,6,0,0,0);
var blockEnd = new TimeSpan(0,17,0,0);

var listOfTimeLogs = new List<TimeLog>()
        {
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,6,0,0),Type = "I"},
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,10,0,0),Type = "O"},
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,10,15,0),Type = "I"},
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,12,0,0),Type = "O"},
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,12,30,0),Type = "I"},
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,15,0,0),Type = "O"},
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,15,15,0),Type = "I"},
            new TimeLog() {EntryDateTime = new DateTime(2016,05,20,18,00,0),Type = "O"}
        };

希望这是有道理的。任何帮助将不胜感激。 谢谢

1 个答案:

答案 0 :(得分:1)

使计算机做循环。

以下是我将如何处理问题的sample

<强> Program.cs的

using System;
using System.Collections.Generic;
using System.Linq;

namespace TimeClock
{
    class Program
    {
        static void Main()
        {
            var blockStart = new TimeSpan(0, 6, 0, 0);
            var blockEnd = new TimeSpan(0, 17, 0, 0);

            var listOfTimeLogs = new List<TimeLog>
            {
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,6,0,0),EntryType = EntryTypes.In},
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,10,0,0),EntryType = EntryTypes.Out},
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,10,15,0),EntryType = EntryTypes.In},
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,12,0,0),EntryType = EntryTypes.Out},
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,12,30,0),EntryType = EntryTypes.In},
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,15,0,0),EntryType = EntryTypes.Out},
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,15,15,0),EntryType = EntryTypes.In},
                new TimeLog {EntryDateTime = new DateTime(2016,05,20,18,00,0),EntryType = EntryTypes.Out}
            };


            // You are going to have have for / for each unless you use Linq

            // fist I would count clock in's versus the out's
            var totalIn = listOfTimeLogs.Count(e => e.EntryType == EntryTypes.In);
            var totalOut = listOfTimeLogs.Count() - totalIn;

            // check if we have in the number of time entries
            if (totalIn > totalOut)
            {
                Console.WriteLine("Employee didn't clock out");
            }

            // as I was coding this sample program, i thought of another way to store the time
            // I would store them in blocks - we have to loop
            var timeBlocks = new List<TimeBlock>();
            for (var x = 0; x < listOfTimeLogs.Count; x += 2)
            {
                // create a new WORKING block based on the in/out time entries
                timeBlocks.Add(new TimeBlock
                {
                    BlockType = BlockTypes.Working,
                    In = listOfTimeLogs[x],
                    Out = listOfTimeLogs[x + 1]
                });

                // create a BREAK block based on gaps
                // check if the next entry in a clock in
                var breakOut = x + 2;
                if (breakOut < listOfTimeLogs.Count)
                {
                    var breakIn = x + 1;
                    // create a new BREAK block
                    timeBlocks.Add(new TimeBlock
                    {
                        BlockType = BlockTypes.Break,
                        In = listOfTimeLogs[breakIn],
                        Out = listOfTimeLogs[breakOut]
                    });
                }
            }

            var breakCount = 0;
            // here is a loop for displaying detail
            foreach (var block in timeBlocks)
            {
                var lineTitle = block.BlockType.ToString();
                // this is me trying to be fancy
                if (block.BlockType == BlockTypes.Break)
                {
                    if (block.IsBreak())
                    {
                        lineTitle = $"Break #{++breakCount}";
                    }
                    else
                    {
                        lineTitle = "Lunch";
                    }
                }
                Console.WriteLine($" {lineTitle,-10} {block}  ===  Length: {block.Duration.ToString(@"hh\:mm")}");
            }

            // calculating total time for each block type
            var workingTime = timeBlocks.Where(b => b.BlockType == BlockTypes.Working)
                    .Aggregate(new TimeSpan(0), (p, v) => p.Add(v.Duration));

            var breakTime = timeBlocks.Where(b => b.BlockType == BlockTypes.Break)
                    .Aggregate(new TimeSpan(0), (p, v) => p.Add(v.Duration));


            Console.WriteLine($"\nTotal Working Hours: {workingTime.ToString(@"hh\:mm")}");
            Console.WriteLine($"   Total Break Time: {breakTime.ToString(@"hh\:mm")}");

            Console.ReadLine();
        }
    }
}

<强> TimeBlock.cs

using System;

namespace TimeClock
{
    public enum BlockTypes
    {
        Working,
        Break
    }

    public class TimeBlock
    {
        public BlockTypes BlockType;
        public TimeLog In;
        public TimeLog Out;

        public TimeSpan Duration
        {
            get
            {
                // TODO: Need error checking
                return Out.EntryDateTime.Subtract(In.EntryDateTime);
            }
        }

        public override string ToString()
        {
            return $"In: {In.EntryDateTime:HH:mm} - Out: {Out.EntryDateTime:HH:mm}";
        }

    }

    // a little extension class
    public static class Extensions
    {
        public static bool IsBreak(this TimeBlock block)
        {
            // if the length of the break period is less than 19 minutes
            // we will consider it a break, the person could have clock IN late
            return block.Duration.TotalMinutes < 19 ? true : false;

        }

    }

}

<强> TimeLog.cs

using System;

namespace TimeClock
{
    public class TimeLog
    {
        public DateTime EntryDateTime;
        public EntryTypes EntryType;
    }
}

<强> EntryTypes.cs

namespace TimeClock
{
    public enum EntryTypes
    {
        In,
        Out
    }
}

Output of Program