我希望有人能帮助我找到最佳解决方案。我有一份时间日志列表。它包含每位员工每天每个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"}
};
希望这是有道理的。任何帮助将不胜感激。 谢谢
答案 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
}
}